This commit is contained in:
J. Nick Koston 2025-07-20 19:40:21 -10:00
parent 1dc736e27a
commit 9cb86241b9
No known key found for this signature in database
3 changed files with 65 additions and 15 deletions

View File

@ -831,6 +831,8 @@ bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthD
switch (field_id) { switch (field_id) {
case 1: case 1:
this->key = value.as_string(); this->key = value.as_string();
this->key_ptr_ = reinterpret_cast<const uint8_t *>(this->key.data());
this->key_len_ = this->key.size();
break; break;
default: default:
return false; return false;
@ -1999,6 +2001,8 @@ bool BluetoothGATTWriteRequest::decode_length(uint32_t field_id, ProtoLengthDeli
switch (field_id) { switch (field_id) {
case 4: case 4:
this->data = value.as_string(); this->data = value.as_string();
this->data_ptr_ = reinterpret_cast<const uint8_t *>(this->data.data());
this->data_len_ = this->data.size();
break; break;
default: default:
return false; return false;
@ -2035,6 +2039,8 @@ bool BluetoothGATTWriteDescriptorRequest::decode_length(uint32_t field_id, Proto
switch (field_id) { switch (field_id) {
case 3: case 3:
this->data = value.as_string(); this->data = value.as_string();
this->data_ptr_ = reinterpret_cast<const uint8_t *>(this->data.data());
this->data_len_ = this->data.size();
break; break;
default: default:
return false; return false;
@ -2257,6 +2263,8 @@ bool VoiceAssistantAudio::decode_length(uint32_t field_id, ProtoLengthDelimited
switch (field_id) { switch (field_id) {
case 1: case 1:
this->data = value.as_string(); this->data = value.as_string();
this->data_ptr_ = reinterpret_cast<const uint8_t *>(this->data.data());
this->data_len_ = this->data.size();
break; break;
default: default:
return false; return false;

View File

@ -993,6 +993,7 @@ class NoiseEncryptionSetKeyRequest : public ProtoDecodableMessage {
#endif #endif
const uint8_t *key_ptr_{nullptr}; const uint8_t *key_ptr_{nullptr};
size_t key_len_{0}; size_t key_len_{0};
std::string key{}; // Storage for decoded data
void set_key(const uint8_t *data, size_t len) { void set_key(const uint8_t *data, size_t len) {
this->key_ptr_ = data; this->key_ptr_ = data;
this->key_len_ = len; this->key_len_ = len;
@ -1921,6 +1922,7 @@ class BluetoothGATTWriteRequest : public ProtoDecodableMessage {
bool response{false}; bool response{false};
const uint8_t *data_ptr_{nullptr}; const uint8_t *data_ptr_{nullptr};
size_t data_len_{0}; size_t data_len_{0};
std::string data{}; // Storage for decoded data
void set_data(const uint8_t *data, size_t len) { void set_data(const uint8_t *data, size_t len) {
this->data_ptr_ = data; this->data_ptr_ = data;
this->data_len_ = len; this->data_len_ = len;
@ -1960,6 +1962,7 @@ class BluetoothGATTWriteDescriptorRequest : public ProtoDecodableMessage {
uint32_t handle{0}; uint32_t handle{0};
const uint8_t *data_ptr_{nullptr}; const uint8_t *data_ptr_{nullptr};
size_t data_len_{0}; size_t data_len_{0};
std::string data{}; // Storage for decoded data
void set_data(const uint8_t *data, size_t len) { void set_data(const uint8_t *data, size_t len) {
this->data_ptr_ = data; this->data_ptr_ = data;
this->data_len_ = len; this->data_len_ = len;
@ -2298,6 +2301,7 @@ class VoiceAssistantAudio : public ProtoDecodableMessage {
#endif #endif
const uint8_t *data_ptr_{nullptr}; const uint8_t *data_ptr_{nullptr};
size_t data_len_{0}; size_t data_len_{0};
std::string data{}; // Storage for decoded data
void set_data(const uint8_t *data, size_t len) { void set_data(const uint8_t *data, size_t len) {
this->data_ptr_ = data; this->data_ptr_ = data;
this->data_len_ = len; this->data_len_ = len;

View File

@ -313,7 +313,9 @@ def validate_field_type(field_type: int, field_name: str = "") -> None:
) )
def create_field_type_info(field: descriptor.FieldDescriptorProto) -> TypeInfo: def create_field_type_info(
field: descriptor.FieldDescriptorProto, needs_decode: bool = True
) -> TypeInfo:
"""Create the appropriate TypeInfo instance for a field, handling repeated fields and custom options.""" """Create the appropriate TypeInfo instance for a field, handling repeated fields and custom options."""
if field.label == 3: # repeated if field.label == 3: # repeated
return RepeatedTypeInfo(field) return RepeatedTypeInfo(field)
@ -325,6 +327,10 @@ def create_field_type_info(field: descriptor.FieldDescriptorProto) -> TypeInfo:
): ):
return FixedArrayBytesType(field, fixed_size) return FixedArrayBytesType(field, fixed_size)
# Special handling for bytes fields
if field.type == 12:
return BytesType(field, needs_decode)
validate_field_type(field.type, field.name) validate_field_type(field.type, field.name)
return TYPE_INFO[field.type](field) return TYPE_INFO[field.type](field)
@ -589,22 +595,54 @@ class BytesType(TypeInfo):
default_value = "" default_value = ""
reference_type = "std::string &" reference_type = "std::string &"
const_reference_type = "const std::string &" const_reference_type = "const std::string &"
decode_length = "value.as_string()"
encode_func = "encode_bytes" encode_func = "encode_bytes"
wire_type = WireType.LENGTH_DELIMITED # Uses wire type 2 wire_type = WireType.LENGTH_DELIMITED # Uses wire type 2
def __init__(
self, field: descriptor.FieldDescriptorProto, needs_decode: bool = True
) -> None:
super().__init__(field)
self.needs_decode = needs_decode
@property @property
def public_content(self) -> list[str]: def public_content(self) -> list[str]:
# Store both pointer and length for zero-copy encoding, plus setter method # Store both pointer and length for zero-copy encoding, plus setter method
return [ content = [
f"const uint8_t* {self.field_name}_ptr_{{nullptr}};", f"const uint8_t* {self.field_name}_ptr_{{nullptr}};",
f"size_t {self.field_name}_len_{{0}};", f"size_t {self.field_name}_len_{{0}};",
f"void set_{self.field_name}(const uint8_t* data, size_t len) {{",
f" this->{self.field_name}_ptr_ = data;",
f" this->{self.field_name}_len_ = len;",
"}",
] ]
# Only add storage if message needs decoding
if self.needs_decode:
content.append(
f"std::string {self.field_name}{{}}; // Storage for decoded data"
)
content.extend(
[
f"void set_{self.field_name}(const uint8_t* data, size_t len) {{",
f" this->{self.field_name}_ptr_ = data;",
f" this->{self.field_name}_len_ = len;",
"}",
]
)
return content
@property
def decode_length_content(self) -> str:
if not self.needs_decode:
return "" # No decode needed for SOURCE_SERVER messages
# Decode into storage and update pointer/length
return (
f"case {self.number}:\n"
f" this->{self.field_name} = value.as_string();\n"
f" this->{self.field_name}_ptr_ = reinterpret_cast<const uint8_t*>(this->{self.field_name}.data());\n"
f" this->{self.field_name}_len_ = this->{self.field_name}.size();\n"
f" break;"
)
@property @property
def encode_content(self) -> str: def encode_content(self) -> str:
return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);" return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);"
@ -1268,7 +1306,7 @@ def build_message_type(
if field.options.deprecated: if field.options.deprecated:
continue continue
ti = create_field_type_info(field) ti = create_field_type_info(field, needs_decode)
# Skip field declarations for fields that are in the base class # Skip field declarations for fields that are in the base class
# but include their encode/decode logic # but include their encode/decode logic
@ -1583,10 +1621,16 @@ def build_base_class(
public_content = [] public_content = []
protected_content = [] protected_content = []
# Determine if any message using this base class needs decoding
needs_decode = any(
message_source_map.get(msg.name, SOURCE_BOTH) in (SOURCE_BOTH, SOURCE_CLIENT)
for msg in messages
)
# For base classes, we only declare the fields but don't handle encode/decode # For base classes, we only declare the fields but don't handle encode/decode
# The derived classes will handle encoding/decoding with their specific field numbers # The derived classes will handle encoding/decoding with their specific field numbers
for field in common_fields: for field in common_fields:
ti = create_field_type_info(field) ti = create_field_type_info(field, needs_decode)
# Get field_ifdef if it's consistent across all messages # Get field_ifdef if it's consistent across all messages
field_ifdef = get_common_field_ifdef(field.name, messages) field_ifdef = get_common_field_ifdef(field.name, messages)
@ -1597,12 +1641,6 @@ def build_base_class(
if ti.public_content: if ti.public_content:
public_content.extend(wrap_with_ifdef(ti.public_content, field_ifdef)) public_content.extend(wrap_with_ifdef(ti.public_content, field_ifdef))
# Determine if any message using this base class needs decoding
needs_decode = any(
message_source_map.get(msg.name, SOURCE_BOTH) in (SOURCE_BOTH, SOURCE_CLIENT)
for msg in messages
)
# Build header # Build header
parent_class = "ProtoDecodableMessage" if needs_decode else "ProtoMessage" parent_class = "ProtoDecodableMessage" if needs_decode else "ProtoMessage"
out = f"class {base_class_name} : public {parent_class} {{\n" out = f"class {base_class_name} : public {parent_class} {{\n"