mirror of
https://github.com/esphome/esphome.git
synced 2025-08-05 09:57:47 +00:00
revert wire type storage
This commit is contained in:
parent
984c24a1b5
commit
28620190f0
@ -349,19 +349,16 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
|||||||
}
|
}
|
||||||
ProtoVarInt value = *value_res;
|
ProtoVarInt value = *value_res;
|
||||||
|
|
||||||
// Try regular fields first
|
// Try regular fields first using binary search
|
||||||
for (uint8_t j = 0; j < field_count; j++) {
|
if (const FieldMeta *field = find_field_binary(fields, field_count, field_id, 0)) {
|
||||||
if (fields[j].field_num == field_id && get_wire_type(fields[j].get_type()) == 0) {
|
void *field_addr = base + field->get_offset();
|
||||||
void *field_addr = base + fields[j].get_offset();
|
decoded = decode_varint_field(field->get_type(), field_addr, value);
|
||||||
decoded = decode_varint_field(fields[j].get_type(), field_addr, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not found, try repeated fields
|
// If not found, try repeated fields (linear search - usually only 1-2 fields)
|
||||||
if (!decoded) {
|
if (!decoded) {
|
||||||
for (uint8_t j = 0; j < repeated_count; j++) {
|
for (uint8_t j = 0; j < repeated_count; j++) {
|
||||||
if (repeated_fields[j].field_num == field_id && get_wire_type(repeated_fields[j].get_type()) == 0) {
|
if (repeated_fields[j].field_num == field_id && repeated_fields[j].get_wire_type() == 0) {
|
||||||
void *field_addr = base + repeated_fields[j].get_offset();
|
void *field_addr = base + repeated_fields[j].get_offset();
|
||||||
decoded = decode_repeated_varint_field(repeated_fields[j].get_type(), field_addr, value);
|
decoded = decode_repeated_varint_field(repeated_fields[j].get_type(), field_addr, value);
|
||||||
break;
|
break;
|
||||||
@ -389,19 +386,16 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
|||||||
|
|
||||||
ProtoLengthDelimited value(&buffer[i], field_length);
|
ProtoLengthDelimited value(&buffer[i], field_length);
|
||||||
|
|
||||||
// Try regular fields first
|
// Try regular fields first using binary search
|
||||||
for (uint8_t j = 0; j < field_count; j++) {
|
if (const FieldMeta *field = find_field_binary(fields, field_count, field_id, 2)) {
|
||||||
if (fields[j].field_num == field_id && get_wire_type(fields[j].get_type()) == 2) {
|
void *field_addr = base + field->get_offset();
|
||||||
void *field_addr = base + fields[j].get_offset();
|
decoded = decode_length_field(field->get_type(), field_addr, value, field->get_message_type_id());
|
||||||
decoded = decode_length_field(fields[j].get_type(), field_addr, value, fields[j].get_message_type_id());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not found, try repeated fields
|
// If not found, try repeated fields (linear search - usually only 1-2 fields)
|
||||||
if (!decoded) {
|
if (!decoded) {
|
||||||
for (uint8_t j = 0; j < repeated_count; j++) {
|
for (uint8_t j = 0; j < repeated_count; j++) {
|
||||||
if (repeated_fields[j].field_num == field_id && get_wire_type(repeated_fields[j].get_type()) == 2) {
|
if (repeated_fields[j].field_num == field_id && repeated_fields[j].get_wire_type() == 2) {
|
||||||
void *field_addr = base + repeated_fields[j].get_offset();
|
void *field_addr = base + repeated_fields[j].get_offset();
|
||||||
decoded = decode_repeated_length_field(repeated_fields[j].get_type(), field_addr, value,
|
decoded = decode_repeated_length_field(repeated_fields[j].get_type(), field_addr, value,
|
||||||
repeated_fields[j].get_message_type_id());
|
repeated_fields[j].get_message_type_id());
|
||||||
@ -427,19 +421,16 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
|||||||
raw |= uint32_t(buffer[i + 3]) << 24;
|
raw |= uint32_t(buffer[i + 3]) << 24;
|
||||||
Proto32Bit value(raw);
|
Proto32Bit value(raw);
|
||||||
|
|
||||||
// Try regular fields first
|
// Try regular fields first using binary search
|
||||||
for (uint8_t j = 0; j < field_count; j++) {
|
if (const FieldMeta *field = find_field_binary(fields, field_count, field_id, 5)) {
|
||||||
if (fields[j].field_num == field_id && get_wire_type(fields[j].get_type()) == 5) {
|
void *field_addr = base + field->get_offset();
|
||||||
void *field_addr = base + fields[j].get_offset();
|
decoded = decode_32bit_field(field->get_type(), field_addr, value);
|
||||||
decoded = decode_32bit_field(fields[j].get_type(), field_addr, value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not found, try repeated fields
|
// If not found, try repeated fields (linear search - usually only 1-2 fields)
|
||||||
if (!decoded) {
|
if (!decoded) {
|
||||||
for (uint8_t j = 0; j < repeated_count; j++) {
|
for (uint8_t j = 0; j < repeated_count; j++) {
|
||||||
if (repeated_fields[j].field_num == field_id && get_wire_type(repeated_fields[j].get_type()) == 5) {
|
if (repeated_fields[j].field_num == field_id && repeated_fields[j].get_wire_type() == 5) {
|
||||||
void *field_addr = base + repeated_fields[j].get_offset();
|
void *field_addr = base + repeated_fields[j].get_offset();
|
||||||
decoded = decode_repeated_32bit_field(repeated_fields[j].get_type(), field_addr, value);
|
decoded = decode_repeated_32bit_field(repeated_fields[j].get_type(), field_addr, value);
|
||||||
break;
|
break;
|
||||||
|
@ -271,6 +271,7 @@ struct FieldMeta {
|
|||||||
// Helper methods
|
// Helper methods
|
||||||
inline ProtoFieldType get_type() const { return static_cast<ProtoFieldType>(type_and_size & 0x1F); }
|
inline ProtoFieldType get_type() const { return static_cast<ProtoFieldType>(type_and_size & 0x1F); }
|
||||||
inline uint8_t get_precalced_size() const { return ((type_and_size >> 5) & 0x03) + 1; }
|
inline uint8_t get_precalced_size() const { return ((type_and_size >> 5) & 0x03) + 1; }
|
||||||
|
inline uint8_t get_wire_type() const { return ::esphome::api::get_wire_type(get_type()); }
|
||||||
inline uint16_t get_offset() const {
|
inline uint16_t get_offset() const {
|
||||||
if (get_type() == ProtoFieldType::TYPE_MESSAGE) {
|
if (get_type() == ProtoFieldType::TYPE_MESSAGE) {
|
||||||
// Reconstruct full offset from packed fields (10-bit offset)
|
// Reconstruct full offset from packed fields (10-bit offset)
|
||||||
@ -297,6 +298,7 @@ struct RepeatedFieldMeta {
|
|||||||
// Helper methods
|
// Helper methods
|
||||||
inline ProtoFieldType get_type() const { return static_cast<ProtoFieldType>(type_and_size & 0x1F); }
|
inline ProtoFieldType get_type() const { return static_cast<ProtoFieldType>(type_and_size & 0x1F); }
|
||||||
inline uint8_t get_precalced_size() const { return ((type_and_size >> 5) & 0x03) + 1; }
|
inline uint8_t get_precalced_size() const { return ((type_and_size >> 5) & 0x03) + 1; }
|
||||||
|
inline uint8_t get_wire_type() const { return ::esphome::api::get_wire_type(get_type()); }
|
||||||
inline uint16_t get_offset() const {
|
inline uint16_t get_offset() const {
|
||||||
if (get_type() == ProtoFieldType::TYPE_MESSAGE) {
|
if (get_type() == ProtoFieldType::TYPE_MESSAGE) {
|
||||||
// Reconstruct full offset from packed fields (10-bit offset)
|
// Reconstruct full offset from packed fields (10-bit offset)
|
||||||
@ -308,6 +310,49 @@ struct RepeatedFieldMeta {
|
|||||||
inline uint8_t get_message_type_id() const { return message_type_id >> 2; } // Upper 6 bits for type ID (0-63)
|
inline uint8_t get_message_type_id() const { return message_type_id >> 2; } // Upper 6 bits for type ID (0-63)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Binary search for field lookup - optimized for performance
|
||||||
|
template<typename MetaType>
|
||||||
|
inline const MetaType *find_field_binary(const MetaType *fields, uint8_t count, uint8_t field_id, uint8_t wire_type) {
|
||||||
|
uint8_t left = 0;
|
||||||
|
uint8_t right = count;
|
||||||
|
|
||||||
|
while (left < right) {
|
||||||
|
uint8_t mid = (left + right) / 2;
|
||||||
|
uint8_t mid_field = fields[mid].field_num;
|
||||||
|
|
||||||
|
if (mid_field < field_id) {
|
||||||
|
left = mid + 1;
|
||||||
|
} else if (mid_field > field_id) {
|
||||||
|
right = mid;
|
||||||
|
} else {
|
||||||
|
// Found field_id, check wire type
|
||||||
|
if (fields[mid].get_wire_type() == wire_type) {
|
||||||
|
return &fields[mid];
|
||||||
|
}
|
||||||
|
// Field number matches but wire type doesn't - search nearby entries
|
||||||
|
// (in case there are multiple fields with same number but different types)
|
||||||
|
|
||||||
|
// Search backwards
|
||||||
|
for (uint8_t k = mid; k > 0 && fields[k - 1].field_num == field_id; k--) {
|
||||||
|
if (fields[k - 1].get_wire_type() == wire_type) {
|
||||||
|
return &fields[k - 1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search forwards
|
||||||
|
for (uint8_t k = mid + 1; k < count && fields[k].field_num == field_id; k++) {
|
||||||
|
if (fields[k].get_wire_type() == wire_type) {
|
||||||
|
return &fields[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr; // Field number found but no matching wire type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr; // Field not found
|
||||||
|
}
|
||||||
|
|
||||||
class ProtoWriteBuffer {
|
class ProtoWriteBuffer {
|
||||||
public:
|
public:
|
||||||
ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer) {}
|
ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer) {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user