Decode request maps directly into Wasm workspaces
This commit is contained in:
+43
-14
@@ -921,11 +921,11 @@ bool ucb_append_varint(String& out, u64 value)
|
||||
return(true);
|
||||
}
|
||||
|
||||
bool ucb_read_varint(const String& src, size_t& offset, u64& value_out)
|
||||
bool ucb_read_varint(const char* src, size_t src_size, size_t& offset, u64& value_out)
|
||||
{
|
||||
value_out = 0;
|
||||
u32 shift = 0;
|
||||
while(offset < src.size() && shift <= 63)
|
||||
while(offset < src_size && shift <= 63)
|
||||
{
|
||||
u8 byte = (u8)src[offset++];
|
||||
value_out |= ((u64)(byte & 0x7f) << shift);
|
||||
@@ -936,6 +936,11 @@ bool ucb_read_varint(const String& src, size_t& offset, u64& value_out)
|
||||
return(false);
|
||||
}
|
||||
|
||||
bool ucb_read_varint(const String& src, size_t& offset, u64& value_out)
|
||||
{
|
||||
return(ucb_read_varint(src.data(), src.size(), offset, value_out));
|
||||
}
|
||||
|
||||
char ucb_node_type(const DValue& value)
|
||||
{
|
||||
const DValue& target = value.deref();
|
||||
@@ -1149,6 +1154,30 @@ String ucb_encode(const DValue& value)
|
||||
return(out);
|
||||
}
|
||||
|
||||
// Internal request/config transport uses the same UCEB2 map representation
|
||||
// without first building a duplicate DValue tree.
|
||||
String ucb_encode_flat_string_map(const StringMap& value)
|
||||
{
|
||||
String out;
|
||||
out.append(UCEB_MAGIC, 4);
|
||||
out.push_back((char)UCEB_VERSION);
|
||||
out.push_back(0);
|
||||
out.push_back('M');
|
||||
ucb_append_varint(out, 0);
|
||||
ucb_append_varint(out, value.size());
|
||||
for(auto& child : value)
|
||||
{
|
||||
ucb_append_varint(out, child.first.size());
|
||||
out.append(child.first.data(), child.first.size());
|
||||
out.push_back(0);
|
||||
out.push_back('S');
|
||||
ucb_append_varint(out, child.second.size());
|
||||
out.append(child.second.data(), child.second.size());
|
||||
ucb_append_varint(out, 0);
|
||||
}
|
||||
return(out);
|
||||
}
|
||||
|
||||
bool ucb_decode(const String& encoded, DValue& out, String* error_out)
|
||||
{
|
||||
String error;
|
||||
@@ -1176,7 +1205,7 @@ bool ucb_decode(const String& encoded, DValue& out, String* error_out)
|
||||
}
|
||||
|
||||
#ifdef __UCE_WASM_CORE__
|
||||
static bool ucb_decode_flat_string_map(const String& encoded, StringMap& out, String* error_out)
|
||||
static bool ucb_decode_flat_string_map(const char* encoded, size_t encoded_size, StringMap& out, String* error_out)
|
||||
{
|
||||
String error;
|
||||
StringMap decoded;
|
||||
@@ -1185,14 +1214,14 @@ static bool ucb_decode_flat_string_map(const String& encoded, StringMap& out, St
|
||||
error = message;
|
||||
return(false);
|
||||
};
|
||||
if(encoded.size() < 5 || encoded.compare(0, 4, UCEB_MAGIC) != 0)
|
||||
if(encoded_size < 5 || memcmp(encoded, UCEB_MAGIC, 4) != 0)
|
||||
fail("missing UCEB magic header");
|
||||
else if((u8)encoded[4] != UCEB_VERSION)
|
||||
fail("unsupported UCEB version");
|
||||
else
|
||||
{
|
||||
offset = 5;
|
||||
if(encoded.size() - offset < 2)
|
||||
if(encoded_size - offset < 2)
|
||||
fail("unexpected end of UCEB2 string map");
|
||||
else
|
||||
{
|
||||
@@ -1201,44 +1230,44 @@ static bool ucb_decode_flat_string_map(const String& encoded, StringMap& out, St
|
||||
u64 scalar_len = 0, child_count = 0;
|
||||
if(flags != 0 || type != 'M')
|
||||
fail("UCEB2 string map root must be a map");
|
||||
else if(!ucb_read_varint(encoded, offset, scalar_len) || scalar_len != 0)
|
||||
else if(!ucb_read_varint(encoded, encoded_size, offset, scalar_len) || scalar_len != 0)
|
||||
fail("UCEB2 string map root must have no scalar");
|
||||
else if(!ucb_read_varint(encoded, offset, child_count))
|
||||
else if(!ucb_read_varint(encoded, encoded_size, offset, child_count))
|
||||
fail("invalid UCEB2 string map child count");
|
||||
else
|
||||
{
|
||||
for(u64 i = 0; error == "" && i < child_count; i++)
|
||||
{
|
||||
u64 key_len = 0, value_len = 0, value_children = 0;
|
||||
if(!ucb_read_varint(encoded, offset, key_len) || key_len > encoded.size() - offset)
|
||||
if(!ucb_read_varint(encoded, encoded_size, offset, key_len) || key_len > encoded_size - offset)
|
||||
{
|
||||
fail("invalid UCEB2 string map key");
|
||||
break;
|
||||
}
|
||||
String key(encoded.data() + offset, (size_t)key_len);
|
||||
String key(encoded + offset, (size_t)key_len);
|
||||
offset += (size_t)key_len;
|
||||
if(encoded.size() - offset < 2)
|
||||
if(encoded_size - offset < 2)
|
||||
{
|
||||
fail("unexpected end of UCEB2 string map value");
|
||||
break;
|
||||
}
|
||||
u8 value_flags = (u8)encoded[offset++];
|
||||
char value_type = encoded[offset++];
|
||||
if(value_flags != 0 || value_type != 'S' || !ucb_read_varint(encoded, offset, value_len) || value_len > encoded.size() - offset)
|
||||
if(value_flags != 0 || value_type != 'S' || !ucb_read_varint(encoded, encoded_size, offset, value_len) || value_len > encoded_size - offset)
|
||||
{
|
||||
fail("UCEB2 string map value must be a string scalar");
|
||||
break;
|
||||
}
|
||||
String value(encoded.data() + offset, (size_t)value_len);
|
||||
String value(encoded + offset, (size_t)value_len);
|
||||
offset += (size_t)value_len;
|
||||
if(!ucb_read_varint(encoded, offset, value_children) || value_children != 0)
|
||||
if(!ucb_read_varint(encoded, encoded_size, offset, value_children) || value_children != 0)
|
||||
{
|
||||
fail("UCEB2 string map value cannot have children");
|
||||
break;
|
||||
}
|
||||
decoded[std::move(key)] = std::move(value);
|
||||
}
|
||||
if(error == "" && offset != encoded.size())
|
||||
if(error == "" && offset != encoded_size)
|
||||
fail("trailing bytes after UCEB2 string map");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ String to_String(DValue t);
|
||||
String var_dump(const DValue& map, String prefix = "", String postfix = "\n");
|
||||
|
||||
String ucb_encode(const DValue& value);
|
||||
String ucb_encode_flat_string_map(const StringMap& value);
|
||||
DValue ucb_decode(const String& encoded);
|
||||
bool ucb_decode(const String& encoded, DValue& out, String* error_out = 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user