From bcdb384bbe48ff4d686ca0ff5dcc3bfc75bde99d Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 7 Sep 2026 09:41:57 +0200 Subject: [PATCH] [api] Collapse the three protobuf decode virtuals into one Every decodable message overrode up to three virtuals, one per wire type, so each carried a five slot vtable and up to three functions with their own prologue and return tails. The shared decode loop now parses the payload for the wire type into a ProtoFieldValue and calls a single decode_field() virtual with the tag, the field number and the wire type; the generated override is one switch. The switch key is chosen per target through PROTO_DECODE_KEY. Embedded builds compile switches to compare chains (ESP-IDF passes -fno-jump-tables), so they key on the full wire tag, one compare per field with no separate wire type check. The host compiler builds a jump table for the dense field number switch, so there the key is the field number and PROTO_DECODE_GUARD rejects a mismatched wire type. Both forms drop a field that arrives with a wire type it does not declare, exactly as the per wire type virtuals did. Per decodable message the vtable shrinks from 20 to 12 bytes on xtensa and the extra decode functions fold into one; the shared loop shrinks as well. Host instruction counts per decoded field are unchanged apart from the guard compare, which replaces the prologue of the separate function it used to call. --- esphome/components/api/api_pb2.cpp | 2081 ++++++++--------- esphome/components/api/api_pb2.h | 165 +- esphome/components/api/proto.cpp | 22 +- esphome/components/api/proto.h | 84 +- script/api_protobuf/api_protobuf.py | 217 +- .../api/test_api_protobuf_generator.py | 67 + 6 files changed, 1273 insertions(+), 1363 deletions(-) diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 8fd24dc502..f6524b9e4a 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -7,25 +7,20 @@ namespace esphome::api { -bool HelloRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->api_version_major = value; - break; - case 3: - this->api_version_minor = value; - break; - default: - return false; - } - return true; -} -bool HelloRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool HelloRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->client_info = StringRef(reinterpret_cast(value.data()), value.size()); break; - } + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->api_version_major = value.as_varint(); + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->api_version_minor = value.as_varint(); + break; default: return false; } @@ -49,10 +44,11 @@ uint32_t HelloResponse::calc_size_msg(const void *self) { size += 2 + msg.name.size(); return size; } -bool DisconnectRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->reason = static_cast(value); +bool DisconnectRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->reason = static_cast(value.as_varint()); break; default: return false; @@ -471,38 +467,38 @@ uint32_t CoverStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool CoverCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 4: - this->has_position = value != 0; - break; - case 6: - this->has_tilt = value != 0; - break; - case 8: - this->stop = value != 0; - break; -#ifdef USE_DEVICES - case 9: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool CoverCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool CoverCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 5: + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_position = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(5, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->position = value.as_float(); break; - case 7: + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_tilt = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(7, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->tilt = value.as_float(); break; + case PROTO_DECODE_CASE(8, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->stop = value.as_varint() != 0; + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(9, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -586,61 +582,58 @@ uint32_t FanStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool FanCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->has_state = value != 0; - break; - case 3: - this->state = value != 0; - break; - case 6: - this->has_oscillating = value != 0; - break; - case 7: - this->oscillating = value != 0; - break; - case 8: - this->has_direction = value != 0; - break; - case 9: - this->direction = static_cast(value); - break; - case 10: - this->has_speed_level = value != 0; - break; - case 11: - this->speed_level = static_cast(value); - break; - case 12: - this->has_preset_mode = value != 0; - break; -#ifdef USE_DEVICES - case 14: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool FanCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 13: { - this->preset_mode = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool FanCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool FanCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_state = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->state = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_oscillating = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(7, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->oscillating = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(8, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_direction = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(9, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->direction = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(10, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_speed_level = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(11, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->speed_level = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(12, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_preset_mode = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(13, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->preset_mode = StringRef(reinterpret_cast(value.data()), value.size()); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(14, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -762,109 +755,122 @@ uint32_t LightStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool LightCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->has_state = value != 0; - break; - case 3: - this->state = value != 0; - break; - case 4: - this->has_brightness = value != 0; - break; - case 22: - this->has_color_mode = value != 0; - break; - case 23: - this->color_mode = static_cast(value); - break; - case 20: - this->has_color_brightness = value != 0; - break; - case 6: - this->has_rgb = value != 0; - break; - case 10: - this->has_white = value != 0; - break; - case 12: - this->has_color_temperature = value != 0; - break; - case 24: - this->has_cold_white = value != 0; - break; - case 26: - this->has_warm_white = value != 0; - break; - case 14: - this->has_transition_length = value != 0; - break; - case 15: - this->transition_length = value; - break; - case 16: - this->has_flash_length = value != 0; - break; - case 17: - this->flash_length = value; - break; - case 18: - this->has_effect = value != 0; - break; -#ifdef USE_DEVICES - case 28: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool LightCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 19: { - this->effect = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool LightCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool LightCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 5: + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_state = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->state = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_brightness = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(5, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->brightness = value.as_float(); break; - case 21: + case PROTO_DECODE_CASE(22, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_color_mode = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(23, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->color_mode = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(20, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_color_brightness = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(21, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->color_brightness = value.as_float(); break; - case 7: + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_rgb = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(7, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->red = value.as_float(); break; - case 8: + case PROTO_DECODE_CASE(8, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->green = value.as_float(); break; - case 9: + case PROTO_DECODE_CASE(9, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->blue = value.as_float(); break; - case 11: + case PROTO_DECODE_CASE(10, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_white = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(11, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->white = value.as_float(); break; - case 13: + case PROTO_DECODE_CASE(12, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_color_temperature = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(13, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->color_temperature = value.as_float(); break; - case 25: + case PROTO_DECODE_CASE(24, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_cold_white = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(25, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->cold_white = value.as_float(); break; - case 27: + case PROTO_DECODE_CASE(26, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_warm_white = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(27, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->warm_white = value.as_float(); break; + case PROTO_DECODE_CASE(14, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_transition_length = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(15, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->transition_length = value.as_varint(); + break; + case PROTO_DECODE_CASE(16, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_flash_length = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(17, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->flash_length = value.as_varint(); + break; + case PROTO_DECODE_CASE(18, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_effect = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(19, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->effect = StringRef(reinterpret_cast(value.data()), value.size()); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(28, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -1000,26 +1006,22 @@ uint32_t SwitchStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool SwitchCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->state = value != 0; - break; -#ifdef USE_DEVICES - case 3: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool SwitchCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool SwitchCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->state = value.as_varint() != 0; + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -1085,13 +1087,15 @@ uint32_t TextSensorStateResponse::calc_size_msg(const void *self) { return size; } #endif -bool SubscribeLogsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->level = static_cast(value); +bool SubscribeLogsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->level = static_cast(value.as_varint()); break; - case 2: - this->dump_config = value != 0; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->dump_config = value.as_varint() != 0; break; default: return false; @@ -1119,13 +1123,14 @@ SubscribeLogsResponse::calc_size_msg(const void *self) { return size; } #ifdef USE_API_NOISE -bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool NoiseEncryptionSetKeyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->key = value.data(); this->key_len = value.size(); break; - } default: return false; } @@ -1218,31 +1223,27 @@ uint32_t HomeassistantActionRequest::calc_size_msg(const void *self) { } #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES -bool HomeassistantActionResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->call_id = value; +bool HomeassistantActionResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->call_id = value.as_varint(); break; - case 2: - this->success = value != 0; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->success = value.as_varint() != 0; break; - default: - return false; - } - return true; -} -bool HomeassistantActionResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 3: { + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->error_message = StringRef(reinterpret_cast(value.data()), value.size()); break; - } #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - case 4: { + case PROTO_DECODE_CASE(4, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->response_data = value.data(); this->response_data_len = value.size(); break; - } #endif default: return false; @@ -1268,70 +1269,74 @@ uint32_t SubscribeHomeAssistantStateResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_bool(1, msg.once); return size; } -bool HomeAssistantStateResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool HomeAssistantStateResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->entity_id = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 2: { + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->state = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 3: { + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->attribute = StringRef(reinterpret_cast(value.data()), value.size()); break; - } default: return false; } return true; } #endif -bool DSTRule::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->time_seconds = decode_zigzag32(static_cast(value)); +bool DSTRule::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->time_seconds = decode_zigzag32(static_cast(value.as_varint())); break; - case 2: - this->day = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->day = value.as_varint(); break; - case 3: - this->type = static_cast(value); + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->type = static_cast(value.as_varint()); break; - case 4: - this->month = value; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->month = value.as_varint(); break; - case 5: - this->week = value; + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->week = value.as_varint(); break; - case 6: - this->day_of_week = value; + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->day_of_week = value.as_varint(); break; default: return false; } return true; } -bool ParsedTimezone::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->std_offset_seconds = decode_zigzag32(static_cast(value)); +bool ParsedTimezone::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->std_offset_seconds = decode_zigzag32(static_cast(value.as_varint())); break; - case 2: - this->dst_offset_seconds = decode_zigzag32(static_cast(value)); + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->dst_offset_seconds = decode_zigzag32(static_cast(value.as_varint())); break; - default: - return false; - } - return true; -} -bool ParsedTimezone::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 3: + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); value.decode_to_message(this->dst_start); break; - case 4: + case PROTO_DECODE_CASE(4, 2): + PROTO_DECODE_GUARD(wire_type, 2); value.decode_to_message(this->dst_end); break; default: @@ -1339,9 +1344,14 @@ bool ParsedTimezone::decode_length(uint32_t field_id, ProtoLengthDelimited value } return true; } -bool GetTimeResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 3: +bool GetTimeResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); + this->epoch_seconds = value.as_fixed32(); + break; + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); value.decode_to_message(this->parsed_timezone); this->has_parsed_timezone = true; break; @@ -1350,16 +1360,6 @@ bool GetTimeResponse::decode_length(uint32_t field_id, ProtoLengthDelimited valu } return true; } -bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: - this->epoch_seconds = value.as_fixed32(); - break; - default: - return false; - } - return true; -} #ifdef USE_API_USER_DEFINED_ACTIONS uint8_t *ListEntitiesServicesArgument::encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) { const auto &msg = *static_cast(self); @@ -1417,50 +1417,44 @@ uint32_t ListEntitiesServicesResponse::calc_size_msg(const void *self) { #endif return size; } -bool ExecuteServiceArgument::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->bool_ = value != 0; +bool ExecuteServiceArgument::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->bool_ = value.as_varint() != 0; break; - case 2: - this->legacy_int = static_cast(value); + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->legacy_int = static_cast(value.as_varint()); break; - case 5: - this->int_ = decode_zigzag32(static_cast(value)); - break; - case 6: - this->bool_array.push_back(value != 0); - break; - case 7: - this->int_array.push_back(decode_zigzag32(static_cast(value))); - break; - default: - return false; - } - return true; -} -bool ExecuteServiceArgument::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 4: { - this->string_ = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - case 9: - this->string_array.push_back(value.as_string()); - break; - default: - return false; - } - return true; -} -bool ExecuteServiceArgument::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 3: + case PROTO_DECODE_CASE(3, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->float_ = value.as_float(); break; - case 8: + case PROTO_DECODE_CASE(4, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->string_ = StringRef(reinterpret_cast(value.data()), value.size()); + break; + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->int_ = decode_zigzag32(static_cast(value.as_varint())); + break; + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->bool_array.push_back(value.as_varint() != 0); + break; + case PROTO_DECODE_CASE(7, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->int_array.push_back(decode_zigzag32(static_cast(value.as_varint()))); + break; + case PROTO_DECODE_CASE(8, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->float_array.push_back(value.as_float()); break; + case PROTO_DECODE_CASE(9, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->string_array.push_back(value.as_string()); + break; default: return false; } @@ -1477,39 +1471,29 @@ void ExecuteServiceArgument::decode(const uint8_t *buffer, size_t length) { this->string_array.init(count_string_array); ProtoDecodableMessage::decode(buffer, length); } -bool ExecuteServiceRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { -#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES - case 3: - this->call_id = value; +bool ExecuteServiceRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); + this->key = value.as_fixed32(); break; -#endif -#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES - case 4: - this->return_response = value != 0; - break; -#endif - default: - return false; - } - return true; -} -bool ExecuteServiceRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 2: + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->args.emplace_back(); value.decode_to_message(this->args.back()); break; - default: - return false; - } - return true; -} -bool ExecuteServiceRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: - this->key = value.as_fixed32(); +#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->call_id = value.as_varint(); break; +#endif +#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->return_response = value.as_varint() != 0; + break; +#endif default: return false; } @@ -1600,13 +1584,15 @@ uint32_t CameraImageResponse::calc_size_msg(const void *self) { #endif return size; } -bool CameraImageRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->single = value != 0; +bool CameraImageRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->single = value.as_varint() != 0; break; - case 2: - this->stream = value != 0; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->stream = value.as_varint() != 0; break; default: return false; @@ -1775,92 +1761,98 @@ uint32_t ClimateStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool ClimateCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->has_mode = value != 0; - break; - case 3: - this->mode = static_cast(value); - break; - case 4: - this->has_target_temperature = value != 0; - break; - case 6: - this->has_target_temperature_low = value != 0; - break; - case 8: - this->has_target_temperature_high = value != 0; - break; - case 12: - this->has_fan_mode = value != 0; - break; - case 13: - this->fan_mode = static_cast(value); - break; - case 14: - this->has_swing_mode = value != 0; - break; - case 15: - this->swing_mode = static_cast(value); - break; - case 16: - this->has_custom_fan_mode = value != 0; - break; - case 18: - this->has_preset = value != 0; - break; - case 19: - this->preset = static_cast(value); - break; - case 20: - this->has_custom_preset = value != 0; - break; - case 22: - this->has_target_humidity = value != 0; - break; -#ifdef USE_DEVICES - case 24: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool ClimateCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 17: { - this->custom_fan_mode = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - case 21: { - this->custom_preset = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool ClimateCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 5: + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_mode = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->mode = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_target_temperature = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(5, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->target_temperature = value.as_float(); break; - case 7: + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_target_temperature_low = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(7, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->target_temperature_low = value.as_float(); break; - case 9: + case PROTO_DECODE_CASE(8, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_target_temperature_high = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(9, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->target_temperature_high = value.as_float(); break; - case 23: + case PROTO_DECODE_CASE(12, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_fan_mode = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(13, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->fan_mode = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(14, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_swing_mode = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(15, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->swing_mode = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(16, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_custom_fan_mode = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(17, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->custom_fan_mode = StringRef(reinterpret_cast(value.data()), value.size()); + break; + case PROTO_DECODE_CASE(18, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_preset = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(19, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->preset = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(20, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_custom_preset = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(21, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->custom_preset = StringRef(reinterpret_cast(value.data()), value.size()); + break; + case PROTO_DECODE_CASE(22, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_target_humidity = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(23, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->target_humidity = value.as_float(); break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(24, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -1961,39 +1953,41 @@ uint32_t WaterHeaterStateResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_float(1, msg.target_temperature_high); return size; } -bool WaterHeaterCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->has_fields = value; - break; - case 3: - this->mode = static_cast(value); - break; -#ifdef USE_DEVICES - case 5: - this->device_id = value; - break; -#endif - case 6: - this->state = value; - break; - default: - return false; - } - return true; -} -bool WaterHeaterCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool WaterHeaterCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 4: + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_fields = value.as_varint(); + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->mode = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(4, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->target_temperature = value.as_float(); break; - case 7: +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->state = value.as_varint(); + break; + case PROTO_DECODE_CASE(7, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->target_temperature_low = value.as_float(); break; - case 8: + case PROTO_DECODE_CASE(8, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->target_temperature_high = value.as_float(); break; default: @@ -2077,26 +2071,22 @@ uint32_t NumberStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool NumberCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { -#ifdef USE_DEVICES - case 3: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool NumberCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool NumberCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 2: + case PROTO_DECODE_CASE(2, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->state = value.as_float(); break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -2166,34 +2156,22 @@ uint32_t SelectStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool SelectCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { -#ifdef USE_DEVICES - case 3: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool SelectCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 2: { - this->state = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool SelectCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool SelectCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->state = StringRef(reinterpret_cast(value.data()), value.size()); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -2265,55 +2243,50 @@ uint32_t SirenStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool SirenCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->has_state = value != 0; - break; - case 3: - this->state = value != 0; - break; - case 4: - this->has_tone = value != 0; - break; - case 6: - this->has_duration = value != 0; - break; - case 7: - this->duration = value; - break; - case 8: - this->has_volume = value != 0; - break; -#ifdef USE_DEVICES - case 10: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool SirenCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 5: { - this->tone = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool SirenCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool SirenCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 9: + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_state = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->state = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_tone = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(5, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->tone = StringRef(reinterpret_cast(value.data()), value.size()); + break; + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_duration = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(7, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->duration = value.as_varint(); + break; + case PROTO_DECODE_CASE(8, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_volume = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(9, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->volume = value.as_float(); break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(10, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -2381,40 +2354,30 @@ uint32_t LockStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool LockCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->command = static_cast(value); - break; - case 3: - this->has_code = value != 0; - break; -#ifdef USE_DEVICES - case 5: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool LockCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 4: { - this->code = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool LockCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool LockCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->command = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_code = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(4, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->code = StringRef(reinterpret_cast(value.data()), value.size()); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -2456,23 +2419,18 @@ uint32_t ListEntitiesButtonResponse::calc_size_msg(const void *self) { #endif return size; } -bool ButtonCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { -#ifdef USE_DEVICES - case 2: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool ButtonCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool ButtonCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -2569,55 +2527,51 @@ uint32_t MediaPlayerStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool MediaPlayerCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->has_command = value != 0; - break; - case 3: - this->command = static_cast(value); - break; - case 4: - this->has_volume = value != 0; - break; - case 6: - this->has_media_url = value != 0; - break; - case 8: - this->has_announcement = value != 0; - break; - case 9: - this->announcement = value != 0; - break; -#ifdef USE_DEVICES - case 10: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool MediaPlayerCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 7: { - this->media_url = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool MediaPlayerCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool MediaPlayerCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 5: + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_command = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->command = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_volume = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(5, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->volume = value.as_float(); break; + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_media_url = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(7, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->media_url = StringRef(reinterpret_cast(value.data()), value.size()); + break; + case PROTO_DECODE_CASE(8, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_announcement = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(9, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->announcement = value.as_varint() != 0; + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(10, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -2625,10 +2579,12 @@ bool MediaPlayerCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value } #endif #ifdef USE_BLUETOOTH_PROXY -bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->flags = value; +bool SubscribeBluetoothLEAdvertisementsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->flags = value.as_varint(); break; default: return false; @@ -2677,19 +2633,23 @@ BluetoothLERawAdvertisementsResponse::calc_size_msg(const void *self) { } #endif #ifdef USE_BLUETOOTH_PROXY_CONNECTIONS -bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothDeviceRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; - case 2: - this->request_type = static_cast(value); + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->request_type = static_cast(value.as_varint()); break; - case 3: - this->has_address_type = value != 0; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_address_type = value.as_varint() != 0; break; - case 4: - this->address_type = value; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address_type = value.as_varint(); break; default: return false; @@ -2715,10 +2675,12 @@ uint32_t BluetoothDeviceConnectionResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_int32(1, msg.error); return size; } -bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothGATTGetServicesRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; default: return false; @@ -2843,13 +2805,16 @@ uint32_t BluetoothGATTGetServicesDoneResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_uint64(1, msg.address); return size; } -bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothGATTReadRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; - case 2: - this->handle = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->handle = value.as_varint(); break; default: return false; @@ -2872,82 +2837,82 @@ uint32_t BluetoothGATTReadResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data_len_); return size; } -bool BluetoothGATTWriteRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothGATTWriteRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; - case 2: - this->handle = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->handle = value.as_varint(); break; - case 3: - this->response = value != 0; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->response = value.as_varint() != 0; break; - default: - return false; - } - return true; -} -bool BluetoothGATTWriteRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 4: { + case PROTO_DECODE_CASE(4, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data = value.data(); this->data_len = value.size(); break; - } default: return false; } return true; } -bool BluetoothGATTReadDescriptorRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothGATTReadDescriptorRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; - case 2: - this->handle = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->handle = value.as_varint(); break; default: return false; } return true; } -bool BluetoothGATTWriteDescriptorRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothGATTWriteDescriptorRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; - case 2: - this->handle = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->handle = value.as_varint(); break; - default: - return false; - } - return true; -} -bool BluetoothGATTWriteDescriptorRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 3: { + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data = value.data(); this->data_len = value.size(); break; - } default: return false; } return true; } -bool BluetoothGATTNotifyRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothGATTNotifyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; - case 2: - this->handle = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->handle = value.as_varint(); break; - case 3: - this->enable = value != 0; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->enable = value.as_varint() != 0; break; default: return false; @@ -3110,10 +3075,12 @@ uint32_t BluetoothScannerStateResponse::calc_size_msg(const void *self) { size += msg.configured_mode ? 2 : 0; return size; } -bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->mode = static_cast(value); +bool BluetoothScannerSetModeRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->mode = static_cast(value.as_varint()); break; default: return false; @@ -3122,13 +3089,16 @@ bool BluetoothScannerSetModeRequest::decode_varint(uint32_t field_id, proto_vari } #endif #ifdef USE_VOICE_ASSISTANT -bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->subscribe = value != 0; +bool SubscribeVoiceAssistantRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->subscribe = value.as_varint() != 0; break; - case 2: - this->flags = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->flags = value.as_varint(); break; default: return false; @@ -3173,47 +3143,45 @@ uint32_t VoiceAssistantRequest::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.wake_word_phrase.size()); return size; } -bool VoiceAssistantResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->port = value; +bool VoiceAssistantResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->port = value.as_varint(); break; - case 2: - this->error = value != 0; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->error = value.as_varint() != 0; break; default: return false; } return true; } -bool VoiceAssistantEventData::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool VoiceAssistantEventData::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->name = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 2: { + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->value = StringRef(reinterpret_cast(value.data()), value.size()); break; - } default: return false; } return true; } -bool VoiceAssistantEventResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->event_type = static_cast(value); +bool VoiceAssistantEventResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->event_type = static_cast(value.as_varint()); break; - default: - return false; - } - return true; -} -bool VoiceAssistantEventResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 2: + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data.emplace_back(); value.decode_to_message(this->data.back()); break; @@ -3222,28 +3190,22 @@ bool VoiceAssistantEventResponse::decode_length(uint32_t field_id, ProtoLengthDe } return true; } -bool VoiceAssistantAudio::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->end = value != 0; - break; - default: - return false; - } - return true; -} -bool VoiceAssistantAudio::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool VoiceAssistantAudio::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data = value.data(); this->data_len = value.size(); break; - } - case 3: { + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->end = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data2 = value.data(); this->data2_len = value.size(); break; - } default: return false; } @@ -3265,64 +3227,57 @@ uint32_t VoiceAssistantAudio::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data2_len); return size; } -bool VoiceAssistantTimerEventResponse::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->event_type = static_cast(value); +bool VoiceAssistantTimerEventResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->event_type = static_cast(value.as_varint()); break; - case 4: - this->total_seconds = value; - break; - case 5: - this->seconds_left = value; - break; - case 6: - this->is_active = value != 0; - break; - default: - return false; - } - return true; -} -bool VoiceAssistantTimerEventResponse::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 2: { + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->timer_id = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 3: { + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->name = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - default: - return false; - } - return true; -} -bool VoiceAssistantAnnounceRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 4: - this->start_conversation = value != 0; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->total_seconds = value.as_varint(); + break; + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->seconds_left = value.as_varint(); + break; + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->is_active = value.as_varint() != 0; break; default: return false; } return true; } -bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool VoiceAssistantAnnounceRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->media_id = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 2: { + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->text = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 3: { + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->preannounce_media_id = StringRef(reinterpret_cast(value.data()), value.size()); break; - } + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->start_conversation = value.as_varint() != 0; + break; default: return false; } @@ -3363,49 +3318,47 @@ uint32_t VoiceAssistantWakeWord::calc_size_msg(const void *self) { } return size; } -bool VoiceAssistantExternalWakeWord::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 5: - this->model_size = value; - break; - default: - return false; - } - return true; -} -bool VoiceAssistantExternalWakeWord::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool VoiceAssistantExternalWakeWord::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->id = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 2: { + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->wake_word = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 3: + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->trained_languages.push_back(value.as_string()); break; - case 4: { + case PROTO_DECODE_CASE(4, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->model_type = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 6: { + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->model_size = value.as_varint(); + break; + case PROTO_DECODE_CASE(6, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->model_hash = StringRef(reinterpret_cast(value.data()), value.size()); break; - } - case 7: { + case PROTO_DECODE_CASE(7, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->url = StringRef(reinterpret_cast(value.data()), value.size()); break; - } default: return false; } return true; } -bool VoiceAssistantConfigurationRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: +bool VoiceAssistantConfigurationRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->external_wake_words.emplace_back(); value.decode_to_message(this->external_wake_words.back()); break; @@ -3443,9 +3396,11 @@ uint32_t VoiceAssistantConfigurationResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_uint32(1, msg.max_active_wake_words); return size; } -bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: +bool VoiceAssistantSetConfiguration::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->active_wake_words.push_back(value.as_string()); break; default: @@ -3515,37 +3470,27 @@ uint32_t AlarmControlPanelStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool AlarmControlPanelCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->command = static_cast(value); - break; -#ifdef USE_DEVICES - case 4: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool AlarmControlPanelCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 3: { - this->code = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool AlarmControlPanelCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool AlarmControlPanelCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->command = static_cast(value.as_varint()); + break; + case PROTO_DECODE_CASE(3, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->code = StringRef(reinterpret_cast(value.data()), value.size()); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -3615,34 +3560,22 @@ uint32_t TextStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool TextCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { -#ifdef USE_DEVICES - case 3: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool TextCommandRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 2: { - this->state = StringRef(reinterpret_cast(value.data()), value.size()); - break; - } - default: - return false; - } - return true; -} -bool TextCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool TextCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); + this->state = StringRef(reinterpret_cast(value.data()), value.size()); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -3708,32 +3641,30 @@ uint32_t DateStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool DateCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->year = value; - break; - case 3: - this->month = value; - break; - case 4: - this->day = value; - break; -#ifdef USE_DEVICES - case 5: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool DateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool DateCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->year = value.as_varint(); + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->month = value.as_varint(); + break; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->day = value.as_varint(); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -3799,32 +3730,30 @@ uint32_t TimeStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool TimeCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->hour = value; - break; - case 3: - this->minute = value; - break; - case 4: - this->second = value; - break; -#ifdef USE_DEVICES - case 5: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool TimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool TimeCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->hour = value.as_varint(); + break; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->minute = value.as_varint(); + break; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->second = value.as_varint(); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -3960,32 +3889,30 @@ uint32_t ValveStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool ValveCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->has_position = value != 0; - break; - case 4: - this->stop = value != 0; - break; -#ifdef USE_DEVICES - case 5: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool ValveCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool ValveCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 3: + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->has_position = value.as_varint() != 0; + break; + case PROTO_DECODE_CASE(3, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->position = value.as_float(); break; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->stop = value.as_varint() != 0; + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -4049,26 +3976,22 @@ uint32_t DateTimeStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool DateTimeCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { -#ifdef USE_DEVICES - case 3: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool DateTimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool DateTimeCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; - case 2: + case PROTO_DECODE_CASE(2, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->epoch_seconds = value.as_fixed32(); break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -4148,26 +4071,22 @@ uint32_t UpdateStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool UpdateCommandRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 2: - this->command = static_cast(value); - break; -#ifdef USE_DEVICES - case 3: - this->device_id = value; - break; -#endif - default: - return false; - } - return true; -} -bool UpdateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 1: +bool UpdateCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 5): + PROTO_DECODE_GUARD(wire_type, 5); this->key = value.as_fixed32(); break; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->command = static_cast(value.as_varint()); + break; +#ifdef USE_DEVICES + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); + break; +#endif default: return false; } @@ -4175,13 +4094,13 @@ bool UpdateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { } #endif #ifdef USE_ZWAVE_PROXY -bool ZWaveProxyFrame::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 1: { +bool ZWaveProxyFrame::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data = value.data(); this->data_len = value.size(); break; - } default: return false; } @@ -4203,23 +4122,17 @@ ZWaveProxyFrame::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data_len); return size; } -bool ZWaveProxyRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->type = static_cast(value); +bool ZWaveProxyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->type = static_cast(value.as_varint()); break; - default: - return false; - } - return true; -} -bool ZWaveProxyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 2: { + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data = value.data(); this->data_len = value.size(); break; - } default: return false; } @@ -4293,44 +4206,36 @@ uint32_t ListEntitiesInfraredResponse::calc_size_msg(const void *self) { } #endif #if defined(USE_IR_RF) || defined(USE_RADIO_FREQUENCY) -bool InfraredRFTransmitRawTimingsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { +bool InfraredRFTransmitRawTimingsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { #ifdef USE_DEVICES - case 1: - this->device_id = value; + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->device_id = value.as_varint(); break; #endif - case 3: - this->carrier_frequency = value; + case PROTO_DECODE_CASE(2, 5): + PROTO_DECODE_GUARD(wire_type, 5); + this->key = value.as_fixed32(); break; - case 4: - this->repeat_count = value; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->carrier_frequency = value.as_varint(); break; - case 6: - this->modulation = value; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->repeat_count = value.as_varint(); break; - default: - return false; - } - return true; -} -bool InfraredRFTransmitRawTimingsRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 5: { + case PROTO_DECODE_CASE(5, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->timings_data_ = value.data(); this->timings_length_ = value.size(); this->timings_count_ = count_packed_varints(value.data(), value.size()); break; - } - default: - return false; - } - return true; -} -bool InfraredRFTransmitRawTimingsRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { - switch (field_id) { - case 2: - this->key = value.as_fixed32(); + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->modulation = value.as_varint(); break; default: return false; @@ -4412,25 +4317,32 @@ uint32_t ListEntitiesRadioFrequencyResponse::calc_size_msg(const void *self) { } #endif #ifdef USE_SERIAL_PROXY -bool SerialProxyConfigureRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->instance = value; +bool SerialProxyConfigureRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->instance = value.as_varint(); break; - case 2: - this->baudrate = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->baudrate = value.as_varint(); break; - case 3: - this->flow_control = value != 0; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->flow_control = value.as_varint() != 0; break; - case 4: - this->parity = static_cast(value); + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->parity = static_cast(value.as_varint()); break; - case 5: - this->stop_bits = value; + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->stop_bits = value.as_varint(); break; - case 6: - this->data_size = value; + case PROTO_DECODE_CASE(6, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->data_size = value.as_varint(); break; default: return false; @@ -4455,45 +4367,44 @@ SerialProxyDataReceived::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data_len_); return size; } -bool SerialProxyWriteRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->instance = value; +bool SerialProxyWriteRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->instance = value.as_varint(); break; - default: - return false; - } - return true; -} -bool SerialProxyWriteRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) { - switch (field_id) { - case 2: { + case PROTO_DECODE_CASE(2, 2): + PROTO_DECODE_GUARD(wire_type, 2); this->data = value.data(); this->data_len = value.size(); break; - } default: return false; } return true; } -bool SerialProxySetModemPinsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->instance = value; +bool SerialProxySetModemPinsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->instance = value.as_varint(); break; - case 2: - this->line_states = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->line_states = value.as_varint(); break; default: return false; } return true; } -bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->instance = value; +bool SerialProxyGetModemPinsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->instance = value.as_varint(); break; default: return false; @@ -4517,13 +4428,15 @@ uint32_t SerialProxyGetModemPinsResponse::calc_size_msg(const void *self) { size += msg.status ? 2 : 0; return size; } -bool SerialProxyRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->instance = value; +bool SerialProxyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->instance = value.as_varint(); break; - case 2: - this->type = static_cast(value); + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->type = static_cast(value.as_varint()); break; default: return false; @@ -4550,22 +4463,28 @@ uint32_t SerialProxyRequestResponse::calc_size_msg(const void *self) { } #endif #ifdef USE_BLUETOOTH_PROXY_CONNECTIONS -bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, proto_varint_value_t value) { - switch (field_id) { - case 1: - this->address = value; +bool BluetoothSetConnectionParamsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, + ProtoFieldValue value) { + switch (PROTO_DECODE_KEY(tag, field_id)) { + case PROTO_DECODE_CASE(1, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->address = value.as_varint(); break; - case 2: - this->min_interval = value; + case PROTO_DECODE_CASE(2, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->min_interval = value.as_varint(); break; - case 3: - this->max_interval = value; + case PROTO_DECODE_CASE(3, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->max_interval = value.as_varint(); break; - case 4: - this->latency = value; + case PROTO_DECODE_CASE(4, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->latency = value.as_varint(); break; - case 5: - this->timeout = value; + case PROTO_DECODE_CASE(5, 0): + PROTO_DECODE_GUARD(wire_type, 0); + this->timeout = value.as_varint(); break; default: return false; diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 0c33ac5bc2..6241545de3 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -424,8 +424,7 @@ class HelloRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class HelloResponse final : public ProtoMessage { public: @@ -469,7 +468,7 @@ class DisconnectRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class DisconnectResponse final : public ProtoMessage { public: @@ -845,8 +844,7 @@ class CoverCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_FAN @@ -920,9 +918,7 @@ class FanCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_LIGHT @@ -1018,9 +1014,7 @@ class LightCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_SENSOR @@ -1125,8 +1119,7 @@ class SwitchCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_TEXT_SENSOR @@ -1186,7 +1179,7 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class SubscribeLogsResponse final : public ProtoMessage { public: @@ -1229,7 +1222,7 @@ class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class NoiseEncryptionSetKeyResponse final : public ProtoMessage { public: @@ -1323,8 +1316,7 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_API_HOMEASSISTANT_STATES @@ -1365,7 +1357,7 @@ class HomeAssistantStateResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif class GetTimeRequest final : public ProtoMessage { @@ -1394,7 +1386,7 @@ class DSTRule final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class ParsedTimezone final : public ProtoDecodableMessage { public: @@ -1407,8 +1399,7 @@ class ParsedTimezone final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class GetTimeResponse final : public ProtoDecodableMessage { public: @@ -1425,8 +1416,7 @@ class GetTimeResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #ifdef USE_API_USER_DEFINED_ACTIONS class ListEntitiesServicesArgument final : public ProtoMessage { @@ -1494,9 +1484,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class ExecuteServiceRequest final : public ProtoDecodableMessage { public: @@ -1519,9 +1507,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES @@ -1612,7 +1598,7 @@ class CameraImageRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_CLIMATE @@ -1718,9 +1704,7 @@ class ClimateCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_WATER_HEATER @@ -1792,8 +1776,7 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_NUMBER @@ -1856,8 +1839,7 @@ class NumberCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_SELECT @@ -1915,9 +1897,7 @@ class SelectCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_SIREN @@ -1983,9 +1963,7 @@ class SirenCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_LOCK @@ -2047,9 +2025,7 @@ class LockCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_BUTTON @@ -2085,8 +2061,7 @@ class ButtonCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_MEDIA_PLAYER @@ -2172,9 +2147,7 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_BLUETOOTH_PROXY @@ -2191,7 +2164,7 @@ class SubscribeBluetoothLEAdvertisementsRequest final : public ProtoDecodableMes #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothLERawAdvertisement final : public ProtoMessage { public: @@ -2245,7 +2218,7 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothDeviceConnectionResponse final : public ProtoMessage { public: @@ -2283,7 +2256,7 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothGATTDescriptor final : public ProtoMessage { public: @@ -2394,7 +2367,7 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothGATTReadResponse final : public ProtoMessage { public: @@ -2440,8 +2413,7 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { public: @@ -2457,7 +2429,7 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { public: @@ -2475,8 +2447,7 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { public: @@ -2493,7 +2464,7 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothGATTNotifyDataResponse final : public ProtoMessage { public: @@ -2711,7 +2682,7 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_VOICE_ASSISTANT @@ -2729,7 +2700,7 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantAudioSettings final : public ProtoMessage { public: @@ -2786,7 +2757,7 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantEventData final : public ProtoDecodableMessage { public: @@ -2797,7 +2768,7 @@ class VoiceAssistantEventData final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantEventResponse final : public ProtoDecodableMessage { public: @@ -2813,8 +2784,7 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantAudio final : public ProtoDecodableMessage { public: @@ -2839,8 +2809,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { public: @@ -2860,8 +2829,7 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { public: @@ -2879,8 +2847,7 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantAnnounceFinished final : public ProtoMessage { public: @@ -2933,8 +2900,7 @@ class VoiceAssistantExternalWakeWord final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { public: @@ -2949,7 +2915,7 @@ class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class VoiceAssistantConfigurationResponse final : public ProtoMessage { public: @@ -2986,7 +2952,7 @@ class VoiceAssistantSetConfiguration final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_ALARM_CONTROL_PANEL @@ -3046,9 +3012,7 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_TEXT @@ -3109,9 +3073,7 @@ class TextCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_DATETIME_DATE @@ -3172,8 +3134,7 @@ class DateCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_DATETIME_TIME @@ -3234,8 +3195,7 @@ class TimeCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_EVENT @@ -3341,8 +3301,7 @@ class ValveCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_DATETIME_DATETIME @@ -3399,8 +3358,7 @@ class DateTimeCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_UPDATE @@ -3465,8 +3423,7 @@ class UpdateCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; #endif #ifdef USE_ZWAVE_PROXY @@ -3490,7 +3447,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class ZWaveProxyRequest final : public ProtoDecodableMessage { public: @@ -3513,8 +3470,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class ZWaveProxyRequestResponse final : public ProtoMessage { public: @@ -3584,9 +3540,7 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_32bit(uint32_t field_id, Proto32Bit value) override; - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class InfraredRFReceiveEvent final : public ProtoMessage { public: @@ -3657,7 +3611,7 @@ class SerialProxyConfigureRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class SerialProxyDataReceived final : public ProtoMessage { public: @@ -3700,8 +3654,7 @@ class SerialProxyWriteRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override; - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { public: @@ -3717,7 +3670,7 @@ class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { public: @@ -3732,7 +3685,7 @@ class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class SerialProxyGetModemPinsResponse final : public ProtoMessage { public: @@ -3770,7 +3723,7 @@ class SerialProxyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class SerialProxyRequestResponse final : public ProtoMessage { public: @@ -3814,7 +3767,7 @@ class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_varint(uint32_t field_id, proto_varint_value_t value) override; + bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; }; class BluetoothSetConnectionParamsResponse final : public ProtoMessage { public: diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 236e4a474a..f5ce38d3db 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -226,6 +226,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { uint32_t field_type = tag & WIRE_TYPE_MASK; uint32_t field_id = tag >> 3; ptr += res.consumed; + ProtoFieldValue value; switch (field_type) { case WIRE_TYPE_VARINT: { // VarInt @@ -234,10 +235,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer)); return; } - if (!this->decode_varint(field_id, res.value)) { - ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu64 "!", field_id, - static_cast(res.value)); - } + value.varint_ = res.value; ptr += res.consumed; break; } @@ -253,9 +251,8 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer)); return; } - if (!this->decode_length(field_id, ProtoLengthDelimited(ptr, field_length))) { - ESP_LOGV(TAG, "Cannot decode Length Delimited field %" PRIu32 "!", field_id); - } + value.ld_.data = ptr; + value.ld_.len = field_length; ptr += field_length; break; } @@ -264,16 +261,12 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer)); return; } - uint32_t val; #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ // Protobuf fixed32 is little-endian — direct load on LE platforms - memcpy(&val, ptr, 4); + memcpy(&value.fixed32_, ptr, 4); #else - val = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]); + value.fixed32_ = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]); #endif - if (!this->decode_32bit(field_id, Proto32Bit(val))) { - ESP_LOGV(TAG, "Cannot decode 32-bit field %" PRIu32 " with value %" PRIu32 "!", field_id, val); - } ptr += 4; break; } @@ -281,6 +274,9 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { ESP_LOGV(TAG, "Invalid field type %" PRIu32 " at offset %ld", field_type, (long) (ptr - buffer)); return; } + if (!this->decode_field(tag, field_id, field_type, value)) { + ESP_LOGV(TAG, "Cannot decode field %" PRIu32 " with wire type %" PRIu32 "!", field_id, field_type); + } } } diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 3510430623..c49fdcb431 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -170,40 +170,59 @@ class ProtoVarInt { class ProtoMessage; class ProtoSize; -class ProtoLengthDelimited { - public: - explicit ProtoLengthDelimited(const uint8_t *value, size_t length) : value_(value), length_(length) {} - std::string as_string() const { return std::string(reinterpret_cast(this->value_), this->length_); } +// Generated decode_field() bodies switch on PROTO_DECODE_KEY and label each case with +// PROTO_DECODE_CASE. Embedded targets compile switches to compare chains (ESP-IDF passes +// -fno-jump-tables), so keying on the full wire tag costs one compare per field and needs no +// separate wire type check. The host compiler turns the dense field number switch into a jump +// table, so there the key is the field number and PROTO_DECODE_GUARD rejects the wrong wire type +// before the field is read. Both forms drop a field that arrives with a wire type it does not +// declare, which is what the per wire type virtuals did before. +#ifdef USE_HOST +#define PROTO_DECODE_KEY(tag, field_id) (field_id) +#define PROTO_DECODE_CASE(field_id, wire_type) (field_id) +#define PROTO_DECODE_GUARD(wire_type, expected) \ + if ((wire_type) != (expected)) \ + return false +#else +#define PROTO_DECODE_KEY(tag, field_id) (tag) +#define PROTO_DECODE_CASE(field_id, wire_type) (((field_id) << 3) | (wire_type)) +#define PROTO_DECODE_GUARD(wire_type, expected) (void) 0 +#endif - // Direct access to raw data without string allocation - const uint8_t *data() const { return this->value_; } - size_t size() const { return this->length_; } +/// Payload of one decoded field, handed to ProtoDecodableMessage::decode_field() together with +/// the field number and wire type. The wire type says which member is live; the accessors do not check. +/// Eight bytes with or without USE_API_VARINT64, so it travels in two registers on every target. +struct ProtoFieldValue { + union { + proto_varint_value_t varint_; + struct { + const uint8_t *data; + uint32_t len; + } ld_; + uint32_t fixed32_; + }; - /// Decode the length-delimited data into a message instance. + proto_varint_value_t as_varint() const { return this->varint_; } + + // Length-delimited accessors + const uint8_t *data() const { return this->ld_.data; } + size_t size() const { return this->ld_.len; } + std::string as_string() const { return std::string(reinterpret_cast(this->ld_.data), this->ld_.len); } + /// Decode the length-delimited payload into a message instance. /// Template preserves concrete type so decode() resolves statically. - template void decode_to_message(T &msg) const; + template void decode_to_message(T &msg) const { msg.decode(this->ld_.data, this->ld_.len); } - protected: - const uint8_t *const value_; - const size_t length_; -}; - -class Proto32Bit { - public: - explicit Proto32Bit(uint32_t value) : value_(value) {} - uint32_t as_fixed32() const { return this->value_; } - int32_t as_sfixed32() const { return static_cast(this->value_); } + // Fixed32 accessors + uint32_t as_fixed32() const { return this->fixed32_; } + int32_t as_sfixed32() const { return static_cast(this->fixed32_); } float as_float() const { union { uint32_t raw; float value; } s{}; - s.raw = this->value_; + s.raw = this->fixed32_; return s.value; } - - protected: - const uint32_t value_; }; // NOTE: Proto64Bit class removed - wire type 1 (64-bit fixed) not supported @@ -728,10 +747,16 @@ class ProtoDecodableMessage : public ProtoMessage { protected: ~ProtoDecodableMessage() = default; - virtual bool decode_varint(uint32_t field_id, proto_varint_value_t value) { return false; } - virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value) { return false; } - virtual bool decode_32bit(uint32_t field_id, Proto32Bit value) { return false; } - // NOTE: decode_64bit removed - wire type 1 not supported + /// Store one decoded field. \p field_id and \p wire_type are \p tag split in two; the loop has all + /// three at hand, so passing them costs nothing and the generated switch keys on whichever form is + /// cheapest for the target (see PROTO_DECODE_KEY). \p wire_type selects the live ProtoFieldValue + /// member; overrides reject a field that arrived with a wire type other than the one it declares. + /// Return false for unknown or mismatched fields. + /// One virtual instead of one per wire type keeps each message's vtable at a single slot. + // NOTE: wire type 1 (64-bit fixed) is not supported + virtual bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { + return false; + } }; class ProtoSize { @@ -951,11 +976,6 @@ template inline void ProtoWriteBuffer::encode_optional_sub_message(u this->encode_optional_sub_message(field_id, T::calc_size_msg(&value), &value, &T::encode_msg); } -// Template decode_to_message - preserves concrete type so decode() resolves statically -template void ProtoLengthDelimited::decode_to_message(T &msg) const { - msg.decode(this->value_, this->length_); -} - template const char *proto_enum_to_string(T value); // ProtoService removed — its methods were inlined into APIConnection. diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index b31ac7847c..289a314f31 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -229,12 +229,27 @@ class TypeInfo(ABC): def class_member(self) -> str: return f"{self.cpp_type} {self.field_name}{{{self.default_value}}};" + # decode_field() cases are keyed through the PROTO_DECODE_* macros in proto.h: embedded + # targets switch on the full wire tag, the host switches on the field number and guards + # the wire type. Either way a field that arrives with the wrong wire type falls through + # to "return false" instead of being read from the wrong ProtoFieldValue member. + def decode_case(self, wire_type: WireType, body: str) -> str: + """Emit one decode_field() case for a field and the wire type it expects.""" + return ( + f"case PROTO_DECODE_CASE({self.number}, {int(wire_type)}):\n" + f" PROTO_DECODE_GUARD(wire_type, {int(wire_type)});\n" + f" {body}\n" + f" break;" + ) + @property def decode_varint_content(self) -> str: content = self.decode_varint if content is None: return None - return f"case {self.number}: this->{self.field_name} = {content}; break;" + return self.decode_case( + WireType.VARINT, f"this->{self.field_name} = {content};" + ) decode_varint = None @@ -243,7 +258,9 @@ class TypeInfo(ABC): content = self.decode_length if content is None: return None - return f"case {self.number}: this->{self.field_name} = {content}; break;" + return self.decode_case( + WireType.LENGTH_DELIMITED, f"this->{self.field_name} = {content};" + ) decode_length = None @@ -252,19 +269,12 @@ class TypeInfo(ABC): content = self.decode_32bit if content is None: return None - return f"case {self.number}: this->{self.field_name} = {content}; break;" + return self.decode_case( + WireType.FIXED32, f"this->{self.field_name} = {content};" + ) decode_32bit = None - @property - def decode_64bit_content(self) -> str: - content = self.decode_64bit - if content is None: - return None - return f"case {self.number}: this->{self.field_name} = {content}; break;" - - decode_64bit = None - # Mapping from encode_func to raw encode expression template. # When a forced field has a single-byte tag, the code generator emits # write_raw_byte(tag) + raw encode instead of the full encode_* method, @@ -638,7 +648,6 @@ class DoubleType(FixedSizeTypeMixin, TypeInfo): # Unsupported but defined for completeness cpp_type = "double" default_value = "0.0" - decode_64bit = "value.as_double()" encode_func = "encode_double" wire_type = WireType.FIXED64 # Uses wire type 1 according to protobuf spec @@ -693,7 +702,7 @@ class Int64Type(VarintTypeMixin, TypeInfo): cpp_type = "int64_t" _varint_max_bits = 64 default_value = "0" - decode_varint = "static_cast(value)" + decode_varint = "static_cast(value.as_varint())" encode_func = "encode_int64" wire_type = WireType.VARINT # Uses wire type 0 @@ -714,7 +723,7 @@ class UInt64Type(VarintTypeMixin, TypeInfo): cpp_type = "uint64_t" _varint_max_bits = 64 default_value = "0" - decode_varint = "value" + decode_varint = "value.as_varint()" encode_func = "encode_uint64" wire_type = WireType.VARINT # Uses wire type 0 @@ -749,7 +758,7 @@ class Int32Type(VarintTypeMixin, TypeInfo): cpp_type = "int32_t" _varint_max_bits = 64 # int32 is sign-extended to 64 bits in protobuf default_value = "0" - decode_varint = "static_cast(value)" + decode_varint = "static_cast(value.as_varint())" encode_func = "encode_int32" wire_type = WireType.VARINT # Uses wire type 0 @@ -769,7 +778,6 @@ class Int32Type(VarintTypeMixin, TypeInfo): class Fixed64Type(FixedSizeTypeMixin, TypeInfo): cpp_type = "uint64_t" default_value = "0" - decode_64bit = "value.as_fixed64()" encode_func = "encode_fixed64" wire_type = WireType.FIXED64 # Uses wire type 1 @@ -824,7 +832,7 @@ class BoolType(VarintTypeMixin, TypeInfo): _varint_max_bits = 1 cpp_type = "bool" default_value = "false" - decode_varint = "value != 0" + decode_varint = "value.as_varint() != 0" encode_func = "encode_bool" wire_type = WireType.VARINT # Uses wire type 0 @@ -1014,13 +1022,15 @@ class MessageType(TypeInfo): # decode_to_message() cannot report failure, so setting the flag # afterwards only documents intent; a status-returning decode could # gate it for real without touching callers. - return ( - f"case {self.number}:\n" - f" value.decode_to_message(this->{self.field_name});\n" - f" this->has_{self.name} = true;\n" - f" break;" + return self.decode_case( + WireType.LENGTH_DELIMITED, + f"value.decode_to_message(this->{self.field_name});\n" + f" this->has_{self.name} = true;", ) - return f"case {self.number}: value.decode_to_message(this->{self.field_name}); break;" + return self.decode_case( + WireType.LENGTH_DELIMITED, + f"value.decode_to_message(this->{self.field_name});", + ) def dump(self, name: str) -> str: return f"{name}.dump_to(out);" @@ -1216,11 +1226,11 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): @property def decode_length_content(self) -> str | None: - return f"""case {self.number}: {{ - this->{self.field_name} = value.data(); - this->{self.field_name}_len = value.size(); - break; - }}""" + return self.decode_case( + WireType.LENGTH_DELIMITED, + f"this->{self.field_name} = value.data();\n" + f" this->{self.field_name}_len = value.size();", + ) def dump(self, name: str) -> str: return ( @@ -1281,10 +1291,10 @@ class PointerToStringBufferType(PointerToBufferTypeBase): @property def decode_length_content(self) -> str | None: - return f"""case {self.number}: {{ - this->{self.field_name} = StringRef(reinterpret_cast(value.data()), value.size()); - break; - }}""" + return self.decode_case( + WireType.LENGTH_DELIMITED, + f"this->{self.field_name} = StringRef(reinterpret_cast(value.data()), value.size());", + ) def dump(self, name: str) -> str: # Not used since we use dump_field, but required by abstract base class @@ -1355,12 +1365,12 @@ class PackedBufferTypeInfo(TypeInfo): @property def decode_length_content(self) -> str: """Store pointer to buffer and calculate count of packed varints.""" - return f"""case {self.number}: {{ - this->{self.field_name}_data_ = value.data(); - this->{self.field_name}_length_ = value.size(); - this->{self.field_name}_count_ = count_packed_varints(value.data(), value.size()); - break; - }}""" + return self.decode_case( + WireType.LENGTH_DELIMITED, + f"this->{self.field_name}_data_ = value.data();\n" + f" this->{self.field_name}_length_ = value.size();\n" + f" this->{self.field_name}_count_ = count_packed_varints(value.data(), value.size());", + ) @property def encode_content(self) -> str: @@ -1446,16 +1456,13 @@ class FixedArrayBytesType(TypeInfo): @property def decode_length_content(self) -> str: - o = f"case {self.number}: {{\n" - o += " const std::string &data_str = value.as_string();\n" - o += f" this->{self.field_name}_len = data_str.size();\n" - o += f" if (this->{self.field_name}_len > {self.array_size}) {{\n" - o += f" this->{self.field_name}_len = {self.array_size};\n" - o += " }\n" - o += f" memcpy(this->{self.field_name}, data_str.data(), this->{self.field_name}_len);\n" - o += " break;\n" - o += "}" - return o + body = "const std::string &data_str = value.as_string();\n" + body += f" this->{self.field_name}_len = data_str.size();\n" + body += f" if (this->{self.field_name}_len > {self.array_size}) {{\n" + body += f" this->{self.field_name}_len = {self.array_size};\n" + body += " }\n" + body += f" memcpy(this->{self.field_name}, data_str.data(), this->{self.field_name}_len);" + return self.decode_case(WireType.LENGTH_DELIMITED, body) @property def encode_content(self) -> str: @@ -1518,7 +1525,7 @@ class UInt32Type(VarintTypeMixin, TypeInfo): cpp_type = "uint32_t" _varint_max_bits = 32 default_value = "0" - decode_varint = "value" + decode_varint = "value.as_varint()" encode_func = "encode_uint32" wire_type = WireType.VARINT # Uses wire type 0 @@ -1547,7 +1554,7 @@ class EnumType(VarintTypeMixin, TypeInfo): @property def decode_varint(self) -> str: - return f"static_cast<{self.cpp_type}>(value)" + return f"static_cast<{self.cpp_type}>(value.as_varint())" default_value = "" wire_type = WireType.VARINT # Uses wire type 0 @@ -1620,7 +1627,6 @@ class SFixed32Type(FixedSizeTypeMixin, TypeInfo): class SFixed64Type(FixedSizeTypeMixin, TypeInfo): cpp_type = "int64_t" default_value = "0" - decode_64bit = "value.as_sfixed64()" encode_func = "encode_sfixed64" wire_type = WireType.FIXED64 # Uses wire type 1 @@ -1647,7 +1653,7 @@ class SInt32Type(VarintTypeMixin, TypeInfo): cpp_type = "int32_t" _varint_max_bits = 32 # zigzag encoding keeps it 32-bit default_value = "0" - decode_varint = "decode_zigzag32(static_cast(value))" + decode_varint = "decode_zigzag32(static_cast(value.as_varint()))" encode_func = "encode_sint32" wire_type = WireType.VARINT # Uses wire type 0 @@ -1668,7 +1674,7 @@ class SInt64Type(VarintTypeMixin, TypeInfo): cpp_type = "int64_t" _varint_max_bits = 64 default_value = "0" - decode_varint = "decode_zigzag64(value)" + decode_varint = "decode_zigzag64(value.as_varint())" encode_func = "encode_sint64" wire_type = WireType.VARINT # Uses wire type 0 @@ -2138,8 +2144,8 @@ class RepeatedTypeInfo(TypeInfo): content = self._ti.decode_varint if content is None: return None - return ( - f"case {self.number}: this->{self.field_name}.push_back({content}); break;" + return self.decode_case( + WireType.VARINT, f"this->{self.field_name}.push_back({content});" ) @property @@ -2150,11 +2156,15 @@ class RepeatedTypeInfo(TypeInfo): content = self._ti.decode_length if content is None and isinstance(self._ti, MessageType): # Special handling for non-template message decoding - return f"case {self.number}: this->{self.field_name}.emplace_back(); value.decode_to_message(this->{self.field_name}.back()); break;" + return self.decode_case( + WireType.LENGTH_DELIMITED, + f"this->{self.field_name}.emplace_back();\n" + f" value.decode_to_message(this->{self.field_name}.back());", + ) if content is None: return None - return ( - f"case {self.number}: this->{self.field_name}.push_back({content}); break;" + return self.decode_case( + WireType.LENGTH_DELIMITED, f"this->{self.field_name}.push_back({content});" ) @property @@ -2165,20 +2175,8 @@ class RepeatedTypeInfo(TypeInfo): content = self._ti.decode_32bit if content is None: return None - return ( - f"case {self.number}: this->{self.field_name}.push_back({content}); break;" - ) - - @property - def decode_64bit_content(self) -> str: - # Pointer fields don't support decoding - if self._use_pointer: - return None - content = self._ti.decode_64bit - if content is None: - return None - return ( - f"case {self.number}: this->{self.field_name}.push_back({content}); break;" + return self.decode_case( + WireType.FIXED32, f"this->{self.field_name}.push_back({content});" ) @property @@ -2595,10 +2593,7 @@ def build_message_type( ) -> tuple[str, str, str]: public_content: list[str] = [] protected_content: list[str] = [] - decode_varint: list[str] = [] - decode_length: list[str] = [] - decode_32bit: list[str] = [] - decode_64bit: list[str] = [] + decode: list[str] = [] encode: list[str] = [] dump: list[str] = [] size_calc: list[str] = [] @@ -2727,22 +2722,13 @@ def build_message_type( if field.options.HasExtension(pb.field_ifdef): field_ifdef = field.options.Extensions[pb.field_ifdef] - if ti.decode_varint_content: - decode_varint.extend( - wrap_with_ifdef(ti.decode_varint_content, field_ifdef) - ) - if ti.decode_length_content: - decode_length.extend( - wrap_with_ifdef(ti.decode_length_content, field_ifdef) - ) - if ti.decode_32bit_content: - decode_32bit.extend( - wrap_with_ifdef(ti.decode_32bit_content, field_ifdef) - ) - if ti.decode_64bit_content: - decode_64bit.extend( - wrap_with_ifdef(ti.decode_64bit_content, field_ifdef) - ) + for case in ( + ti.decode_varint_content, + ti.decode_length_content, + ti.decode_32bit_content, + ): + if case: + decode.extend(wrap_with_ifdef(case, field_ifdef)) if ti.dump_content: # Check for field_ifdef option for dump as well field_ifdef = None @@ -2752,49 +2738,18 @@ def build_message_type( dump.extend(wrap_with_ifdef(ti.dump_content, field_ifdef)) cpp = "" - if decode_varint: - o = f"bool {desc.name}::decode_varint(uint32_t field_id, proto_varint_value_t value) {{\n" - o += " switch (field_id) {\n" - o += indent("\n".join(decode_varint), " ") + "\n" + if decode: + # One virtual per message: the shared decode loop parses the payload for the wire + # type and hands it over with the tag, so a single switch covers every field. + o = f"bool {desc.name}::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) {{\n" + o += " switch (PROTO_DECODE_KEY(tag, field_id)) {\n" + o += indent("\n".join(decode), " ") + "\n" o += " default: return false;\n" o += " }\n" o += " return true;\n" o += "}\n" cpp += o - prot = "bool decode_varint(uint32_t field_id, proto_varint_value_t value) override;" - protected_content.insert(0, prot) - if decode_length: - o = f"bool {desc.name}::decode_length(uint32_t field_id, ProtoLengthDelimited value) {{\n" - o += " switch (field_id) {\n" - o += indent("\n".join(decode_length), " ") + "\n" - o += " default: return false;\n" - o += " }\n" - o += " return true;\n" - o += "}\n" - cpp += o - prot = "bool decode_length(uint32_t field_id, ProtoLengthDelimited value) override;" - protected_content.insert(0, prot) - if decode_32bit: - o = f"bool {desc.name}::decode_32bit(uint32_t field_id, Proto32Bit value) {{\n" - o += " switch (field_id) {\n" - o += indent("\n".join(decode_32bit), " ") + "\n" - o += " default: return false;\n" - o += " }\n" - o += " return true;\n" - o += "}\n" - cpp += o - prot = "bool decode_32bit(uint32_t field_id, Proto32Bit value) override;" - protected_content.insert(0, prot) - if decode_64bit: - o = f"bool {desc.name}::decode_64bit(uint32_t field_id, Proto64Bit value) {{\n" - o += " switch (field_id) {\n" - o += indent("\n".join(decode_64bit), " ") + "\n" - o += " default: return false;\n" - o += " }\n" - o += " return true;\n" - o += "}\n" - cpp += o - prot = "bool decode_64bit(uint32_t field_id, Proto64Bit value) override;" + prot = "bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override;" protected_content.insert(0, prot) # Generate custom decode() override for messages with FixedVector fields diff --git a/tests/unit_tests/components/api/test_api_protobuf_generator.py b/tests/unit_tests/components/api/test_api_protobuf_generator.py index c182520c5a..a59681b12e 100644 --- a/tests/unit_tests/components/api/test_api_protobuf_generator.py +++ b/tests/unit_tests/components/api/test_api_protobuf_generator.py @@ -18,7 +18,9 @@ sys.path.insert(0, str(Path(__file__).parents[4] / "script" / "api_protobuf")) import aioesphomeapi.api_options_pb2 as pb # noqa: E402 from api_protobuf import ( # noqa: E402 MAX_MESSAGE_ID, + SOURCE_CLIENT, _make_ifdef_line, + build_message_type, create_field_type_info, get_varint64_ifdef, validate_message_id, @@ -182,3 +184,68 @@ def test_multi_byte_tag_fixed32_falls_back_to_the_generic_helper( content = _encode_field(field_type, number=16) assert "write_tag_and_fixed32" not in content, content assert content.startswith("pos = ProtoEncode::encode_"), content + + +def _decode_cases(field_type: int, number: int) -> list[str]: + """Return the decode_field() case lines the generator emits for one decoded field.""" + field = descriptor_pb2.FieldDescriptorProto( + name="value", number=number, type=field_type + ) + ti = create_field_type_info(field, needs_decode=True, needs_encode=False) + return [ + case + for case in ( + ti.decode_varint_content, + ti.decode_length_content, + ti.decode_32bit_content, + ) + if case + ] + + +UINT32_T = descriptor_pb2.FieldDescriptorProto.TYPE_UINT32 +STRING_T = descriptor_pb2.FieldDescriptorProto.TYPE_STRING +BOOL_T = descriptor_pb2.FieldDescriptorProto.TYPE_BOOL + + +@pytest.mark.parametrize( + ("field_type", "number", "wire_type", "accessor"), + [ + (UINT32_T, 2, 0, "value.as_varint()"), + (BOOL_T, 3, 0, "value.as_varint() != 0"), + (STRING_T, 1, 2, "value.data()"), + (FLOAT, 4, 5, "value.as_float()"), + (FIXED32, 5, 5, "value.as_fixed32()"), + ], +) +def test_decode_cases_carry_field_number_and_wire_type( + field_type: int, number: int, wire_type: int, accessor: str +) -> None: + """Each decoded field yields one case keyed on its number and declared wire type.""" + cases = _decode_cases(field_type, number) + assert len(cases) == 1, cases + lines = cases[0].splitlines() + assert lines[0] == f"case PROTO_DECODE_CASE({number}, {wire_type}):", cases[0] + assert lines[1].strip() == f"PROTO_DECODE_GUARD(wire_type, {wire_type});", cases[0] + assert accessor in cases[0], cases[0] + + +def test_message_gets_a_single_decode_field_override() -> None: + """All wire types of a decoded message land in one decode_field() switch.""" + desc = descriptor_pb2.DescriptorProto(name="Mixed") + desc.field.add(name="name", number=1, type=STRING_T) + desc.field.add(name="count", number=2, type=UINT32_T) + desc.field.add(name="level", number=3, type=FLOAT) + header, cpp, _ = build_message_type(desc, {}, {"Mixed": SOURCE_CLIENT}) + decl = "bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override;" + assert header.count(decl) == 1 + assert "decode_varint" not in header and "decode_length" not in header + assert ( + cpp.count( + "bool Mixed::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) {" + ) + == 1 + ) + assert "switch (PROTO_DECODE_KEY(tag, field_id)) {" in cpp + for number, wire_type in ((1, 2), (2, 0), (3, 5)): + assert f"case PROTO_DECODE_CASE({number}, {wire_type}):" in cpp, cpp