mirror of
https://github.com/esphome/esphome.git
synced 2025-08-03 08:57:47 +00:00
less bad
This commit is contained in:
parent
e24d4450ac
commit
0c8693b8c6
File diff suppressed because it is too large
Load Diff
@ -889,9 +889,10 @@ void ProtoMessage::decode_v2(const uint8_t *buffer, size_t length) {
|
||||
break;
|
||||
}
|
||||
case ProtoFieldType::TYPE_MESSAGE: {
|
||||
// Use message type ID to call the appropriate handler
|
||||
decode_message_field_by_type(field_addr, value, fields[j].message_type_id);
|
||||
decoded = true;
|
||||
// Use function pointer from metadata
|
||||
if (fields[j].handler.message.decode) {
|
||||
decoded = fields[j].handler.message.decode(field_addr, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -921,9 +922,10 @@ void ProtoMessage::decode_v2(const uint8_t *buffer, size_t length) {
|
||||
break;
|
||||
}
|
||||
case ProtoFieldType::TYPE_MESSAGE: {
|
||||
// Use message type ID to call the appropriate handler
|
||||
decode_repeated_message_field_by_type(field_addr, value, repeated_fields[j].message_type_id);
|
||||
decoded = true;
|
||||
// Use function pointer from metadata
|
||||
if (repeated_fields[j].handler.message.decode) {
|
||||
decoded = repeated_fields[j].handler.message.decode(field_addr, value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -1202,8 +1204,10 @@ void ProtoMessage::encode_v2(ProtoWriteBuffer buffer) const {
|
||||
break;
|
||||
}
|
||||
case ProtoFieldType::TYPE_MESSAGE: {
|
||||
// Use message type ID to call the appropriate handler
|
||||
encode_message_field_by_type(buffer, fields[i].field_num, field_addr, fields[i].message_type_id);
|
||||
// Use function pointer from metadata
|
||||
if (fields[i].handler.message.encode) {
|
||||
fields[i].handler.message.encode(buffer, field_addr, fields[i].field_num);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1337,9 +1341,10 @@ void ProtoMessage::encode_v2(ProtoWriteBuffer buffer) const {
|
||||
break;
|
||||
}
|
||||
case ProtoFieldType::TYPE_MESSAGE: {
|
||||
// Use message type ID to call the appropriate handler
|
||||
encode_repeated_message_field_by_type(buffer, repeated_fields[i].field_num, field_addr,
|
||||
repeated_fields[i].message_type_id);
|
||||
// Use function pointer from metadata
|
||||
if (repeated_fields[i].handler.message.encode) {
|
||||
repeated_fields[i].handler.message.encode(buffer, field_addr, repeated_fields[i].field_num);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1447,9 +1452,11 @@ void ProtoMessage::calculate_size_v2(uint32_t &total_size) const {
|
||||
break;
|
||||
}
|
||||
case ProtoFieldType::TYPE_MESSAGE: {
|
||||
// Use message type ID to call the appropriate handler
|
||||
size_message_field_by_type(total_size, fields[i].precalced_field_id_size, field_addr, fields[i].message_type_id,
|
||||
fields[i].force_encode);
|
||||
// Use function pointer from metadata
|
||||
if (fields[i].handler.message.size) {
|
||||
fields[i].handler.message.size(total_size, field_addr, fields[i].precalced_field_id_size,
|
||||
fields[i].force_encode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1577,9 +1584,10 @@ void ProtoMessage::calculate_size_v2(uint32_t &total_size) const {
|
||||
break;
|
||||
}
|
||||
case ProtoFieldType::TYPE_MESSAGE: {
|
||||
// Use message type ID to call the appropriate handler
|
||||
size_repeated_message_field_by_type(total_size, repeated_fields[i].precalced_field_id_size, field_addr,
|
||||
repeated_fields[i].message_type_id);
|
||||
// Use function pointer from metadata
|
||||
if (repeated_fields[i].handler.message.size) {
|
||||
repeated_fields[i].handler.message.size(total_size, field_addr, repeated_fields[i].precalced_field_id_size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -292,7 +292,16 @@ struct FieldMetaV2 {
|
||||
ProtoFieldType type; // Field type enum
|
||||
bool force_encode; // If true, encode even if value is default/empty
|
||||
uint8_t precalced_field_id_size; // Pre-calculated size of field tag in bytes
|
||||
uint8_t message_type_id; // For TYPE_MESSAGE/TYPE_ENUM: identifies which type (0 for non-message/enum)
|
||||
union {
|
||||
// For TYPE_MESSAGE: function pointers (12 bytes on ESP32)
|
||||
struct {
|
||||
EncodeFunc encode;
|
||||
SizeFunc size;
|
||||
DecodeLengthFunc decode;
|
||||
} message;
|
||||
// For TYPE_ENUM: enum ID (1 byte)
|
||||
uint8_t enum_id;
|
||||
} handler;
|
||||
};
|
||||
|
||||
class ProtoWriteBuffer {
|
||||
@ -483,7 +492,16 @@ struct RepeatedFieldMetaV2 {
|
||||
uint16_t offset;
|
||||
ProtoFieldType type; // Element type
|
||||
uint8_t precalced_field_id_size; // Pre-calculated size of field tag in bytes
|
||||
uint8_t message_type_id; // For TYPE_MESSAGE/TYPE_ENUM: identifies which type (0 for non-message/enum)
|
||||
union {
|
||||
// For TYPE_MESSAGE: function pointers
|
||||
struct {
|
||||
RepeatedEncodeFunc encode;
|
||||
RepeatedSizeFunc size;
|
||||
RepeatedDecodeLengthFunc decode;
|
||||
} message;
|
||||
// For TYPE_ENUM: enum ID
|
||||
uint8_t enum_id;
|
||||
} handler;
|
||||
};
|
||||
|
||||
class ProtoMessage {
|
||||
@ -688,6 +706,21 @@ template<typename EnumType> bool decode_repeated_enum_field(void *field_ptr, Pro
|
||||
|
||||
template<typename MessageType> bool decode_repeated_message_field(void *field_ptr, ProtoLengthDelimited value);
|
||||
|
||||
// Forward declarations for message field template functions
|
||||
template<typename MessageType>
|
||||
void encode_message_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num);
|
||||
|
||||
template<typename MessageType>
|
||||
void size_message_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_id_size, bool force);
|
||||
|
||||
template<typename MessageType> bool decode_message_field(void *field_ptr, ProtoLengthDelimited value);
|
||||
|
||||
template<typename MessageType>
|
||||
void encode_repeated_message_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num);
|
||||
|
||||
template<typename MessageType>
|
||||
void size_repeated_message_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_id_size);
|
||||
|
||||
// Core shared functions
|
||||
void encode_from_metadata(ProtoWriteBuffer buffer, const void *obj, const FieldMeta *fields, size_t field_count,
|
||||
const RepeatedFieldMeta *repeated_fields = nullptr, size_t repeated_count = 0);
|
||||
@ -695,18 +728,5 @@ void encode_from_metadata(ProtoWriteBuffer buffer, const void *obj, const FieldM
|
||||
void calculate_size_from_metadata(uint32_t &total_size, const void *obj, const FieldMeta *fields, size_t field_count,
|
||||
const RepeatedFieldMeta *repeated_fields = nullptr, size_t repeated_count = 0);
|
||||
|
||||
// Message type handlers for V2 system
|
||||
void encode_message_field_by_type(ProtoWriteBuffer &buffer, uint8_t field_num, const void *field_ptr,
|
||||
uint8_t message_type_id);
|
||||
void decode_message_field_by_type(void *field_ptr, ProtoLengthDelimited value, uint8_t message_type_id);
|
||||
void size_message_field_by_type(uint32_t &total_size, uint8_t precalced_field_id_size, const void *field_ptr,
|
||||
uint8_t message_type_id, bool force);
|
||||
|
||||
void encode_repeated_message_field_by_type(ProtoWriteBuffer &buffer, uint8_t field_num, const void *field_ptr,
|
||||
uint8_t message_type_id);
|
||||
void decode_repeated_message_field_by_type(void *field_ptr, ProtoLengthDelimited value, uint8_t message_type_id);
|
||||
void size_repeated_message_field_by_type(uint32_t &total_size, uint8_t precalced_field_id_size, const void *field_ptr,
|
||||
uint8_t message_type_id);
|
||||
|
||||
} // namespace api
|
||||
} // namespace esphome
|
||||
|
@ -25,6 +25,26 @@ template<typename EnumType> inline bool decode_enum_field(void *field_ptr, Proto
|
||||
return true;
|
||||
}
|
||||
|
||||
// Template functions for message field handling (regular fields)
|
||||
template<typename MessageType>
|
||||
inline void encode_message_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num) {
|
||||
const MessageType *msg = static_cast<const MessageType *>(field_ptr);
|
||||
buffer.encode_message<MessageType>(field_num, *msg);
|
||||
}
|
||||
|
||||
template<typename MessageType>
|
||||
inline void size_message_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_id_size,
|
||||
bool force) {
|
||||
const MessageType *msg = static_cast<const MessageType *>(field_ptr);
|
||||
ProtoSize::add_message_object(total_size, precalced_field_id_size, *msg, force);
|
||||
}
|
||||
|
||||
template<typename MessageType> inline bool decode_message_field(void *field_ptr, ProtoLengthDelimited value) {
|
||||
MessageType *msg = static_cast<MessageType *>(field_ptr);
|
||||
*msg = value.as_message<MessageType>();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Template repeated field functions (must be in header for instantiation)
|
||||
template<typename EnumType>
|
||||
inline void encode_repeated_enum_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num) {
|
||||
|
@ -1385,25 +1385,33 @@ def build_message_type(
|
||||
if field_type:
|
||||
field_tag_size = ti.calculate_field_id_size()
|
||||
if field.type == descriptor.FieldDescriptorProto.TYPE_MESSAGE:
|
||||
# For messages, get the type ID
|
||||
message_type_id = get_message_type_id(ti._ti.type_name)
|
||||
# For messages, generate function pointers
|
||||
repeated_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"{field_type}, {field_tag_size}, "
|
||||
f"{{.message = {{&encode_repeated_message_field<{ti._ti.type_name}>, "
|
||||
f"&size_repeated_message_field<{ti._ti.type_name}>, "
|
||||
f"&decode_repeated_message_field<{ti._ti.type_name}>}}}}}}"
|
||||
)
|
||||
else:
|
||||
message_type_id = 0 # Non-message types have ID 0
|
||||
repeated_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"{field_type}, {field_tag_size}, {message_type_id}}}"
|
||||
)
|
||||
# Non-message types don't need handler info
|
||||
repeated_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"{field_type}, {field_tag_size}, {{}}}}"
|
||||
)
|
||||
elif isinstance(ti._ti, EnumType):
|
||||
enum_type_id = get_message_type_id(ti._ti.type_name)
|
||||
repeated_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"ProtoFieldType::TYPE_ENUM, {ti.calculate_field_id_size()}, {enum_type_id}}}"
|
||||
f"ProtoFieldType::TYPE_ENUM, {ti.calculate_field_id_size()}, {{.enum_id = {enum_type_id}}}}}"
|
||||
)
|
||||
elif isinstance(ti._ti, MessageType):
|
||||
message_type_id = get_message_type_id(ti._ti.type_name)
|
||||
repeated_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"ProtoFieldType::TYPE_MESSAGE, {ti.calculate_field_id_size()}, {message_type_id}}}"
|
||||
f"ProtoFieldType::TYPE_MESSAGE, {ti.calculate_field_id_size()}, "
|
||||
f"{{.message = {{&encode_repeated_message_field<{ti._ti.type_name}>, "
|
||||
f"&size_repeated_message_field<{ti._ti.type_name}>, "
|
||||
f"&decode_repeated_message_field<{ti._ti.type_name}>}}}}}}"
|
||||
)
|
||||
else:
|
||||
ti = TYPE_INFO[field.type](field)
|
||||
@ -1413,29 +1421,37 @@ def build_message_type(
|
||||
if field_type:
|
||||
field_tag_size = ti.calculate_field_id_size()
|
||||
if field.type == descriptor.FieldDescriptorProto.TYPE_MESSAGE:
|
||||
# For messages, get the type ID
|
||||
message_type_id = get_message_type_id(ti.type_name)
|
||||
# For messages, generate function pointers
|
||||
regular_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"{field_type}, {force}, {field_tag_size}, "
|
||||
f"{{.message = {{&encode_message_field<{ti.type_name}>, "
|
||||
f"&size_message_field<{ti.type_name}>, "
|
||||
f"&decode_message_field<{ti.type_name}>}}}}}}"
|
||||
)
|
||||
else:
|
||||
message_type_id = 0 # Non-message types have ID 0
|
||||
regular_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"{field_type}, {force}, {field_tag_size}, {message_type_id}}}"
|
||||
)
|
||||
# Non-message types don't need handler info
|
||||
regular_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"{field_type}, {force}, {field_tag_size}, {{}}}}"
|
||||
)
|
||||
elif isinstance(ti, EnumType):
|
||||
field_tag_size = ti.calculate_field_id_size()
|
||||
# For enums, use the enum name as type ID
|
||||
enum_type_id = get_message_type_id(ti.type_name)
|
||||
regular_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"ProtoFieldType::TYPE_ENUM, {force}, {field_tag_size}, {enum_type_id}}}"
|
||||
f"ProtoFieldType::TYPE_ENUM, {force}, {field_tag_size}, {{.enum_id = {enum_type_id}}}}}"
|
||||
)
|
||||
elif isinstance(ti, MessageType):
|
||||
field_tag_size = ti.calculate_field_id_size()
|
||||
# For messages, use the message type name as type ID
|
||||
message_type_id = get_message_type_id(ti.type_name)
|
||||
# For messages, generate function pointers
|
||||
regular_fields_v2.append(
|
||||
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
|
||||
f"ProtoFieldType::TYPE_MESSAGE, {force}, {field_tag_size}, {message_type_id}}}"
|
||||
f"ProtoFieldType::TYPE_MESSAGE, {force}, {field_tag_size}, "
|
||||
f"{{.message = {{&encode_message_field<{ti.type_name}>, "
|
||||
f"&size_message_field<{ti.type_name}>, "
|
||||
f"&decode_message_field<{ti.type_name}>}}}}}}"
|
||||
)
|
||||
|
||||
metadata_info["regular_fields_v2"] = regular_fields_v2
|
||||
@ -2085,130 +2101,6 @@ namespace api {
|
||||
if current_ifdef is not None:
|
||||
cpp += "#endif\n"
|
||||
|
||||
# Generate message type handler functions
|
||||
cpp += "\n// Message type handler implementations\n"
|
||||
|
||||
# Sort by type ID for consistent output
|
||||
sorted_types = sorted(MESSAGE_TYPE_REGISTRY.items(), key=lambda x: x[1])
|
||||
|
||||
# Generate encode handler
|
||||
cpp += "void encode_message_field_by_type(ProtoWriteBuffer &buffer, uint8_t field_num, const void *field_ptr, uint8_t message_type_id) {\n"
|
||||
cpp += " switch (message_type_id) {\n"
|
||||
for message_name, type_id in sorted_types:
|
||||
ifdef = message_ifdef_map.get(message_name)
|
||||
if ifdef:
|
||||
cpp += f"#ifdef {ifdef}\n"
|
||||
cpp += f" case {type_id}: {{\n"
|
||||
cpp += f" const {message_name} *msg = static_cast<const {message_name} *>(field_ptr);\n"
|
||||
cpp += f" buffer.encode_message<{message_name}>(field_num, *msg);\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
if ifdef:
|
||||
cpp += "#endif\n"
|
||||
cpp += " default:\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
cpp += "}\n\n"
|
||||
|
||||
# Generate decode handler
|
||||
cpp += "void decode_message_field_by_type(void *field_ptr, ProtoLengthDelimited value, uint8_t message_type_id) {\n"
|
||||
cpp += " switch (message_type_id) {\n"
|
||||
for message_name, type_id in sorted_types:
|
||||
ifdef = message_ifdef_map.get(message_name)
|
||||
if ifdef:
|
||||
cpp += f"#ifdef {ifdef}\n"
|
||||
cpp += f" case {type_id}: {{\n"
|
||||
cpp += (
|
||||
f" {message_name} *msg = static_cast<{message_name} *>(field_ptr);\n"
|
||||
)
|
||||
cpp += f" *msg = value.as_message<{message_name}>();\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
if ifdef:
|
||||
cpp += "#endif\n"
|
||||
cpp += " default:\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
cpp += "}\n\n"
|
||||
|
||||
# Generate size handler
|
||||
cpp += "void size_message_field_by_type(uint32_t &total_size, uint8_t precalced_field_id_size, const void *field_ptr, uint8_t message_type_id, bool force) {\n"
|
||||
cpp += " switch (message_type_id) {\n"
|
||||
for message_name, type_id in sorted_types:
|
||||
ifdef = message_ifdef_map.get(message_name)
|
||||
if ifdef:
|
||||
cpp += f"#ifdef {ifdef}\n"
|
||||
cpp += f" case {type_id}: {{\n"
|
||||
cpp += f" const {message_name} *msg = static_cast<const {message_name} *>(field_ptr);\n"
|
||||
cpp += " ProtoSize::add_message_object(total_size, precalced_field_id_size, *msg, force);\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
if ifdef:
|
||||
cpp += "#endif\n"
|
||||
cpp += " default:\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
cpp += "}\n\n"
|
||||
|
||||
# Generate repeated encode handler
|
||||
cpp += "void encode_repeated_message_field_by_type(ProtoWriteBuffer &buffer, uint8_t field_num, const void *field_ptr, uint8_t message_type_id) {\n"
|
||||
cpp += " switch (message_type_id) {\n"
|
||||
for message_name, type_id in sorted_types:
|
||||
ifdef = message_ifdef_map.get(message_name)
|
||||
if ifdef:
|
||||
cpp += f"#ifdef {ifdef}\n"
|
||||
cpp += f" case {type_id}: {{\n"
|
||||
cpp += f" const std::vector<{message_name}> *vec = static_cast<const std::vector<{message_name}> *>(field_ptr);\n"
|
||||
cpp += " for (const auto &msg : *vec) {\n"
|
||||
cpp += f" buffer.encode_message<{message_name}>(field_num, msg, true);\n"
|
||||
cpp += " }\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
if ifdef:
|
||||
cpp += "#endif\n"
|
||||
cpp += " default:\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
cpp += "}\n\n"
|
||||
|
||||
# Generate repeated decode handler
|
||||
cpp += "void decode_repeated_message_field_by_type(void *field_ptr, ProtoLengthDelimited value, uint8_t message_type_id) {\n"
|
||||
cpp += " switch (message_type_id) {\n"
|
||||
for message_name, type_id in sorted_types:
|
||||
ifdef = message_ifdef_map.get(message_name)
|
||||
if ifdef:
|
||||
cpp += f"#ifdef {ifdef}\n"
|
||||
cpp += f" case {type_id}: {{\n"
|
||||
cpp += f" std::vector<{message_name}> *vec = static_cast<std::vector<{message_name}> *>(field_ptr);\n"
|
||||
cpp += f" vec->push_back(value.as_message<{message_name}>());\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
if ifdef:
|
||||
cpp += "#endif\n"
|
||||
cpp += " default:\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
cpp += "}\n\n"
|
||||
|
||||
# Generate repeated size handler
|
||||
cpp += "void size_repeated_message_field_by_type(uint32_t &total_size, uint8_t precalced_field_id_size, const void *field_ptr, uint8_t message_type_id) {\n"
|
||||
cpp += " switch (message_type_id) {\n"
|
||||
for message_name, type_id in sorted_types:
|
||||
ifdef = message_ifdef_map.get(message_name)
|
||||
if ifdef:
|
||||
cpp += f"#ifdef {ifdef}\n"
|
||||
cpp += f" case {type_id}: {{\n"
|
||||
cpp += f" const std::vector<{message_name}> *vec = static_cast<const std::vector<{message_name}> *>(field_ptr);\n"
|
||||
cpp += f" ProtoSize::add_repeated_message<{message_name}>(total_size, precalced_field_id_size, *vec);\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
if ifdef:
|
||||
cpp += "#endif\n"
|
||||
cpp += " default:\n"
|
||||
cpp += " break;\n"
|
||||
cpp += " }\n"
|
||||
cpp += "}\n"
|
||||
|
||||
cpp += """\
|
||||
|
||||
} // namespace api
|
||||
|
Loading…
x
Reference in New Issue
Block a user