From bcf812d62bc1266f17fc4eb3bfc349fc6e505387 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Mon, 7 Sep 2026 10:05:00 +0200 Subject: [PATCH] [api] Keep the decode loop register resident and inline the varint fast path CodSpeed showed the single virtual costing 7 to 18 percent on the decode benchmarks. The x86-64 disassembly pointed at the call, not the switch: passing the field number and wire type alongside the tag plus a 16 byte union payload kept five values live across the call, so the compiler spilled this, the end pointer and half of the payload to the stack and reloaded them for every field. decode_field() now takes only the tag, the payload pointer (already the loop cursor) and one scalar that holds the varint or fixed32 value or the payload length. The generated override wraps them in a ProtoFieldValue that never exists in memory. On the host the switch key is the field number derived with one shift and the guard compares the whole tag against the constant the case declares, which is the same two instructions the old per wire type dispatch cost. The loop also handles single byte varints inline instead of going through the parse result struct, which drops the materialized consumed count and its add on every tag and small value. --- esphome/components/api/api_pb2.cpp | 842 +++++++++--------- esphome/components/api/api_pb2.h | 118 +-- esphome/components/api/proto.cpp | 56 +- esphome/components/api/proto.h | 70 +- script/api_protobuf/api_protobuf.py | 9 +- .../api/test_api_protobuf_generator.py | 11 +- 6 files changed, 578 insertions(+), 528 deletions(-) diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index f6524b9e4a..3594dabc32 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -7,18 +7,19 @@ namespace esphome::api { -bool HelloRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool HelloRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->client_info = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->api_version_major = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->api_version_minor = value.as_varint(); break; default: @@ -44,10 +45,11 @@ uint32_t HelloResponse::calc_size_msg(const void *self) { size += 2 + msg.name.size(); return size; } -bool DisconnectRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool DisconnectRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->reason = static_cast(value.as_varint()); break; default: @@ -467,35 +469,36 @@ uint32_t CoverStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool CoverCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool CoverCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->has_position = value.as_varint() != 0; break; case PROTO_DECODE_CASE(5, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 5, 5); this->position = value.as_float(); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->has_tilt = value.as_varint() != 0; break; case PROTO_DECODE_CASE(7, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 7, 5); this->tilt = value.as_float(); break; case PROTO_DECODE_CASE(8, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 8, 0); this->stop = value.as_varint() != 0; break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(9, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 9, 0); this->device_id = value.as_varint(); break; #endif @@ -582,55 +585,56 @@ uint32_t FanStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool FanCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool FanCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->has_state = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->state = value.as_varint() != 0; break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->has_oscillating = value.as_varint() != 0; break; case PROTO_DECODE_CASE(7, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 7, 0); this->oscillating = value.as_varint() != 0; break; case PROTO_DECODE_CASE(8, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 8, 0); this->has_direction = value.as_varint() != 0; break; case PROTO_DECODE_CASE(9, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 9, 0); this->direction = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(10, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 10, 0); this->has_speed_level = value.as_varint() != 0; break; case PROTO_DECODE_CASE(11, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 11, 0); this->speed_level = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(12, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 12, 0); this->has_preset_mode = value.as_varint() != 0; break; case PROTO_DECODE_CASE(13, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 13, 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); + PROTO_DECODE_GUARD(tag, 14, 0); this->device_id = value.as_varint(); break; #endif @@ -755,119 +759,120 @@ uint32_t LightStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool LightCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool LightCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->has_state = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->state = value.as_varint() != 0; break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->has_brightness = value.as_varint() != 0; break; case PROTO_DECODE_CASE(5, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 5, 5); this->brightness = value.as_float(); break; case PROTO_DECODE_CASE(22, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 22, 0); this->has_color_mode = value.as_varint() != 0; break; case PROTO_DECODE_CASE(23, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 23, 0); this->color_mode = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(20, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 20, 0); this->has_color_brightness = value.as_varint() != 0; break; case PROTO_DECODE_CASE(21, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 21, 5); this->color_brightness = value.as_float(); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->has_rgb = value.as_varint() != 0; break; case PROTO_DECODE_CASE(7, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 7, 5); this->red = value.as_float(); break; case PROTO_DECODE_CASE(8, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 8, 5); this->green = value.as_float(); break; case PROTO_DECODE_CASE(9, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 9, 5); this->blue = value.as_float(); break; case PROTO_DECODE_CASE(10, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 10, 0); this->has_white = value.as_varint() != 0; break; case PROTO_DECODE_CASE(11, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 11, 5); this->white = value.as_float(); break; case PROTO_DECODE_CASE(12, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 12, 0); this->has_color_temperature = value.as_varint() != 0; break; case PROTO_DECODE_CASE(13, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 13, 5); this->color_temperature = value.as_float(); break; case PROTO_DECODE_CASE(24, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 24, 0); this->has_cold_white = value.as_varint() != 0; break; case PROTO_DECODE_CASE(25, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 25, 5); this->cold_white = value.as_float(); break; case PROTO_DECODE_CASE(26, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 26, 0); this->has_warm_white = value.as_varint() != 0; break; case PROTO_DECODE_CASE(27, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 27, 5); this->warm_white = value.as_float(); break; case PROTO_DECODE_CASE(14, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 14, 0); this->has_transition_length = value.as_varint() != 0; break; case PROTO_DECODE_CASE(15, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 15, 0); this->transition_length = value.as_varint(); break; case PROTO_DECODE_CASE(16, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 16, 0); this->has_flash_length = value.as_varint() != 0; break; case PROTO_DECODE_CASE(17, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 17, 0); this->flash_length = value.as_varint(); break; case PROTO_DECODE_CASE(18, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 18, 0); this->has_effect = value.as_varint() != 0; break; case PROTO_DECODE_CASE(19, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 19, 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); + PROTO_DECODE_GUARD(tag, 28, 0); this->device_id = value.as_varint(); break; #endif @@ -1006,19 +1011,20 @@ uint32_t SwitchStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool SwitchCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SwitchCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->state = value.as_varint() != 0; break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->device_id = value.as_varint(); break; #endif @@ -1087,14 +1093,15 @@ uint32_t TextSensorStateResponse::calc_size_msg(const void *self) { return size; } #endif -bool SubscribeLogsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SubscribeLogsRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->level = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->dump_config = value.as_varint() != 0; break; default: @@ -1123,11 +1130,11 @@ SubscribeLogsResponse::calc_size_msg(const void *self) { return size; } #ifdef USE_API_NOISE -bool NoiseEncryptionSetKeyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool NoiseEncryptionSetKeyRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->key = value.data(); this->key_len = value.size(); break; @@ -1223,24 +1230,24 @@ uint32_t HomeassistantActionRequest::calc_size_msg(const void *self) { } #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES -bool HomeassistantActionResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool HomeassistantActionResponse::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->call_id = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->success = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); this->error_message = StringRef(reinterpret_cast(value.data()), value.size()); break; #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON case PROTO_DECODE_CASE(4, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 4, 2); this->response_data = value.data(); this->response_data_len = value.size(); break; @@ -1269,19 +1276,19 @@ uint32_t SubscribeHomeAssistantStateResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_bool(1, msg.once); return size; } -bool HomeAssistantStateResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool HomeAssistantStateResponse::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->entity_id = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->state = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); this->attribute = StringRef(reinterpret_cast(value.data()), value.size()); break; default: @@ -1290,30 +1297,31 @@ bool HomeAssistantStateResponse::decode_field(uint32_t tag, uint32_t field_id, u return true; } #endif -bool DSTRule::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool DSTRule::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->time_seconds = decode_zigzag32(static_cast(value.as_varint())); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->day = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->type = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->month = value.as_varint(); break; case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->week = value.as_varint(); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->day_of_week = value.as_varint(); break; default: @@ -1321,22 +1329,23 @@ bool DSTRule::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, } return true; } -bool ParsedTimezone::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ParsedTimezone::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->std_offset_seconds = decode_zigzag32(static_cast(value.as_varint())); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->dst_offset_seconds = decode_zigzag32(static_cast(value.as_varint())); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); value.decode_to_message(this->dst_start); break; case PROTO_DECODE_CASE(4, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 4, 2); value.decode_to_message(this->dst_end); break; default: @@ -1344,14 +1353,15 @@ bool ParsedTimezone::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire } return true; } -bool GetTimeResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool GetTimeResponse::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->epoch_seconds = value.as_fixed32(); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); value.decode_to_message(this->parsed_timezone); this->has_parsed_timezone = true; break; @@ -1417,42 +1427,43 @@ uint32_t ListEntitiesServicesResponse::calc_size_msg(const void *self) { #endif return size; } -bool ExecuteServiceArgument::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ExecuteServiceArgument::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->bool_ = value.as_varint() != 0; break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->legacy_int = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(3, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 3, 5); this->float_ = value.as_float(); break; case PROTO_DECODE_CASE(4, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 4, 2); this->string_ = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->int_ = decode_zigzag32(static_cast(value.as_varint())); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->bool_array.push_back(value.as_varint() != 0); break; case PROTO_DECODE_CASE(7, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 7, 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); + PROTO_DECODE_GUARD(tag, 8, 5); this->float_array.push_back(value.as_float()); break; case PROTO_DECODE_CASE(9, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 9, 2); this->string_array.push_back(value.as_string()); break; default: @@ -1471,26 +1482,27 @@ void ExecuteServiceArgument::decode(const uint8_t *buffer, size_t length) { this->string_array.init(count_string_array); ProtoDecodableMessage::decode(buffer, length); } -bool ExecuteServiceRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ExecuteServiceRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->args.emplace_back(); value.decode_to_message(this->args.back()); break; #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 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); + PROTO_DECODE_GUARD(tag, 4, 0); this->return_response = value.as_varint() != 0; break; #endif @@ -1584,14 +1596,15 @@ uint32_t CameraImageResponse::calc_size_msg(const void *self) { #endif return size; } -bool CameraImageRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool CameraImageRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->single = value.as_varint() != 0; break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->stream = value.as_varint() != 0; break; default: @@ -1761,95 +1774,96 @@ uint32_t ClimateStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool ClimateCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ClimateCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->has_mode = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->mode = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->has_target_temperature = value.as_varint() != 0; break; case PROTO_DECODE_CASE(5, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 5, 5); this->target_temperature = value.as_float(); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->has_target_temperature_low = value.as_varint() != 0; break; case PROTO_DECODE_CASE(7, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 7, 5); this->target_temperature_low = value.as_float(); break; case PROTO_DECODE_CASE(8, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 8, 0); this->has_target_temperature_high = value.as_varint() != 0; break; case PROTO_DECODE_CASE(9, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 9, 5); this->target_temperature_high = value.as_float(); break; case PROTO_DECODE_CASE(12, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 12, 0); this->has_fan_mode = value.as_varint() != 0; break; case PROTO_DECODE_CASE(13, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 13, 0); this->fan_mode = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(14, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 14, 0); this->has_swing_mode = value.as_varint() != 0; break; case PROTO_DECODE_CASE(15, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 15, 0); this->swing_mode = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(16, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 16, 0); this->has_custom_fan_mode = value.as_varint() != 0; break; case PROTO_DECODE_CASE(17, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 17, 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); + PROTO_DECODE_GUARD(tag, 18, 0); this->has_preset = value.as_varint() != 0; break; case PROTO_DECODE_CASE(19, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 19, 0); this->preset = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(20, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 20, 0); this->has_custom_preset = value.as_varint() != 0; break; case PROTO_DECODE_CASE(21, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 21, 2); this->custom_preset = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(22, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 22, 0); this->has_target_humidity = value.as_varint() != 0; break; case PROTO_DECODE_CASE(23, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 23, 5); this->target_humidity = value.as_float(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(24, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 24, 0); this->device_id = value.as_varint(); break; #endif @@ -1953,41 +1967,41 @@ uint32_t WaterHeaterStateResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_float(1, msg.target_temperature_high); return size; } -bool WaterHeaterCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool WaterHeaterCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->has_fields = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->mode = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(4, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 4, 5); this->target_temperature = value.as_float(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->device_id = value.as_varint(); break; #endif case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->state = value.as_varint(); break; case PROTO_DECODE_CASE(7, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 7, 5); this->target_temperature_low = value.as_float(); break; case PROTO_DECODE_CASE(8, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 8, 5); this->target_temperature_high = value.as_float(); break; default: @@ -2071,19 +2085,20 @@ uint32_t NumberStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool NumberCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool NumberCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 2, 5); this->state = value.as_float(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->device_id = value.as_varint(); break; #endif @@ -2156,19 +2171,20 @@ uint32_t SelectStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool SelectCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SelectCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 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); + PROTO_DECODE_GUARD(tag, 3, 0); this->device_id = value.as_varint(); break; #endif @@ -2243,47 +2259,48 @@ uint32_t SirenStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool SirenCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SirenCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->has_state = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->state = value.as_varint() != 0; break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->has_tone = value.as_varint() != 0; break; case PROTO_DECODE_CASE(5, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 5, 2); this->tone = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->has_duration = value.as_varint() != 0; break; case PROTO_DECODE_CASE(7, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 7, 0); this->duration = value.as_varint(); break; case PROTO_DECODE_CASE(8, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 8, 0); this->has_volume = value.as_varint() != 0; break; case PROTO_DECODE_CASE(9, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 9, 5); this->volume = value.as_float(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(10, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 10, 0); this->device_id = value.as_varint(); break; #endif @@ -2354,27 +2371,28 @@ uint32_t LockStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool LockCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool LockCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->command = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->has_code = value.as_varint() != 0; break; case PROTO_DECODE_CASE(4, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 4, 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); + PROTO_DECODE_GUARD(tag, 5, 0); this->device_id = value.as_varint(); break; #endif @@ -2419,15 +2437,16 @@ uint32_t ListEntitiesButtonResponse::calc_size_msg(const void *self) { #endif return size; } -bool ButtonCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ButtonCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->device_id = value.as_varint(); break; #endif @@ -2527,48 +2546,48 @@ uint32_t MediaPlayerStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool MediaPlayerCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool MediaPlayerCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->has_command = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->command = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->has_volume = value.as_varint() != 0; break; case PROTO_DECODE_CASE(5, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 5, 5); this->volume = value.as_float(); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->has_media_url = value.as_varint() != 0; break; case PROTO_DECODE_CASE(7, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 7, 2); this->media_url = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(8, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 8, 0); this->has_announcement = value.as_varint() != 0; break; case PROTO_DECODE_CASE(9, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 9, 0); this->announcement = value.as_varint() != 0; break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(10, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 10, 0); this->device_id = value.as_varint(); break; #endif @@ -2579,11 +2598,12 @@ bool MediaPlayerCommandRequest::decode_field(uint32_t tag, uint32_t field_id, ui } #endif #ifdef USE_BLUETOOTH_PROXY -bool SubscribeBluetoothLEAdvertisementsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SubscribeBluetoothLEAdvertisementsRequest::decode_field(uint32_t tag, const uint8_t *data, + proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->flags = value.as_varint(); break; default: @@ -2633,22 +2653,23 @@ BluetoothLERawAdvertisementsResponse::calc_size_msg(const void *self) { } #endif #ifdef USE_BLUETOOTH_PROXY_CONNECTIONS -bool BluetoothDeviceRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothDeviceRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->request_type = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->has_address_type = value.as_varint() != 0; break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->address_type = value.as_varint(); break; default: @@ -2675,11 +2696,11 @@ uint32_t BluetoothDeviceConnectionResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_int32(1, msg.error); return size; } -bool BluetoothGATTGetServicesRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothGATTGetServicesRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; default: @@ -2805,15 +2826,15 @@ uint32_t BluetoothGATTGetServicesDoneResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_uint64(1, msg.address); return size; } -bool BluetoothGATTReadRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothGATTReadRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->handle = value.as_varint(); break; default: @@ -2837,23 +2858,23 @@ uint32_t BluetoothGATTReadResponse::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data_len_); return size; } -bool BluetoothGATTWriteRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothGATTWriteRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->handle = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->response = value.as_varint() != 0; break; case PROTO_DECODE_CASE(4, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 4, 2); this->data = value.data(); this->data_len = value.size(); break; @@ -2862,15 +2883,15 @@ bool BluetoothGATTWriteRequest::decode_field(uint32_t tag, uint32_t field_id, ui } return true; } -bool BluetoothGATTReadDescriptorRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothGATTReadDescriptorRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->handle = value.as_varint(); break; default: @@ -2878,19 +2899,19 @@ bool BluetoothGATTReadDescriptorRequest::decode_field(uint32_t tag, uint32_t fie } return true; } -bool BluetoothGATTWriteDescriptorRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothGATTWriteDescriptorRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->handle = value.as_varint(); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); this->data = value.data(); this->data_len = value.size(); break; @@ -2899,19 +2920,19 @@ bool BluetoothGATTWriteDescriptorRequest::decode_field(uint32_t tag, uint32_t fi } return true; } -bool BluetoothGATTNotifyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothGATTNotifyRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->handle = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->enable = value.as_varint() != 0; break; default: @@ -3075,11 +3096,11 @@ uint32_t BluetoothScannerStateResponse::calc_size_msg(const void *self) { size += msg.configured_mode ? 2 : 0; return size; } -bool BluetoothScannerSetModeRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothScannerSetModeRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->mode = static_cast(value.as_varint()); break; default: @@ -3089,15 +3110,15 @@ bool BluetoothScannerSetModeRequest::decode_field(uint32_t tag, uint32_t field_i } #endif #ifdef USE_VOICE_ASSISTANT -bool SubscribeVoiceAssistantRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SubscribeVoiceAssistantRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->subscribe = value.as_varint() != 0; break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->flags = value.as_varint(); break; default: @@ -3143,14 +3164,15 @@ uint32_t VoiceAssistantRequest::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.wake_word_phrase.size()); return size; } -bool VoiceAssistantResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantResponse::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->port = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->error = value.as_varint() != 0; break; default: @@ -3158,14 +3180,15 @@ bool VoiceAssistantResponse::decode_field(uint32_t tag, uint32_t field_id, uint3 } return true; } -bool VoiceAssistantEventData::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantEventData::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->name = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->value = StringRef(reinterpret_cast(value.data()), value.size()); break; default: @@ -3173,15 +3196,15 @@ bool VoiceAssistantEventData::decode_field(uint32_t tag, uint32_t field_id, uint } return true; } -bool VoiceAssistantEventResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantEventResponse::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->event_type = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->data.emplace_back(); value.decode_to_message(this->data.back()); break; @@ -3190,19 +3213,20 @@ bool VoiceAssistantEventResponse::decode_field(uint32_t tag, uint32_t field_id, } return true; } -bool VoiceAssistantAudio::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantAudio::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->data = value.data(); this->data_len = value.size(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->end = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); this->data2 = value.data(); this->data2_len = value.size(); break; @@ -3227,31 +3251,31 @@ uint32_t VoiceAssistantAudio::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data2_len); return size; } -bool VoiceAssistantTimerEventResponse::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantTimerEventResponse::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->event_type = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->timer_id = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); this->name = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->total_seconds = value.as_varint(); break; case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->seconds_left = value.as_varint(); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->is_active = value.as_varint() != 0; break; default: @@ -3259,23 +3283,23 @@ bool VoiceAssistantTimerEventResponse::decode_field(uint32_t tag, uint32_t field } return true; } -bool VoiceAssistantAnnounceRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantAnnounceRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->media_id = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->text = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 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); + PROTO_DECODE_GUARD(tag, 4, 0); this->start_conversation = value.as_varint() != 0; break; default: @@ -3318,35 +3342,35 @@ uint32_t VoiceAssistantWakeWord::calc_size_msg(const void *self) { } return size; } -bool VoiceAssistantExternalWakeWord::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantExternalWakeWord::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->id = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->wake_word = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 2); this->trained_languages.push_back(value.as_string()); break; case PROTO_DECODE_CASE(4, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 4, 2); this->model_type = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->model_size = value.as_varint(); break; case PROTO_DECODE_CASE(6, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 6, 2); this->model_hash = StringRef(reinterpret_cast(value.data()), value.size()); break; case PROTO_DECODE_CASE(7, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 7, 2); this->url = StringRef(reinterpret_cast(value.data()), value.size()); break; default: @@ -3354,11 +3378,11 @@ bool VoiceAssistantExternalWakeWord::decode_field(uint32_t tag, uint32_t field_i } return true; } -bool VoiceAssistantConfigurationRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantConfigurationRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->external_wake_words.emplace_back(); value.decode_to_message(this->external_wake_words.back()); break; @@ -3396,11 +3420,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_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool VoiceAssistantSetConfiguration::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->active_wake_words.push_back(value.as_string()); break; default: @@ -3470,24 +3494,24 @@ uint32_t AlarmControlPanelStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool AlarmControlPanelCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool AlarmControlPanelCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->command = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(3, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 3, 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); + PROTO_DECODE_GUARD(tag, 4, 0); this->device_id = value.as_varint(); break; #endif @@ -3560,19 +3584,20 @@ uint32_t TextStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool TextCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool TextCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 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); + PROTO_DECODE_GUARD(tag, 3, 0); this->device_id = value.as_varint(); break; #endif @@ -3641,27 +3666,28 @@ uint32_t DateStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool DateCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool DateCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->year = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->month = value.as_varint(); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->day = value.as_varint(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->device_id = value.as_varint(); break; #endif @@ -3730,27 +3756,28 @@ uint32_t TimeStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool TimeCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool TimeCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->hour = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->minute = value.as_varint(); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->second = value.as_varint(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->device_id = value.as_varint(); break; #endif @@ -3889,27 +3916,28 @@ uint32_t ValveStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool ValveCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ValveCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->has_position = value.as_varint() != 0; break; case PROTO_DECODE_CASE(3, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 3, 5); this->position = value.as_float(); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->stop = value.as_varint() != 0; break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->device_id = value.as_varint(); break; #endif @@ -3976,19 +4004,20 @@ uint32_t DateTimeStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool DateTimeCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool DateTimeCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 2, 5); this->epoch_seconds = value.as_fixed32(); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->device_id = value.as_varint(); break; #endif @@ -4071,19 +4100,20 @@ uint32_t UpdateStateResponse::calc_size_msg(const void *self) { #endif return size; } -bool UpdateCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool UpdateCommandRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 1, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->command = static_cast(value.as_varint()); break; #ifdef USE_DEVICES case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->device_id = value.as_varint(); break; #endif @@ -4094,10 +4124,11 @@ bool UpdateCommandRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_ } #endif #ifdef USE_ZWAVE_PROXY -bool ZWaveProxyFrame::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ZWaveProxyFrame::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 1, 2); this->data = value.data(); this->data_len = value.size(); break; @@ -4122,14 +4153,15 @@ ZWaveProxyFrame::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data_len); return size; } -bool ZWaveProxyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool ZWaveProxyRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->type = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->data = value.data(); this->data_len = value.size(); break; @@ -4206,35 +4238,35 @@ uint32_t ListEntitiesInfraredResponse::calc_size_msg(const void *self) { } #endif #if defined(USE_IR_RF) || defined(USE_RADIO_FREQUENCY) -bool InfraredRFTransmitRawTimingsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool InfraredRFTransmitRawTimingsRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { #ifdef USE_DEVICES case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->device_id = value.as_varint(); break; #endif case PROTO_DECODE_CASE(2, 5): - PROTO_DECODE_GUARD(wire_type, 5); + PROTO_DECODE_GUARD(tag, 2, 5); this->key = value.as_fixed32(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->carrier_frequency = value.as_varint(); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->repeat_count = value.as_varint(); break; case PROTO_DECODE_CASE(5, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 5, 2); this->timings_data_ = value.data(); this->timings_length_ = value.size(); this->timings_count_ = count_packed_varints(value.data(), value.size()); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->modulation = value.as_varint(); break; default: @@ -4317,31 +4349,31 @@ uint32_t ListEntitiesRadioFrequencyResponse::calc_size_msg(const void *self) { } #endif #ifdef USE_SERIAL_PROXY -bool SerialProxyConfigureRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SerialProxyConfigureRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->instance = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->baudrate = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->flow_control = value.as_varint() != 0; break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->parity = static_cast(value.as_varint()); break; case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->stop_bits = value.as_varint(); break; case PROTO_DECODE_CASE(6, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 6, 0); this->data_size = value.as_varint(); break; default: @@ -4367,14 +4399,15 @@ SerialProxyDataReceived::calc_size_msg(const void *self) { size += ProtoSize::calc_length(1, msg.data_len_); return size; } -bool SerialProxyWriteRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SerialProxyWriteRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->instance = value.as_varint(); break; case PROTO_DECODE_CASE(2, 2): - PROTO_DECODE_GUARD(wire_type, 2); + PROTO_DECODE_GUARD(tag, 2, 2); this->data = value.data(); this->data_len = value.size(); break; @@ -4383,15 +4416,15 @@ bool SerialProxyWriteRequest::decode_field(uint32_t tag, uint32_t field_id, uint } return true; } -bool SerialProxySetModemPinsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SerialProxySetModemPinsRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->instance = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->line_states = value.as_varint(); break; default: @@ -4399,11 +4432,11 @@ bool SerialProxySetModemPinsRequest::decode_field(uint32_t tag, uint32_t field_i } return true; } -bool SerialProxyGetModemPinsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SerialProxyGetModemPinsRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->instance = value.as_varint(); break; default: @@ -4428,14 +4461,15 @@ uint32_t SerialProxyGetModemPinsResponse::calc_size_msg(const void *self) { size += msg.status ? 2 : 0; return size; } -bool SerialProxyRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool SerialProxyRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->instance = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->type = static_cast(value.as_varint()); break; default: @@ -4463,27 +4497,27 @@ uint32_t SerialProxyRequestResponse::calc_size_msg(const void *self) { } #endif #ifdef USE_BLUETOOTH_PROXY_CONNECTIONS -bool BluetoothSetConnectionParamsRequest::decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, - ProtoFieldValue value) { - switch (PROTO_DECODE_KEY(tag, field_id)) { +bool BluetoothSetConnectionParamsRequest::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { + const ProtoFieldValue value(data, scalar); + switch (PROTO_DECODE_KEY(tag)) { case PROTO_DECODE_CASE(1, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 1, 0); this->address = value.as_varint(); break; case PROTO_DECODE_CASE(2, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 2, 0); this->min_interval = value.as_varint(); break; case PROTO_DECODE_CASE(3, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 3, 0); this->max_interval = value.as_varint(); break; case PROTO_DECODE_CASE(4, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 4, 0); this->latency = value.as_varint(); break; case PROTO_DECODE_CASE(5, 0): - PROTO_DECODE_GUARD(wire_type, 0); + PROTO_DECODE_GUARD(tag, 5, 0); this->timeout = value.as_varint(); break; default: diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index 6241545de3..771d82beb2 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -424,7 +424,7 @@ class HelloRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class HelloResponse final : public ProtoMessage { public: @@ -468,7 +468,7 @@ class DisconnectRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class DisconnectResponse final : public ProtoMessage { public: @@ -844,7 +844,7 @@ class CoverCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_FAN @@ -918,7 +918,7 @@ class FanCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_LIGHT @@ -1014,7 +1014,7 @@ class LightCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_SENSOR @@ -1119,7 +1119,7 @@ class SwitchCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_TEXT_SENSOR @@ -1179,7 +1179,7 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class SubscribeLogsResponse final : public ProtoMessage { public: @@ -1222,7 +1222,7 @@ class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class NoiseEncryptionSetKeyResponse final : public ProtoMessage { public: @@ -1316,7 +1316,7 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_API_HOMEASSISTANT_STATES @@ -1357,7 +1357,7 @@ class HomeAssistantStateResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif class GetTimeRequest final : public ProtoMessage { @@ -1386,7 +1386,7 @@ class DSTRule final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class ParsedTimezone final : public ProtoDecodableMessage { public: @@ -1399,7 +1399,7 @@ class ParsedTimezone final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class GetTimeResponse final : public ProtoDecodableMessage { public: @@ -1416,7 +1416,7 @@ class GetTimeResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #ifdef USE_API_USER_DEFINED_ACTIONS class ListEntitiesServicesArgument final : public ProtoMessage { @@ -1484,7 +1484,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class ExecuteServiceRequest final : public ProtoDecodableMessage { public: @@ -1507,7 +1507,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES @@ -1598,7 +1598,7 @@ class CameraImageRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_CLIMATE @@ -1704,7 +1704,7 @@ class ClimateCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_WATER_HEATER @@ -1776,7 +1776,7 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_NUMBER @@ -1839,7 +1839,7 @@ class NumberCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_SELECT @@ -1897,7 +1897,7 @@ class SelectCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_SIREN @@ -1963,7 +1963,7 @@ class SirenCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_LOCK @@ -2025,7 +2025,7 @@ class LockCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_BUTTON @@ -2061,7 +2061,7 @@ class ButtonCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_MEDIA_PLAYER @@ -2147,7 +2147,7 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_BLUETOOTH_PROXY @@ -2164,7 +2164,7 @@ class SubscribeBluetoothLEAdvertisementsRequest final : public ProtoDecodableMes #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothLERawAdvertisement final : public ProtoMessage { public: @@ -2218,7 +2218,7 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothDeviceConnectionResponse final : public ProtoMessage { public: @@ -2256,7 +2256,7 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothGATTDescriptor final : public ProtoMessage { public: @@ -2367,7 +2367,7 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothGATTReadResponse final : public ProtoMessage { public: @@ -2413,7 +2413,7 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { public: @@ -2429,7 +2429,7 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { public: @@ -2447,7 +2447,7 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { public: @@ -2464,7 +2464,7 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothGATTNotifyDataResponse final : public ProtoMessage { public: @@ -2682,7 +2682,7 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_VOICE_ASSISTANT @@ -2700,7 +2700,7 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantAudioSettings final : public ProtoMessage { public: @@ -2757,7 +2757,7 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantEventData final : public ProtoDecodableMessage { public: @@ -2768,7 +2768,7 @@ class VoiceAssistantEventData final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantEventResponse final : public ProtoDecodableMessage { public: @@ -2784,7 +2784,7 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantAudio final : public ProtoDecodableMessage { public: @@ -2809,7 +2809,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { public: @@ -2829,7 +2829,7 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { public: @@ -2847,7 +2847,7 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantAnnounceFinished final : public ProtoMessage { public: @@ -2900,7 +2900,7 @@ class VoiceAssistantExternalWakeWord final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { public: @@ -2915,7 +2915,7 @@ class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class VoiceAssistantConfigurationResponse final : public ProtoMessage { public: @@ -2952,7 +2952,7 @@ class VoiceAssistantSetConfiguration final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_ALARM_CONTROL_PANEL @@ -3012,7 +3012,7 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_TEXT @@ -3073,7 +3073,7 @@ class TextCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_DATETIME_DATE @@ -3134,7 +3134,7 @@ class DateCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_DATETIME_TIME @@ -3195,7 +3195,7 @@ class TimeCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_EVENT @@ -3301,7 +3301,7 @@ class ValveCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_DATETIME_DATETIME @@ -3358,7 +3358,7 @@ class DateTimeCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_UPDATE @@ -3423,7 +3423,7 @@ class UpdateCommandRequest final : public CommandProtoMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; #endif #ifdef USE_ZWAVE_PROXY @@ -3447,7 +3447,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class ZWaveProxyRequest final : public ProtoDecodableMessage { public: @@ -3470,7 +3470,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class ZWaveProxyRequestResponse final : public ProtoMessage { public: @@ -3540,7 +3540,7 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class InfraredRFReceiveEvent final : public ProtoMessage { public: @@ -3611,7 +3611,7 @@ class SerialProxyConfigureRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class SerialProxyDataReceived final : public ProtoMessage { public: @@ -3654,7 +3654,7 @@ class SerialProxyWriteRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { public: @@ -3670,7 +3670,7 @@ class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { public: @@ -3685,7 +3685,7 @@ class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class SerialProxyGetModemPinsResponse final : public ProtoMessage { public: @@ -3723,7 +3723,7 @@ class SerialProxyRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class SerialProxyRequestResponse final : public ProtoMessage { public: @@ -3767,7 +3767,7 @@ class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage { #endif protected: - bool decode_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override; + bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; }; class BluetoothSetConnectionParamsResponse final : public ProtoMessage { public: diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index f5ce38d3db..bc82d53dbf 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -214,45 +214,57 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { const uint8_t *ptr = buffer; const uint8_t *end = buffer + length; - while (ptr < end) { - // Parse field header - ptr < end guarantees len >= 1 + // Single-byte varints dominate real messages (tags, small lengths, bools, enums), so that case + // advances the cursor inline; a merged path would materialize the consumed count and add it. + auto read_varint = [&](proto_varint_value_t &value) ESPHOME_ALWAYS_INLINE { + if (ptr == end) + return false; + if ((*ptr & 0x80) == 0) [[likely]] { + value = *ptr++; + return true; + } auto res = ProtoVarInt::parse_non_empty(ptr, end - ptr); - if (!res.has_value()) { + if (!res.has_value()) + return false; + value = res.value; + ptr += res.consumed; + return true; + }; + + while (ptr < end) { + proto_varint_value_t tag_value; + if (!read_varint(tag_value)) { ESP_LOGV(TAG, "Invalid field start at offset %ld", (long) (ptr - buffer)); return; } - uint32_t tag = static_cast(res.value); + uint32_t tag = static_cast(tag_value); uint32_t field_type = tag & WIRE_TYPE_MASK; - uint32_t field_id = tag >> 3; - ptr += res.consumed; - ProtoFieldValue value; + // Payload start for scalar wire types; length-delimited fields advance it past the length. + const uint8_t *data = ptr; + proto_varint_value_t scalar; switch (field_type) { case WIRE_TYPE_VARINT: { // VarInt - res = ProtoVarInt::parse(ptr, end - ptr); - if (!res.has_value()) { + if (!read_varint(scalar)) { ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer)); return; } - value.varint_ = res.value; - ptr += res.consumed; break; } case WIRE_TYPE_LENGTH_DELIMITED: { // Length-delimited - res = ProtoVarInt::parse(ptr, end - ptr); - if (!res.has_value()) { + proto_varint_value_t length_value; + if (!read_varint(length_value)) { ESP_LOGV(TAG, "Invalid Length Delimited at offset %ld", (long) (ptr - buffer)); return; } - uint32_t field_length = static_cast(res.value); - ptr += res.consumed; + uint32_t field_length = static_cast(length_value); if (field_length > static_cast(end - ptr)) { ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer)); return; } - value.ld_.data = ptr; - value.ld_.len = field_length; + data = ptr; + scalar = field_length; ptr += field_length; break; } @@ -261,12 +273,14 @@ 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(&value.fixed32_, ptr, 4); + memcpy(&val, ptr, 4); #else - value.fixed32_ = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]); + val = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]); #endif + scalar = val; ptr += 4; break; } @@ -274,8 +288,8 @@ 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); + if (!this->decode_field(tag, data, scalar)) { + ESP_LOGV(TAG, "Cannot decode field %" PRIu32 " with wire type %" PRIu32 "!", tag >> 3, field_type); } } } diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 2ae7b7ae22..4a0599f104 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -174,55 +174,54 @@ class ProtoSize; // 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. +// table, so there the key is the field number and PROTO_DECODE_GUARD compares the tag against the +// one the case declares, which rejects the wrong wire type in a single compare. Both forms drop a +// field that arrives with a wire type it does not declare, as the per wire type virtuals did. #ifdef USE_HOST -#define PROTO_DECODE_KEY(tag, field_id) (field_id) +#define PROTO_DECODE_KEY(tag) ((tag) >> 3) #define PROTO_DECODE_CASE(field_id, wire_type) (field_id) -#define PROTO_DECODE_GUARD(wire_type, expected) \ - if ((wire_type) != (expected)) \ +#define PROTO_DECODE_GUARD(tag, field_id, wire_type) \ + if ((tag) != (((field_id) << 3) | (wire_type))) \ return false #else -#define PROTO_DECODE_KEY(tag, field_id) (tag) +#define PROTO_DECODE_KEY(tag) (tag) #define PROTO_DECODE_CASE(field_id, wire_type) (((field_id) << 3) | (wire_type)) -#define PROTO_DECODE_GUARD(wire_type, expected) (void) 0 +#define PROTO_DECODE_GUARD(tag, field_id, wire_type) (void) 0 #endif -/// 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_; - }; +/// Payload of one decoded field as decode_field() receives it: the payload pointer and one scalar +/// that holds the varint or fixed32 value, or the byte length of a length-delimited field. The +/// wire type in the tag says which reading applies; the accessors do not check. Built by the +/// generated decode_field() from its two register arguments, so it never exists in memory. +class ProtoFieldValue { + public: + ProtoFieldValue(const uint8_t *data, proto_varint_value_t scalar) : data_(data), scalar_(scalar) {} - proto_varint_value_t as_varint() const { return this->varint_; } + proto_varint_value_t as_varint() const { return this->scalar_; } // 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); } + const uint8_t *data() const { return this->data_; } + size_t size() const { return static_cast(this->scalar_); } + std::string as_string() const { return std::string(reinterpret_cast(this->data_), this->size()); } /// 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 { msg.decode(this->ld_.data, this->ld_.len); } + template void decode_to_message(T &msg) const { msg.decode(this->data_, this->size()); } // Fixed32 accessors - uint32_t as_fixed32() const { return this->fixed32_; } - int32_t as_sfixed32() const { return static_cast(this->fixed32_); } + uint32_t as_fixed32() const { return static_cast(this->scalar_); } + int32_t as_sfixed32() const { return static_cast(this->as_fixed32()); } float as_float() const { union { uint32_t raw; float value; } s{}; - s.raw = this->fixed32_; + s.raw = this->as_fixed32(); return s.value; } + + private: + const uint8_t *data_; + proto_varint_value_t scalar_; }; // NOTE: Proto64Bit class removed - wire type 1 (64-bit fixed) not supported @@ -751,16 +750,15 @@ class ProtoDecodableMessage : public ProtoMessage { protected: ~ProtoDecodableMessage() = default; - /// 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. + /// Store one decoded field. \p tag is the wire tag (field number and wire type), \p data points at + /// the field payload and \p scalar is the varint or fixed32 value, or the payload length for a + /// length-delimited field. Three register arguments keep the shared loop free of spills; the + /// generated override wraps them in a ProtoFieldValue and keys its switch through + /// PROTO_DECODE_KEY. 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; - } + virtual bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) { return false; } }; class ProtoSize { diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 289a314f31..b1e6cb8ca8 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -237,7 +237,7 @@ class TypeInfo(ABC): """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" PROTO_DECODE_GUARD(tag, {self.number}, {int(wire_type)});\n" f" {body}\n" f" break;" ) @@ -2741,15 +2741,16 @@ def build_message_type( 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 = f"bool {desc.name}::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) {{\n" + o += " const ProtoFieldValue value(data, scalar);\n" + o += " switch (PROTO_DECODE_KEY(tag)) {\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_field(uint32_t tag, uint32_t field_id, uint32_t wire_type, ProtoFieldValue value) override;" + prot = "bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) 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 a59681b12e..ae629ff11a 100644 --- a/tests/unit_tests/components/api/test_api_protobuf_generator.py +++ b/tests/unit_tests/components/api/test_api_protobuf_generator.py @@ -226,7 +226,9 @@ def test_decode_cases_carry_field_number_and_wire_type( 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 lines[1].strip() == f"PROTO_DECODE_GUARD(tag, {number}, {wire_type});", ( + cases[0] + ) assert accessor in cases[0], cases[0] @@ -237,15 +239,16 @@ def test_message_gets_a_single_decode_field_override() -> None: 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;" + decl = "bool decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) 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) {" + "bool Mixed::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) {" ) == 1 ) - assert "switch (PROTO_DECODE_KEY(tag, field_id)) {" in cpp + assert "switch (PROTO_DECODE_KEY(tag)) {" in cpp + assert "const ProtoFieldValue value(data, scalar);" 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