Compare commits

...
Author SHA1 Message Date
J. Nick Koston 3dea55368f [api] State the destructor trade-off as a codebase rule, not a language guarantee 2026-09-08 04:57:49 +02:00
J. Nick Koston 76100fec58 [api] Use the direction helpers in the base class builder too 2026-09-08 04:43:02 +02:00
J. Nick Koston 4736550677 [api] Say why ProtoDecodableMessage has no protected destructor 2026-09-08 04:43:02 +02:00
J. Nick Koston 2d86ffec7e [api] Drop the unused base decode(), group the vtable asserts, and test the decode emitters
A generated decodable message that lost its decode() would now fail to compile instead of
silently keeping its defaults. The asserts cover exactly the classes that derive from
ProtoDecodableMessage, under one ifdef per run instead of one per line, and the generator
tests pin the inline decode() wrapper, its absence on fixed vector messages, and the
this-> free static body.
2026-09-08 04:43:02 +02:00
J. Nick Koston 4509e5d388 [api] Assert at compile time that decodable messages carry no vtable
Every build below VERY_VERBOSE now checks the base class and each generated decodable
message with std::is_polymorphic_v, so a vtable cannot come back unnoticed.
2026-09-08 04:43:02 +02:00
J. Nick Koston 0e3554f6f8 [api] Decode without a vtable
decode_field() becomes a static per message function and the generated decode() hands it
to the shared loop as a function pointer, so decodable messages carry no vtable and no
vptr store at every construction site. The loop loses the two vtable loads per field. The
protected destructor on ProtoDecodableMessage goes with the virtuals; ProtoMessage keeps
its own guard for the dump builds that still have them.
2026-09-08 04:43:02 +02:00
6 changed files with 881 additions and 418 deletions
File diff suppressed because it is too large Load Diff
+230 -59
View File
@@ -419,12 +419,15 @@ class HelloRequest final : public ProtoDecodableMessage {
StringRef client_info{}; StringRef client_info{};
uint32_t api_version_major{0}; uint32_t api_version_major{0};
uint32_t api_version_minor{0}; uint32_t api_version_minor{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class HelloResponse final : public ProtoMessage { class HelloResponse final : public ProtoMessage {
public: public:
@@ -457,6 +460,9 @@ class DisconnectRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("disconnect_request"); } const LogString *message_name() const override { return LOG_STR("disconnect_request"); }
#endif #endif
enums::DisconnectReason reason{}; enums::DisconnectReason reason{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM); static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG); return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -468,7 +474,7 @@ class DisconnectRequest final : public ProtoDecodableMessage {
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class DisconnectResponse final : public ProtoMessage { class DisconnectResponse final : public ProtoMessage {
public: public:
@@ -839,12 +845,15 @@ class CoverCommandRequest final : public CommandProtoMessage {
bool has_tilt{false}; bool has_tilt{false};
float tilt{0.0f}; float tilt{0.0f};
bool stop{false}; bool stop{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_FAN #ifdef USE_FAN
@@ -913,12 +922,15 @@ class FanCommandRequest final : public CommandProtoMessage {
int32_t speed_level{0}; int32_t speed_level{0};
bool has_preset_mode{false}; bool has_preset_mode{false};
StringRef preset_mode{}; StringRef preset_mode{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_LIGHT #ifdef USE_LIGHT
@@ -1009,12 +1021,15 @@ class LightCommandRequest final : public CommandProtoMessage {
uint32_t flash_length{0}; uint32_t flash_length{0};
bool has_effect{false}; bool has_effect{false};
StringRef effect{}; StringRef effect{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_SENSOR #ifdef USE_SENSOR
@@ -1114,12 +1129,15 @@ class SwitchCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("switch_command_request"); } const LogString *message_name() const override { return LOG_STR("switch_command_request"); }
#endif #endif
bool state{false}; bool state{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_TEXT_SENSOR #ifdef USE_TEXT_SENSOR
@@ -1174,12 +1192,15 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage {
#endif #endif
enums::LogLevel level{}; enums::LogLevel level{};
bool dump_config{false}; bool dump_config{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class SubscribeLogsResponse final : public ProtoMessage { class SubscribeLogsResponse final : public ProtoMessage {
public: public:
@@ -1217,12 +1238,15 @@ class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage {
#endif #endif
const uint8_t *key{nullptr}; const uint8_t *key{nullptr};
uint16_t key_len{0}; uint16_t key_len{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class NoiseEncryptionSetKeyResponse final : public ProtoMessage { class NoiseEncryptionSetKeyResponse final : public ProtoMessage {
public: public:
@@ -1311,12 +1335,15 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage {
const uint8_t *response_data{nullptr}; const uint8_t *response_data{nullptr};
uint16_t response_data_len{0}; uint16_t response_data_len{0};
#endif #endif
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_API_HOMEASSISTANT_STATES #ifdef USE_API_HOMEASSISTANT_STATES
@@ -1352,12 +1379,15 @@ class HomeAssistantStateResponse final : public ProtoDecodableMessage {
StringRef entity_id{}; StringRef entity_id{};
StringRef state{}; StringRef state{};
StringRef attribute{}; StringRef attribute{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
class GetTimeRequest final : public ProtoMessage { class GetTimeRequest final : public ProtoMessage {
@@ -1381,12 +1411,15 @@ class DSTRule final : public ProtoDecodableMessage {
uint32_t month{0}; uint32_t month{0};
uint32_t week{0}; uint32_t week{0};
uint32_t day_of_week{0}; uint32_t day_of_week{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class ParsedTimezone final : public ProtoDecodableMessage { class ParsedTimezone final : public ProtoDecodableMessage {
public: public:
@@ -1394,12 +1427,15 @@ class ParsedTimezone final : public ProtoDecodableMessage {
int32_t dst_offset_seconds{0}; int32_t dst_offset_seconds{0};
DSTRule dst_start{}; DSTRule dst_start{};
DSTRule dst_end{}; DSTRule dst_end{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class GetTimeResponse final : public ProtoDecodableMessage { class GetTimeResponse final : public ProtoDecodableMessage {
public: public:
@@ -1411,12 +1447,15 @@ class GetTimeResponse final : public ProtoDecodableMessage {
uint32_t epoch_seconds{0}; uint32_t epoch_seconds{0};
ParsedTimezone parsed_timezone{}; ParsedTimezone parsed_timezone{};
bool has_parsed_timezone{false}; bool has_parsed_timezone{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#ifdef USE_API_USER_DEFINED_ACTIONS #ifdef USE_API_USER_DEFINED_ACTIONS
class ListEntitiesServicesArgument final : public ProtoMessage { class ListEntitiesServicesArgument final : public ProtoMessage {
@@ -1484,7 +1523,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage {
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class ExecuteServiceRequest final : public ProtoDecodableMessage { class ExecuteServiceRequest final : public ProtoDecodableMessage {
public: public:
@@ -1507,7 +1546,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage {
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
@@ -1593,12 +1632,15 @@ class CameraImageRequest final : public ProtoDecodableMessage {
#endif #endif
bool single{false}; bool single{false};
bool stream{false}; bool stream{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_CLIMATE #ifdef USE_CLIMATE
@@ -1699,12 +1741,15 @@ class ClimateCommandRequest final : public CommandProtoMessage {
StringRef custom_preset{}; StringRef custom_preset{};
bool has_target_humidity{false}; bool has_target_humidity{false};
float target_humidity{0.0f}; float target_humidity{0.0f};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_WATER_HEATER #ifdef USE_WATER_HEATER
@@ -1771,12 +1816,15 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage {
uint32_t state{0}; uint32_t state{0};
float target_temperature_low{0.0f}; float target_temperature_low{0.0f};
float target_temperature_high{0.0f}; float target_temperature_high{0.0f};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_NUMBER #ifdef USE_NUMBER
@@ -1834,12 +1882,15 @@ class NumberCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("number_command_request"); } const LogString *message_name() const override { return LOG_STR("number_command_request"); }
#endif #endif
float state{0.0f}; float state{0.0f};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_SELECT #ifdef USE_SELECT
@@ -1892,12 +1943,15 @@ class SelectCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("select_command_request"); } const LogString *message_name() const override { return LOG_STR("select_command_request"); }
#endif #endif
StringRef state{}; StringRef state{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_SIREN #ifdef USE_SIREN
@@ -1958,12 +2012,15 @@ class SirenCommandRequest final : public CommandProtoMessage {
uint32_t duration{0}; uint32_t duration{0};
bool has_volume{false}; bool has_volume{false};
float volume{0.0f}; float volume{0.0f};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_LOCK #ifdef USE_LOCK
@@ -2020,12 +2077,15 @@ class LockCommandRequest final : public CommandProtoMessage {
enums::LockCommand command{}; enums::LockCommand command{};
bool has_code{false}; bool has_code{false};
StringRef code{}; StringRef code{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_BUTTON #ifdef USE_BUTTON
@@ -2056,12 +2116,15 @@ class ButtonCommandRequest final : public CommandProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("button_command_request"); } const LogString *message_name() const override { return LOG_STR("button_command_request"); }
#endif #endif
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_MEDIA_PLAYER #ifdef USE_MEDIA_PLAYER
@@ -2142,12 +2205,15 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage {
StringRef media_url{}; StringRef media_url{};
bool has_announcement{false}; bool has_announcement{false};
bool announcement{false}; bool announcement{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_BLUETOOTH_PROXY #ifdef USE_BLUETOOTH_PROXY
@@ -2159,12 +2225,15 @@ class SubscribeBluetoothLEAdvertisementsRequest final : public ProtoDecodableMes
const LogString *message_name() const override { return LOG_STR("subscribe_bluetooth_le_advertisements_request"); } const LogString *message_name() const override { return LOG_STR("subscribe_bluetooth_le_advertisements_request"); }
#endif #endif
uint32_t flags{0}; uint32_t flags{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothLERawAdvertisement final : public ProtoMessage { class BluetoothLERawAdvertisement final : public ProtoMessage {
public: public:
@@ -2213,12 +2282,15 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage {
enums::BluetoothDeviceRequestType request_type{}; enums::BluetoothDeviceRequestType request_type{};
bool has_address_type{false}; bool has_address_type{false};
uint32_t address_type{0}; uint32_t address_type{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothDeviceConnectionResponse final : public ProtoMessage { class BluetoothDeviceConnectionResponse final : public ProtoMessage {
public: public:
@@ -2251,12 +2323,15 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_get_services_request"); } const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_get_services_request"); }
#endif #endif
uint64_t address{0}; uint64_t address{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothGATTDescriptor final : public ProtoMessage { class BluetoothGATTDescriptor final : public ProtoMessage {
public: public:
@@ -2362,12 +2437,15 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage {
#endif #endif
uint64_t address{0}; uint64_t address{0};
uint32_t handle{0}; uint32_t handle{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothGATTReadResponse final : public ProtoMessage { class BluetoothGATTReadResponse final : public ProtoMessage {
public: public:
@@ -2408,12 +2486,15 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage {
bool response{false}; bool response{false};
const uint8_t *data{nullptr}; const uint8_t *data{nullptr};
uint16_t data_len{0}; uint16_t data_len{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage { class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage {
public: public:
@@ -2424,12 +2505,15 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage {
#endif #endif
uint64_t address{0}; uint64_t address{0};
uint32_t handle{0}; uint32_t handle{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage { class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage {
public: public:
@@ -2442,12 +2526,15 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage {
uint32_t handle{0}; uint32_t handle{0};
const uint8_t *data{nullptr}; const uint8_t *data{nullptr};
uint16_t data_len{0}; uint16_t data_len{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage { class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage {
public: public:
@@ -2459,12 +2546,15 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage {
uint64_t address{0}; uint64_t address{0};
uint32_t handle{0}; uint32_t handle{0};
bool enable{false}; bool enable{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothGATTNotifyDataResponse final : public ProtoMessage { class BluetoothGATTNotifyDataResponse final : public ProtoMessage {
public: public:
@@ -2677,12 +2767,15 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("bluetooth_scanner_set_mode_request"); } const LogString *message_name() const override { return LOG_STR("bluetooth_scanner_set_mode_request"); }
#endif #endif
enums::BluetoothScannerMode mode{}; enums::BluetoothScannerMode mode{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_VOICE_ASSISTANT #ifdef USE_VOICE_ASSISTANT
@@ -2695,12 +2788,15 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage {
#endif #endif
bool subscribe{false}; bool subscribe{false};
uint32_t flags{0}; uint32_t flags{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantAudioSettings final : public ProtoMessage { class VoiceAssistantAudioSettings final : public ProtoMessage {
public: public:
@@ -2752,23 +2848,29 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage {
#endif #endif
uint32_t port{0}; uint32_t port{0};
bool error{false}; bool error{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantEventData final : public ProtoDecodableMessage { class VoiceAssistantEventData final : public ProtoDecodableMessage {
public: public:
StringRef name{}; StringRef name{};
StringRef value{}; StringRef value{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantEventResponse final : public ProtoDecodableMessage { class VoiceAssistantEventResponse final : public ProtoDecodableMessage {
public: public:
@@ -2779,12 +2881,15 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage {
#endif #endif
enums::VoiceAssistantEvent event_type{}; enums::VoiceAssistantEvent event_type{};
std::vector<VoiceAssistantEventData> data{}; std::vector<VoiceAssistantEventData> data{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantAudio final : public ProtoDecodableMessage { class VoiceAssistantAudio final : public ProtoDecodableMessage {
public: public:
@@ -2798,6 +2903,9 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage {
bool end{false}; bool end{false};
const uint8_t *data2{nullptr}; const uint8_t *data2{nullptr};
uint16_t data2_len{0}; uint16_t data2_len{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM); static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG); return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -2809,7 +2917,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage {
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage { class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage {
public: public:
@@ -2824,12 +2932,15 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage {
uint32_t total_seconds{0}; uint32_t total_seconds{0};
uint32_t seconds_left{0}; uint32_t seconds_left{0};
bool is_active{false}; bool is_active{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage { class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage {
public: public:
@@ -2842,12 +2953,15 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage {
StringRef text{}; StringRef text{};
StringRef preannounce_media_id{}; StringRef preannounce_media_id{};
bool start_conversation{false}; bool start_conversation{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantAnnounceFinished final : public ProtoMessage { class VoiceAssistantAnnounceFinished final : public ProtoMessage {
public: public:
@@ -2895,12 +3009,15 @@ class VoiceAssistantExternalWakeWord final : public ProtoDecodableMessage {
uint32_t model_size{0}; uint32_t model_size{0};
StringRef model_hash{}; StringRef model_hash{};
StringRef url{}; StringRef url{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage { class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage {
public: public:
@@ -2910,12 +3027,15 @@ class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("voice_assistant_configuration_request"); } const LogString *message_name() const override { return LOG_STR("voice_assistant_configuration_request"); }
#endif #endif
std::vector<VoiceAssistantExternalWakeWord> external_wake_words{}; std::vector<VoiceAssistantExternalWakeWord> external_wake_words{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class VoiceAssistantConfigurationResponse final : public ProtoMessage { class VoiceAssistantConfigurationResponse final : public ProtoMessage {
public: public:
@@ -2947,12 +3067,15 @@ class VoiceAssistantSetConfiguration final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("voice_assistant_set_configuration"); } const LogString *message_name() const override { return LOG_STR("voice_assistant_set_configuration"); }
#endif #endif
std::vector<std::string> active_wake_words{}; std::vector<std::string> active_wake_words{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_ALARM_CONTROL_PANEL #ifdef USE_ALARM_CONTROL_PANEL
@@ -3007,12 +3130,15 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage {
#endif #endif
enums::AlarmControlPanelStateCommand command{}; enums::AlarmControlPanelStateCommand command{};
StringRef code{}; StringRef code{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_TEXT #ifdef USE_TEXT
@@ -3068,12 +3194,15 @@ class TextCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("text_command_request"); } const LogString *message_name() const override { return LOG_STR("text_command_request"); }
#endif #endif
StringRef state{}; StringRef state{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_DATETIME_DATE #ifdef USE_DATETIME_DATE
@@ -3129,12 +3258,15 @@ class DateCommandRequest final : public CommandProtoMessage {
uint32_t year{0}; uint32_t year{0};
uint32_t month{0}; uint32_t month{0};
uint32_t day{0}; uint32_t day{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_DATETIME_TIME #ifdef USE_DATETIME_TIME
@@ -3190,12 +3322,15 @@ class TimeCommandRequest final : public CommandProtoMessage {
uint32_t hour{0}; uint32_t hour{0};
uint32_t minute{0}; uint32_t minute{0};
uint32_t second{0}; uint32_t second{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_EVENT #ifdef USE_EVENT
@@ -3296,12 +3431,15 @@ class ValveCommandRequest final : public CommandProtoMessage {
bool has_position{false}; bool has_position{false};
float position{0.0f}; float position{0.0f};
bool stop{false}; bool stop{false};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_DATETIME_DATETIME #ifdef USE_DATETIME_DATETIME
@@ -3353,12 +3491,15 @@ class DateTimeCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("date_time_command_request"); } const LogString *message_name() const override { return LOG_STR("date_time_command_request"); }
#endif #endif
uint32_t epoch_seconds{0}; uint32_t epoch_seconds{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_UPDATE #ifdef USE_UPDATE
@@ -3418,12 +3559,15 @@ class UpdateCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("update_command_request"); } const LogString *message_name() const override { return LOG_STR("update_command_request"); }
#endif #endif
enums::UpdateCommand command{}; enums::UpdateCommand command{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
#endif #endif
#ifdef USE_ZWAVE_PROXY #ifdef USE_ZWAVE_PROXY
@@ -3436,6 +3580,9 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage {
#endif #endif
const uint8_t *data{nullptr}; const uint8_t *data{nullptr};
uint16_t data_len{0}; uint16_t data_len{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM); static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG); return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -3447,7 +3594,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage {
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class ZWaveProxyRequest final : public ProtoDecodableMessage { class ZWaveProxyRequest final : public ProtoDecodableMessage {
public: public:
@@ -3459,6 +3606,9 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage {
enums::ZWaveProxyRequestType type{}; enums::ZWaveProxyRequestType type{};
const uint8_t *data{nullptr}; const uint8_t *data{nullptr};
uint16_t data_len{0}; uint16_t data_len{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM); static uint8_t *encode_msg(const void *self, ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG); return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -3470,7 +3620,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage {
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class ZWaveProxyRequestResponse final : public ProtoMessage { class ZWaveProxyRequestResponse final : public ProtoMessage {
public: public:
@@ -3535,12 +3685,15 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage {
uint16_t timings_length_{0}; uint16_t timings_length_{0};
uint16_t timings_count_{0}; uint16_t timings_count_{0};
uint32_t modulation{0}; uint32_t modulation{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class InfraredRFReceiveEvent final : public ProtoMessage { class InfraredRFReceiveEvent final : public ProtoMessage {
public: public:
@@ -3606,12 +3759,15 @@ class SerialProxyConfigureRequest final : public ProtoDecodableMessage {
enums::SerialProxyParity parity{}; enums::SerialProxyParity parity{};
uint32_t stop_bits{0}; uint32_t stop_bits{0};
uint32_t data_size{0}; uint32_t data_size{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class SerialProxyDataReceived final : public ProtoMessage { class SerialProxyDataReceived final : public ProtoMessage {
public: public:
@@ -3649,12 +3805,15 @@ class SerialProxyWriteRequest final : public ProtoDecodableMessage {
uint32_t instance{0}; uint32_t instance{0};
const uint8_t *data{nullptr}; const uint8_t *data{nullptr};
uint16_t data_len{0}; uint16_t data_len{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage { class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage {
public: public:
@@ -3665,12 +3824,15 @@ class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage {
#endif #endif
uint32_t instance{0}; uint32_t instance{0};
uint32_t line_states{0}; uint32_t line_states{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage { class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage {
public: public:
@@ -3680,12 +3842,15 @@ class SerialProxyGetModemPinsRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("serial_proxy_get_modem_pins_request"); } const LogString *message_name() const override { return LOG_STR("serial_proxy_get_modem_pins_request"); }
#endif #endif
uint32_t instance{0}; uint32_t instance{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class SerialProxyGetModemPinsResponse final : public ProtoMessage { class SerialProxyGetModemPinsResponse final : public ProtoMessage {
public: public:
@@ -3718,12 +3883,15 @@ class SerialProxyRequest final : public ProtoDecodableMessage {
#endif #endif
uint32_t instance{0}; uint32_t instance{0};
enums::SerialProxyRequestType type{}; enums::SerialProxyRequestType type{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class SerialProxyRequestResponse final : public ProtoMessage { class SerialProxyRequestResponse final : public ProtoMessage {
public: public:
@@ -3762,12 +3930,15 @@ class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage {
uint32_t max_interval{0}; uint32_t max_interval{0};
uint32_t latency{0}; uint32_t latency{0};
uint32_t timeout{0}; uint32_t timeout{0};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP #ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override; const char *dump_to(DumpBuffer &out) const override;
#endif #endif
protected: protected:
void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override; static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
}; };
class BluetoothSetConnectionParamsResponse final : public ProtoMessage { class BluetoothSetConnectionParamsResponse final : public ProtoMessage {
public: public:
+2 -2
View File
@@ -210,7 +210,7 @@ void ProtoWriteBuffer::debug_check_encode_size_(uint32_t field_id, uint32_t expe
#endif #endif
void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { void ProtoDecodableMessage::decode_fields(void *msg, const uint8_t *buffer, size_t length, DecodeFieldFn field) {
const uint8_t *ptr = buffer; const uint8_t *ptr = buffer;
const uint8_t *end = buffer + length; const uint8_t *end = buffer + length;
@@ -281,7 +281,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) {
return; return;
} }
} }
this->decode_field(tag, data, scalar); field(msg, tag, data, scalar);
} }
} }
+16 -8
View File
@@ -10,6 +10,7 @@
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <type_traits>
#include <vector> #include <vector>
#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE #ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
@@ -720,7 +721,13 @@ class ProtoMessage {
// Base class for messages that support decoding // Base class for messages that support decoding
class ProtoDecodableMessage : public ProtoMessage { class ProtoDecodableMessage : public ProtoMessage {
public: public:
void decode(const uint8_t *buffer, size_t length); /// Stores one decoded field into \p msg; generated per message type. \p scalar is the varint or
/// fixed32 value, or the length of the length-delimited payload at \p data. An unknown field or
/// wrong wire type matches no case and is skipped.
using DecodeFieldFn = void (*)(void *msg, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);
/// Walk \p buffer and hand every field to \p field. The generated decode() passes the message's
/// own decode_field, so decodable messages carry no vtable.
static void decode_fields(void *msg, const uint8_t *buffer, size_t length, DecodeFieldFn field);
/** /**
* Count occurrences of a repeated field in a protobuf buffer. * Count occurrences of a repeated field in a protobuf buffer.
@@ -732,14 +739,15 @@ class ProtoDecodableMessage : public ProtoMessage {
* @return Number of times the field appears in the buffer * @return Number of times the field appears in the buffer
*/ */
static uint32_t count_repeated_field(const uint8_t *buffer, size_t length, uint32_t target_field_id); static uint32_t count_repeated_field(const uint8_t *buffer, size_t length, uint32_t target_field_id);
// The destructor stays accessible on purpose: the generated messages are aggregates that brace
protected: // initialise sub message members, which copies a base temporary. That trades away the compile time
~ProtoDecodableMessage() = default; // guard against deleting through this type; messages are stack locals and never owned through a base
/// Store one decoded field; \p scalar is the varint or fixed32 value, or the length of the // pointer. ProtoMessage keeps its guard for the dump builds.
/// length-delimited payload at \p data. An unknown field or wrong wire type matches no case and is skipped.
/// Three register arguments keep the decode loop free of spills.
virtual void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) {}
}; };
#ifndef HAS_PROTO_MESSAGE_DUMP
// decode() passes decode_field explicitly, so nothing here may add a vtable
static_assert(!std::is_polymorphic_v<ProtoDecodableMessage>, "decodable messages carry no vtable");
#endif
class ProtoSize { class ProtoSize {
public: public:
+52 -9
View File
@@ -2536,8 +2536,8 @@ def build_message_type(
# Get source direction to determine if we need decode/encode methods # Get source direction to determine if we need decode/encode methods
source = message_source_map[desc.name] source = message_source_map[desc.name]
needs_decode = source in (SOURCE_BOTH, SOURCE_CLIENT) needs_decode = message_needs_decode(source)
needs_encode = source in (SOURCE_BOTH, SOURCE_SERVER) needs_encode = message_needs_encode(source)
# Add MESSAGE_TYPE method if this is a service message # Add MESSAGE_TYPE method if this is a service message
if message_id is not None: if message_id is not None:
@@ -2661,15 +2661,22 @@ def build_message_type(
cpp = "" cpp = ""
if decode: if decode:
o = f"void {desc.name}::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) {{\n" o = f"void {desc.name}::decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) {{\n"
o += f" auto &msg = *static_cast<{desc.name} *>(self);\n"
o += " const ProtoFieldValue value(data, scalar);\n" o += " const ProtoFieldValue value(data, scalar);\n"
o += " switch (tag) {\n" o += " switch (tag) {\n"
o += indent("\n".join(decode), " ") + "\n" o += indent("\n".join(decode), " ").replace("this->", "msg.") + "\n"
o += " }\n" o += " }\n"
o += "}\n" o += "}\n"
cpp += o cpp += o
prot = "void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override;" prot = "static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);"
protected_content.insert(0, prot) protected_content.insert(0, prot)
if not fixed_vector_fields:
public_content.append(
"void decode(const uint8_t *buffer, size_t length) {\n"
" ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);\n"
"}"
)
# Generate custom decode() override for messages with FixedVector fields # Generate custom decode() override for messages with FixedVector fields
if fixed_vector_fields: if fixed_vector_fields:
@@ -2679,8 +2686,8 @@ def build_message_type(
for field_name, field_number in fixed_vector_fields: for field_name, field_number in fixed_vector_fields:
o += f" uint32_t count_{field_name} = ProtoDecodableMessage::count_repeated_field(buffer, length, {field_number});\n" o += f" uint32_t count_{field_name} = ProtoDecodableMessage::count_repeated_field(buffer, length, {field_number});\n"
o += f" this->{field_name}.init(count_{field_name});\n" o += f" this->{field_name}.init(count_{field_name});\n"
# Call parent decode to populate the fields # Then the shared loop fills them
o += " ProtoDecodableMessage::decode(buffer, length);\n" o += " ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);\n"
o += "}\n" o += "}\n"
cpp += o cpp += o
# Generate the decode() declaration in header (public method) # Generate the decode() declaration in header (public method)
@@ -2839,6 +2846,23 @@ def get_field_opt(
return field.options.Extensions[opt] return field.options.Extensions[opt]
def message_needs_decode(source: int) -> bool:
return source in (SOURCE_BOTH, SOURCE_CLIENT)
def message_needs_encode(source: int) -> bool:
return source in (SOURCE_BOTH, SOURCE_SERVER)
def is_decodable_class(desc: descriptor.DescriptorProto, source: int) -> bool:
"""Whether the generated class derives from ProtoDecodableMessage: decoded, and either on a
decodable base class or with at least one live field."""
return message_needs_decode(source) and (
get_base_class(desc) is not None
or any(not field.options.deprecated for field in desc.field)
)
def get_base_class(desc: descriptor.DescriptorProto) -> str | None: def get_base_class(desc: descriptor.DescriptorProto) -> str | None:
"""Get the base_class option from a message descriptor.""" """Get the base_class option from a message descriptor."""
if not desc.options.HasExtension(pb.base_class): if not desc.options.HasExtension(pb.base_class):
@@ -2940,11 +2964,11 @@ def build_base_class(
# Determine if any message using this base class needs decoding/encoding # Determine if any message using this base class needs decoding/encoding
needs_decode = any( needs_decode = any(
message_source_map.get(msg.name, SOURCE_BOTH) in (SOURCE_BOTH, SOURCE_CLIENT) message_needs_decode(message_source_map.get(msg.name, SOURCE_BOTH))
for msg in messages for msg in messages
) )
needs_encode = any( needs_encode = any(
message_source_map.get(msg.name, SOURCE_BOTH) in (SOURCE_BOTH, SOURCE_SERVER) message_needs_encode(message_source_map.get(msg.name, SOURCE_BOTH))
for msg in messages for msg in messages
) )
@@ -3378,6 +3402,7 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
# Generate message types with base class information # Generate message types with base class information
# Simple grouping by ifdef # Simple grouping by ifdef
decodable_messages: list[tuple[str, str | None]] = []
current_ifdef = None current_ifdef = None
for m in mt: for m in mt:
@@ -3394,6 +3419,8 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
continue continue
s, c, dc = build_message_type(m, base_class_fields, message_source_map) s, c, dc = build_message_type(m, base_class_fields, message_source_map)
if is_decodable_class(m, message_source_map[m.name]):
decodable_messages.append((m.name, message_ifdef_map.get(m.name)))
msg_ifdef = message_ifdef_map.get(m.name) msg_ifdef = message_ifdef_map.get(m.name)
# Handle ifdef changes # Handle ifdef changes
@@ -3420,6 +3447,22 @@ static void dump_bytes_field(DumpBuffer &out, const char *field_name, const uint
cpp += "#endif\n" cpp += "#endif\n"
dump_cpp += "#endif\n" dump_cpp += "#endif\n"
# decode() passes decode_field explicitly, so without the dump virtuals no decodable message
# may carry a vtable; a build at any level below VERY_VERBOSE proves it
cpp += "#ifndef HAS_PROTO_MESSAGE_DUMP\n"
assert_ifdef = None
for name, msg_ifdef in decodable_messages:
if msg_ifdef != assert_ifdef:
if assert_ifdef is not None:
cpp += "#endif\n"
if msg_ifdef is not None:
cpp += _make_ifdef_line(msg_ifdef) + "\n"
assert_ifdef = msg_ifdef
cpp += f'static_assert(!std::is_polymorphic_v<{name}>, "decodable messages carry no vtable");\n'
if assert_ifdef is not None:
cpp += "#endif\n"
cpp += "#endif\n"
content += """\ content += """\
} // namespace esphome::api } // namespace esphome::api
@@ -285,18 +285,19 @@ def test_a_fixed64_field_fails_at_generation_time() -> None:
build_message_type(desc, {}, {"Wide": SOURCE_CLIENT}) build_message_type(desc, {}, {"Wide": SOURCE_CLIENT})
def test_message_gets_a_single_decode_field_override() -> None: def test_message_decodes_through_one_static_decode_field() -> None:
"""All wire types of a decoded message land in one decode_field() switch.""" """All wire types of a decoded message land in one static decode_field() switch that the
inline decode() hands to the shared loop."""
desc = descriptor_pb2.DescriptorProto(name="Mixed") desc = descriptor_pb2.DescriptorProto(name="Mixed")
desc.field.add(name="name", number=1, type=STRING) desc.field.add(name="name", number=1, type=STRING)
desc.field.add(name="count", number=2, type=UINT32) desc.field.add(name="count", number=2, type=UINT32)
desc.field.add(name="level", number=3, type=FLOAT) desc.field.add(name="level", number=3, type=FLOAT)
header, cpp, _ = build_message_type(desc, {}, {"Mixed": SOURCE_CLIENT}) header, cpp, _ = build_message_type(desc, {}, {"Mixed": SOURCE_CLIENT})
decl = "void decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) override;" decl = "static void decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar);"
assert header.count(decl) == 1 assert header.count(decl) == 1
assert ( assert (
cpp.count( cpp.count(
"void Mixed::decode_field(uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) {" "void Mixed::decode_field(void *self, uint32_t tag, const uint8_t *data, proto_varint_value_t scalar) {"
) )
== 1 == 1
) )
@@ -308,3 +309,34 @@ def test_message_gets_a_single_decode_field_override() -> None:
(3, "WIRE_TYPE_FIXED32"), (3, "WIRE_TYPE_FIXED32"),
): ):
assert f"case proto_tag({number}, {wire_type}):" in cpp, cpp assert f"case proto_tag({number}, {wire_type}):" in cpp, cpp
# The static body works on the cast message, never on this
assert "auto &msg = *static_cast<Mixed *>(self);" in cpp
assert "this->" not in cpp
assert (
header.count(
"ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);"
)
== 1
)
def test_fixed_vector_message_keeps_its_own_decode() -> None:
"""A message that sizes a FixedVector first decodes through its own decode(), not the inline one."""
desc = descriptor_pb2.DescriptorProto(name="Sized")
field = desc.field.add(name="values", number=1, type=UINT32)
field.label = descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED
field.options.Extensions[pb.fixed_vector] = True
header, cpp, _ = build_message_type(desc, {}, {"Sized": SOURCE_CLIENT})
assert (
"ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);"
not in header
)
assert header.count("void decode(const uint8_t *buffer, size_t length);") == 1
assert "void Sized::decode(const uint8_t *buffer, size_t length) {" in cpp
assert "ProtoDecodableMessage::count_repeated_field(buffer, length, 1)" in cpp
assert (
cpp.count(
"ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);"
)
== 1
)