mirror of
https://github.com/logos-co/logos-cpp-sdk.git
synced 2026-08-31 01:31:10 +00:00
Fix binary payloads in cdylib events (#100)
This commit is contained in:
@@ -76,6 +76,29 @@ QString stdReturnToJson(const MethodDecl& md, const QString& var)
|
||||
return "nlohmann::json(" + var + ")";
|
||||
}
|
||||
|
||||
void emitBytesEncodeHelpers(QTextStream& s)
|
||||
{
|
||||
s << "// Canonical tagged bytes form {\"_bytes\": base64url} (see logos_protocol.h)\n";
|
||||
s << "std::string lidlB64UrlEncode(const std::vector<uint8_t>& bytes)\n{\n";
|
||||
s << " static const char* alpha = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n";
|
||||
s << " std::string out;\n";
|
||||
s << " size_t i = 0;\n";
|
||||
s << " while (i + 3 <= bytes.size()) {\n";
|
||||
s << " uint32_t n = (uint32_t(bytes[i]) << 16) | (uint32_t(bytes[i+1]) << 8) | uint32_t(bytes[i+2]);\n";
|
||||
s << " out += alpha[(n >> 18) & 0x3f]; out += alpha[(n >> 12) & 0x3f];\n";
|
||||
s << " out += alpha[(n >> 6) & 0x3f]; out += alpha[n & 0x3f];\n";
|
||||
s << " i += 3;\n }\n";
|
||||
s << " if (i < bytes.size()) {\n";
|
||||
s << " uint32_t n = uint32_t(bytes[i]) << 16;\n";
|
||||
s << " if (i + 1 < bytes.size()) n |= uint32_t(bytes[i+1]) << 8;\n";
|
||||
s << " out += alpha[(n >> 18) & 0x3f]; out += alpha[(n >> 12) & 0x3f];\n";
|
||||
s << " if (i + 1 < bytes.size()) out += alpha[(n >> 6) & 0x3f];\n";
|
||||
s << " }\n return out;\n}\n\n";
|
||||
|
||||
s << "nlohmann::json lidlBytesToJson(const std::vector<uint8_t>& bytes)\n{\n";
|
||||
s << " return nlohmann::json{{\"_bytes\", lidlB64UrlEncode(bytes)}};\n}\n\n";
|
||||
}
|
||||
|
||||
void emitInterfaceJson(QTextStream& s, const ModuleDecl& module)
|
||||
{
|
||||
s << "static nlohmann::json lidlInterfaceJson()\n{\n";
|
||||
@@ -228,22 +251,7 @@ QString lidlMakeModuleImplExports(const ModuleDecl& module,
|
||||
s << " if (out) std::memcpy(out, str.data(), str.size() + 1);\n";
|
||||
s << " return out;\n}\n\n";
|
||||
|
||||
s << "// Canonical tagged bytes form {\"_bytes\": base64url} (see logos_protocol.h)\n";
|
||||
s << "std::string lidlB64UrlEncode(const std::vector<uint8_t>& bytes)\n{\n";
|
||||
s << " static const char* alpha = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_\";\n";
|
||||
s << " std::string out;\n";
|
||||
s << " size_t i = 0;\n";
|
||||
s << " while (i + 3 <= bytes.size()) {\n";
|
||||
s << " uint32_t n = (uint32_t(bytes[i]) << 16) | (uint32_t(bytes[i+1]) << 8) | uint32_t(bytes[i+2]);\n";
|
||||
s << " out += alpha[(n >> 18) & 0x3f]; out += alpha[(n >> 12) & 0x3f];\n";
|
||||
s << " out += alpha[(n >> 6) & 0x3f]; out += alpha[n & 0x3f];\n";
|
||||
s << " i += 3;\n }\n";
|
||||
s << " if (i < bytes.size()) {\n";
|
||||
s << " uint32_t n = uint32_t(bytes[i]) << 16;\n";
|
||||
s << " if (i + 1 < bytes.size()) n |= uint32_t(bytes[i+1]) << 8;\n";
|
||||
s << " out += alpha[(n >> 18) & 0x3f]; out += alpha[(n >> 12) & 0x3f];\n";
|
||||
s << " if (i + 1 < bytes.size()) out += alpha[(n >> 6) & 0x3f];\n";
|
||||
s << " }\n return out;\n}\n\n";
|
||||
emitBytesEncodeHelpers(s);
|
||||
|
||||
s << "int lidlB64Idx(char ch)\n{\n";
|
||||
s << " if (ch >= 'A' && ch <= 'Z') return ch - 'A';\n";
|
||||
@@ -300,9 +308,6 @@ QString lidlMakeModuleImplExports(const ModuleDecl& module,
|
||||
s << " out.push_back((n >> 8) & 0xff);\n";
|
||||
s << " }\n }\n return out;\n}\n\n";
|
||||
|
||||
s << "nlohmann::json lidlBytesToJson(const std::vector<uint8_t>& bytes)\n{\n";
|
||||
s << " return nlohmann::json{{\"_bytes\", lidlB64UrlEncode(bytes)}};\n}\n\n";
|
||||
|
||||
s << "nlohmann::json lidlResultToJson(const StdLogosResult& r)\n{\n";
|
||||
s << " nlohmann::json obj;\n";
|
||||
s << " obj[\"success\"] = r.success;\n";
|
||||
@@ -476,6 +481,12 @@ QString lidlMakeEventsSourceCdylib(const ModuleDecl& module,
|
||||
s << "// (the export wrapper forwards to the host's emit callback).\n";
|
||||
s << "#include \"" << implHeader << "\"\n";
|
||||
s << "#include <nlohmann/json.hpp>\n\n";
|
||||
s << "#include <cstdint>\n";
|
||||
s << "#include <string>\n";
|
||||
s << "#include <vector>\n\n";
|
||||
s << "namespace {\n\n";
|
||||
emitBytesEncodeHelpers(s);
|
||||
s << "} // namespace\n\n";
|
||||
|
||||
for (const EventDecl& ed : module.events) {
|
||||
s << "void " << implClass << "::" << ed.name << "(";
|
||||
@@ -491,7 +502,7 @@ QString lidlMakeEventsSourceCdylib(const ModuleDecl& module,
|
||||
s << " nlohmann::json args = nlohmann::json::array();\n";
|
||||
for (const ParamDecl& pd : ed.params) {
|
||||
if (pd.type.kind == TypeExpr::Primitive && pd.type.name == "bstr")
|
||||
s << " args.push_back(nlohmann::json{{\"_bytes\", \"\"}}); // bstr events: encode upstream\n";
|
||||
s << " args.push_back(lidlBytesToJson(" << pd.name << "));\n";
|
||||
else
|
||||
s << " args.push_back(" << pd.name << ");\n";
|
||||
}
|
||||
@@ -500,4 +511,3 @@ QString lidlMakeEventsSourceCdylib(const ModuleDecl& module,
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ add_executable(experimental_tests
|
||||
|
||||
# Code generation tests
|
||||
test_lidl_gen_client.cpp
|
||||
test_lidl_gen_cdylib.cpp
|
||||
|
||||
# Impl header parser tests
|
||||
test_impl_header_parser.cpp
|
||||
@@ -18,6 +19,7 @@ add_executable(experimental_tests
|
||||
# Sources under test
|
||||
${EXPERIMENTAL_SRC_DIR}/lidl_emit_common.cpp
|
||||
${EXPERIMENTAL_SRC_DIR}/lidl_gen_client.cpp
|
||||
${EXPERIMENTAL_SRC_DIR}/lidl_gen_cdylib.cpp
|
||||
${EXPERIMENTAL_SRC_DIR}/impl_header_parser.cpp
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "lidl_gen_cdylib.h"
|
||||
|
||||
TEST(LidlGenCdylib, BinaryEventPayloadUsesCanonicalBytesEncoding)
|
||||
{
|
||||
ModuleDecl module;
|
||||
module.name = "delivery_module";
|
||||
|
||||
EventDecl event;
|
||||
event.name = "messageReceived";
|
||||
|
||||
ParamDecl payload;
|
||||
payload.name = "payload";
|
||||
payload.type = {TypeExpr::Primitive, "bstr", {}};
|
||||
event.params.push_back(payload);
|
||||
module.events.push_back(event);
|
||||
|
||||
const QString source = lidlMakeEventsSourceCdylib(
|
||||
module,
|
||||
"DeliveryModuleImpl",
|
||||
"delivery_module_plugin.h");
|
||||
|
||||
EXPECT_TRUE(source.contains("args.push_back(lidlBytesToJson(payload));"));
|
||||
EXPECT_TRUE(source.contains("std::string lidlB64UrlEncode"));
|
||||
EXPECT_TRUE(source.contains("nlohmann::json lidlBytesToJson"));
|
||||
EXPECT_FALSE(source.contains("nlohmann::json{{\"_bytes\", \"\"}}"));
|
||||
}
|
||||
Reference in New Issue
Block a user