mirror of
https://github.com/esphome/esphome.git
synced 2025-08-05 09:57:47 +00:00
dry
This commit is contained in:
parent
27b0c99580
commit
1818a56096
@ -12,6 +12,14 @@ static const char *const TAG = "api.proto";
|
|||||||
void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
||||||
uint32_t i = 0;
|
uint32_t i = 0;
|
||||||
bool error = false;
|
bool error = false;
|
||||||
|
uint8_t *base = reinterpret_cast<uint8_t *>(this);
|
||||||
|
|
||||||
|
// Get metadata once at the start
|
||||||
|
const FieldMeta *fields = get_field_metadata();
|
||||||
|
size_t field_count = get_field_count();
|
||||||
|
const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata();
|
||||||
|
size_t repeated_count = get_repeated_field_count();
|
||||||
|
|
||||||
while (i < length) {
|
while (i < length) {
|
||||||
uint32_t consumed;
|
uint32_t consumed;
|
||||||
auto res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
|
auto res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
|
||||||
@ -32,7 +40,30 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
|||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!this->decode_varint(field_id, *res)) {
|
ProtoVarInt value = *res;
|
||||||
|
bool decoded = false;
|
||||||
|
|
||||||
|
// Check regular fields
|
||||||
|
for (size_t j = 0; j < field_count; j++) {
|
||||||
|
if (fields[j].field_num == field_id && fields[j].wire_type == 0) {
|
||||||
|
void *field_addr = base + fields[j].offset;
|
||||||
|
decoded = fields[j].decoder.decode_varint(field_addr, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check repeated fields if not found
|
||||||
|
if (!decoded && repeated_fields) {
|
||||||
|
for (size_t j = 0; j < repeated_count; j++) {
|
||||||
|
if (repeated_fields[j].field_num == field_id && repeated_fields[j].wire_type == 0) {
|
||||||
|
void *field_addr = base + repeated_fields[j].offset;
|
||||||
|
decoded = repeated_fields[j].decoder.decode_varint(field_addr, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decoded) {
|
||||||
ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32());
|
ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32());
|
||||||
}
|
}
|
||||||
i += consumed;
|
i += consumed;
|
||||||
@ -52,7 +83,30 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
|||||||
error = true;
|
error = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!this->decode_length(field_id, ProtoLengthDelimited(&buffer[i], field_length))) {
|
ProtoLengthDelimited value(&buffer[i], field_length);
|
||||||
|
bool decoded = false;
|
||||||
|
|
||||||
|
// Check regular fields
|
||||||
|
for (size_t j = 0; j < field_count; j++) {
|
||||||
|
if (fields[j].field_num == field_id && fields[j].wire_type == 2) {
|
||||||
|
void *field_addr = base + fields[j].offset;
|
||||||
|
decoded = fields[j].decoder.decode_length(field_addr, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check repeated fields if not found
|
||||||
|
if (!decoded && repeated_fields) {
|
||||||
|
for (size_t j = 0; j < repeated_count; j++) {
|
||||||
|
if (repeated_fields[j].field_num == field_id && repeated_fields[j].wire_type == 2) {
|
||||||
|
void *field_addr = base + repeated_fields[j].offset;
|
||||||
|
decoded = repeated_fields[j].decoder.decode_length(field_addr, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decoded) {
|
||||||
ESP_LOGV(TAG, "Cannot decode Length Delimited field %" PRIu32 "!", field_id);
|
ESP_LOGV(TAG, "Cannot decode Length Delimited field %" PRIu32 "!", field_id);
|
||||||
}
|
}
|
||||||
i += field_length;
|
i += field_length;
|
||||||
@ -65,7 +119,30 @@ void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
uint32_t val = encode_uint32(buffer[i + 3], buffer[i + 2], buffer[i + 1], buffer[i]);
|
uint32_t val = encode_uint32(buffer[i + 3], buffer[i + 2], buffer[i + 1], buffer[i]);
|
||||||
if (!this->decode_32bit(field_id, Proto32Bit(val))) {
|
Proto32Bit value(val);
|
||||||
|
bool decoded = false;
|
||||||
|
|
||||||
|
// Check regular fields
|
||||||
|
for (size_t j = 0; j < field_count; j++) {
|
||||||
|
if (fields[j].field_num == field_id && fields[j].wire_type == 5) {
|
||||||
|
void *field_addr = base + fields[j].offset;
|
||||||
|
decoded = fields[j].decoder.decode_32bit(field_addr, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check repeated fields if not found
|
||||||
|
if (!decoded && repeated_fields) {
|
||||||
|
for (size_t j = 0; j < repeated_count; j++) {
|
||||||
|
if (repeated_fields[j].field_num == field_id && repeated_fields[j].wire_type == 5) {
|
||||||
|
void *field_addr = base + repeated_fields[j].offset;
|
||||||
|
decoded = repeated_fields[j].decoder.decode_32bit(field_addr, value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!decoded) {
|
||||||
ESP_LOGV(TAG, "Cannot decode 32-bit field %" PRIu32 " with value %" PRIu32 "!", field_id, val);
|
ESP_LOGV(TAG, "Cannot decode 32-bit field %" PRIu32 " with value %" PRIu32 "!", field_id, val);
|
||||||
}
|
}
|
||||||
i += 4;
|
i += 4;
|
||||||
@ -610,117 +687,5 @@ void ProtoMessage::calculate_size(uint32_t &total_size) const {
|
|||||||
get_repeated_field_count());
|
get_repeated_field_count());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProtoMessage::decode_varint(uint32_t field_id, ProtoVarInt value) {
|
|
||||||
uint8_t *base = reinterpret_cast<uint8_t *>(this);
|
|
||||||
|
|
||||||
// Check regular fields
|
|
||||||
const FieldMeta *fields = get_field_metadata();
|
|
||||||
size_t field_count = get_field_count();
|
|
||||||
for (size_t i = 0; i < field_count; i++) {
|
|
||||||
if (fields[i].field_num == field_id && fields[i].wire_type == 0) { // varint
|
|
||||||
void *field_addr = base + fields[i].offset;
|
|
||||||
return fields[i].decoder.decode_varint(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check repeated fields
|
|
||||||
const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata();
|
|
||||||
size_t repeated_count = get_repeated_field_count();
|
|
||||||
if (repeated_fields) {
|
|
||||||
for (size_t i = 0; i < repeated_count; i++) {
|
|
||||||
if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 0) { // varint
|
|
||||||
void *field_addr = base + repeated_fields[i].offset;
|
|
||||||
return repeated_fields[i].decoder.decode_varint(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProtoMessage::decode_length(uint32_t field_id, ProtoLengthDelimited value) {
|
|
||||||
uint8_t *base = reinterpret_cast<uint8_t *>(this);
|
|
||||||
|
|
||||||
// Check regular fields
|
|
||||||
const FieldMeta *fields = get_field_metadata();
|
|
||||||
size_t field_count = get_field_count();
|
|
||||||
for (size_t i = 0; i < field_count; i++) {
|
|
||||||
if (fields[i].field_num == field_id && fields[i].wire_type == 2) { // length-delimited
|
|
||||||
void *field_addr = base + fields[i].offset;
|
|
||||||
return fields[i].decoder.decode_length(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check repeated fields
|
|
||||||
const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata();
|
|
||||||
size_t repeated_count = get_repeated_field_count();
|
|
||||||
if (repeated_fields) {
|
|
||||||
for (size_t i = 0; i < repeated_count; i++) {
|
|
||||||
if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 2) { // length-delimited
|
|
||||||
void *field_addr = base + repeated_fields[i].offset;
|
|
||||||
return repeated_fields[i].decoder.decode_length(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProtoMessage::decode_32bit(uint32_t field_id, Proto32Bit value) {
|
|
||||||
uint8_t *base = reinterpret_cast<uint8_t *>(this);
|
|
||||||
|
|
||||||
// Check regular fields
|
|
||||||
const FieldMeta *fields = get_field_metadata();
|
|
||||||
size_t field_count = get_field_count();
|
|
||||||
for (size_t i = 0; i < field_count; i++) {
|
|
||||||
if (fields[i].field_num == field_id && fields[i].wire_type == 5) { // 32-bit
|
|
||||||
void *field_addr = base + fields[i].offset;
|
|
||||||
return fields[i].decoder.decode_32bit(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check repeated fields
|
|
||||||
const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata();
|
|
||||||
size_t repeated_count = get_repeated_field_count();
|
|
||||||
if (repeated_fields) {
|
|
||||||
for (size_t i = 0; i < repeated_count; i++) {
|
|
||||||
if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 5) { // 32-bit
|
|
||||||
void *field_addr = base + repeated_fields[i].offset;
|
|
||||||
return repeated_fields[i].decoder.decode_32bit(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ProtoMessage::decode_64bit(uint32_t field_id, Proto64Bit value) {
|
|
||||||
uint8_t *base = reinterpret_cast<uint8_t *>(this);
|
|
||||||
|
|
||||||
// Check regular fields
|
|
||||||
const FieldMeta *fields = get_field_metadata();
|
|
||||||
size_t field_count = get_field_count();
|
|
||||||
for (size_t i = 0; i < field_count; i++) {
|
|
||||||
if (fields[i].field_num == field_id && fields[i].wire_type == 1) { // 64-bit
|
|
||||||
void *field_addr = base + fields[i].offset;
|
|
||||||
return fields[i].decoder.decode_64bit(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check repeated fields
|
|
||||||
const RepeatedFieldMeta *repeated_fields = get_repeated_field_metadata();
|
|
||||||
size_t repeated_count = get_repeated_field_count();
|
|
||||||
if (repeated_fields) {
|
|
||||||
for (size_t i = 0; i < repeated_count; i++) {
|
|
||||||
if (repeated_fields[i].field_num == field_id && repeated_fields[i].wire_type == 1) { // 64-bit
|
|
||||||
void *field_addr = base + repeated_fields[i].offset;
|
|
||||||
return repeated_fields[i].decoder.decode_64bit(field_addr, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace api
|
} // namespace api
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
@ -408,13 +408,6 @@ class ProtoMessage {
|
|||||||
virtual void dump_to(std::string &out) const = 0;
|
virtual void dump_to(std::string &out) const = 0;
|
||||||
virtual const char *message_name() const { return "unknown"; }
|
virtual const char *message_name() const { return "unknown"; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
protected:
|
|
||||||
// Decode methods using metadata
|
|
||||||
bool decode_varint(uint32_t field_id, ProtoVarInt value);
|
|
||||||
bool decode_length(uint32_t field_id, ProtoLengthDelimited value);
|
|
||||||
bool decode_32bit(uint32_t field_id, Proto32Bit value);
|
|
||||||
bool decode_64bit(uint32_t field_id, Proto64Bit value);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> const char *proto_enum_to_string(T value);
|
template<typename T> const char *proto_enum_to_string(T value);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user