[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.
This commit is contained in:
J. Nick Koston
2026-09-08 04:43:02 +02:00
parent 5ac2fa8811
commit 0e3554f6f8
6 changed files with 675 additions and 412 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{};
uint32_t api_version_major{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -457,6 +460,9 @@ class DisconnectRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("disconnect_request"); }
#endif
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);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -468,7 +474,7 @@ class DisconnectRequest final : public ProtoDecodableMessage {
#endif
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 {
public:
@@ -839,12 +845,15 @@ class CoverCommandRequest final : public CommandProtoMessage {
bool has_tilt{false};
float tilt{0.0f};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_FAN
@@ -913,12 +922,15 @@ class FanCommandRequest final : public CommandProtoMessage {
int32_t speed_level{0};
bool has_preset_mode{false};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_LIGHT
@@ -1009,12 +1021,15 @@ class LightCommandRequest final : public CommandProtoMessage {
uint32_t flash_length{0};
bool has_effect{false};
StringRef effect{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_SENSOR
@@ -1114,12 +1129,15 @@ class SwitchCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("switch_command_request"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_TEXT_SENSOR
@@ -1174,12 +1192,15 @@ class SubscribeLogsRequest final : public ProtoDecodableMessage {
#endif
enums::LogLevel level{};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -1217,12 +1238,15 @@ class NoiseEncryptionSetKeyRequest final : public ProtoDecodableMessage {
#endif
const uint8_t *key{nullptr};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -1311,12 +1335,15 @@ class HomeassistantActionResponse final : public ProtoDecodableMessage {
const uint8_t *response_data{nullptr};
uint16_t response_data_len{0};
#endif
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_API_HOMEASSISTANT_STATES
@@ -1352,12 +1379,15 @@ class HomeAssistantStateResponse final : public ProtoDecodableMessage {
StringRef entity_id{};
StringRef state{};
StringRef attribute{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
class GetTimeRequest final : public ProtoMessage {
@@ -1381,12 +1411,15 @@ class DSTRule final : public ProtoDecodableMessage {
uint32_t month{0};
uint32_t 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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -1394,12 +1427,15 @@ class ParsedTimezone final : public ProtoDecodableMessage {
int32_t dst_offset_seconds{0};
DSTRule dst_start{};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -1411,12 +1447,15 @@ class GetTimeResponse final : public ProtoDecodableMessage {
uint32_t epoch_seconds{0};
ParsedTimezone parsed_timezone{};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
class ListEntitiesServicesArgument final : public ProtoMessage {
@@ -1484,7 +1523,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage {
#endif
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 {
public:
@@ -1507,7 +1546,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage {
#endif
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
#ifdef USE_API_USER_DEFINED_ACTION_RESPONSES
@@ -1593,12 +1632,15 @@ class CameraImageRequest final : public ProtoDecodableMessage {
#endif
bool single{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_CLIMATE
@@ -1699,12 +1741,15 @@ class ClimateCommandRequest final : public CommandProtoMessage {
StringRef custom_preset{};
bool has_target_humidity{false};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_WATER_HEATER
@@ -1771,12 +1816,15 @@ class WaterHeaterCommandRequest final : public CommandProtoMessage {
uint32_t state{0};
float target_temperature_low{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_NUMBER
@@ -1834,12 +1882,15 @@ class NumberCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("number_command_request"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_SELECT
@@ -1892,12 +1943,15 @@ class SelectCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("select_command_request"); }
#endif
StringRef state{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_SIREN
@@ -1958,12 +2012,15 @@ class SirenCommandRequest final : public CommandProtoMessage {
uint32_t duration{0};
bool has_volume{false};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_LOCK
@@ -2020,12 +2077,15 @@ class LockCommandRequest final : public CommandProtoMessage {
enums::LockCommand command{};
bool has_code{false};
StringRef code{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_BUTTON
@@ -2056,12 +2116,15 @@ class ButtonCommandRequest final : public CommandProtoMessage {
#ifdef HAS_PROTO_MESSAGE_DUMP
const LogString *message_name() const override { return LOG_STR("button_command_request"); }
#endif
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_MEDIA_PLAYER
@@ -2142,12 +2205,15 @@ class MediaPlayerCommandRequest final : public CommandProtoMessage {
StringRef media_url{};
bool has_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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#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"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2213,12 +2282,15 @@ class BluetoothDeviceRequest final : public ProtoDecodableMessage {
enums::BluetoothDeviceRequestType request_type{};
bool has_address_type{false};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2251,12 +2323,15 @@ class BluetoothGATTGetServicesRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("bluetooth_gatt_get_services_request"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2362,12 +2437,15 @@ class BluetoothGATTReadRequest final : public ProtoDecodableMessage {
#endif
uint64_t address{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2408,12 +2486,15 @@ class BluetoothGATTWriteRequest final : public ProtoDecodableMessage {
bool response{false};
const uint8_t *data{nullptr};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2424,12 +2505,15 @@ class BluetoothGATTReadDescriptorRequest final : public ProtoDecodableMessage {
#endif
uint64_t address{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2442,12 +2526,15 @@ class BluetoothGATTWriteDescriptorRequest final : public ProtoDecodableMessage {
uint32_t handle{0};
const uint8_t *data{nullptr};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2459,12 +2546,15 @@ class BluetoothGATTNotifyRequest final : public ProtoDecodableMessage {
uint64_t address{0};
uint32_t handle{0};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2677,12 +2767,15 @@ class BluetoothScannerSetModeRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("bluetooth_scanner_set_mode_request"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_VOICE_ASSISTANT
@@ -2695,12 +2788,15 @@ class SubscribeVoiceAssistantRequest final : public ProtoDecodableMessage {
#endif
bool subscribe{false};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2752,23 +2848,29 @@ class VoiceAssistantResponse final : public ProtoDecodableMessage {
#endif
uint32_t port{0};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
StringRef name{};
StringRef value{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2779,12 +2881,15 @@ class VoiceAssistantEventResponse final : public ProtoDecodableMessage {
#endif
enums::VoiceAssistantEvent event_type{};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2798,6 +2903,9 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage {
bool end{false};
const uint8_t *data2{nullptr};
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);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -2809,7 +2917,7 @@ class VoiceAssistantAudio final : public ProtoDecodableMessage {
#endif
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 {
public:
@@ -2824,12 +2932,15 @@ class VoiceAssistantTimerEventResponse final : public ProtoDecodableMessage {
uint32_t total_seconds{0};
uint32_t seconds_left{0};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2842,12 +2953,15 @@ class VoiceAssistantAnnounceRequest final : public ProtoDecodableMessage {
StringRef text{};
StringRef preannounce_media_id{};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2895,12 +3009,15 @@ class VoiceAssistantExternalWakeWord final : public ProtoDecodableMessage {
uint32_t model_size{0};
StringRef model_hash{};
StringRef url{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2910,12 +3027,15 @@ class VoiceAssistantConfigurationRequest final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("voice_assistant_configuration_request"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -2947,12 +3067,15 @@ class VoiceAssistantSetConfiguration final : public ProtoDecodableMessage {
const LogString *message_name() const override { return LOG_STR("voice_assistant_set_configuration"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_ALARM_CONTROL_PANEL
@@ -3007,12 +3130,15 @@ class AlarmControlPanelCommandRequest final : public CommandProtoMessage {
#endif
enums::AlarmControlPanelStateCommand command{};
StringRef code{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_TEXT
@@ -3068,12 +3194,15 @@ class TextCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("text_command_request"); }
#endif
StringRef state{};
void decode(const uint8_t *buffer, size_t length) {
ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);
}
#ifdef HAS_PROTO_MESSAGE_DUMP
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_DATETIME_DATE
@@ -3129,12 +3258,15 @@ class DateCommandRequest final : public CommandProtoMessage {
uint32_t year{0};
uint32_t month{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_DATETIME_TIME
@@ -3190,12 +3322,15 @@ class TimeCommandRequest final : public CommandProtoMessage {
uint32_t hour{0};
uint32_t minute{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_EVENT
@@ -3296,12 +3431,15 @@ class ValveCommandRequest final : public CommandProtoMessage {
bool has_position{false};
float position{0.0f};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#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"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_UPDATE
@@ -3418,12 +3559,15 @@ class UpdateCommandRequest final : public CommandProtoMessage {
const LogString *message_name() const override { return LOG_STR("update_command_request"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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
#ifdef USE_ZWAVE_PROXY
@@ -3436,6 +3580,9 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage {
#endif
const uint8_t *data{nullptr};
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);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -3447,7 +3594,7 @@ class ZWaveProxyFrame final : public ProtoDecodableMessage {
#endif
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 {
public:
@@ -3459,6 +3606,9 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage {
enums::ZWaveProxyRequestType type{};
const uint8_t *data{nullptr};
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);
uint8_t *encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const {
return encode_msg(this, buffer PROTO_ENCODE_DEBUG_ARG);
@@ -3470,7 +3620,7 @@ class ZWaveProxyRequest final : public ProtoDecodableMessage {
#endif
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 {
public:
@@ -3535,12 +3685,15 @@ class InfraredRFTransmitRawTimingsRequest final : public ProtoDecodableMessage {
uint16_t timings_length_{0};
uint16_t timings_count_{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -3606,12 +3759,15 @@ class SerialProxyConfigureRequest final : public ProtoDecodableMessage {
enums::SerialProxyParity parity{};
uint32_t stop_bits{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -3649,12 +3805,15 @@ class SerialProxyWriteRequest final : public ProtoDecodableMessage {
uint32_t instance{0};
const uint8_t *data{nullptr};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -3665,12 +3824,15 @@ class SerialProxySetModemPinsRequest final : public ProtoDecodableMessage {
#endif
uint32_t instance{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
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"); }
#endif
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -3718,12 +3883,15 @@ class SerialProxyRequest final : public ProtoDecodableMessage {
#endif
uint32_t instance{0};
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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
@@ -3762,12 +3930,15 @@ class BluetoothSetConnectionParamsRequest final : public ProtoDecodableMessage {
uint32_t max_interval{0};
uint32_t latency{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
const char *dump_to(DumpBuffer &out) const override;
#endif
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 {
public:
+2 -2
View File
@@ -210,7 +210,7 @@ void ProtoWriteBuffer::debug_check_encode_size_(uint32_t field_id, uint32_t expe
#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 *end = buffer + length;
@@ -281,7 +281,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) {
return;
}
}
this->decode_field(tag, data, scalar);
field(msg, tag, data, scalar);
}
}
+9 -8
View File
@@ -720,7 +720,15 @@ class ProtoMessage {
// Base class for messages that support decoding
class ProtoDecodableMessage : public ProtoMessage {
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);
/// A decodable message without fields has nothing to read
void decode(const uint8_t *buffer, size_t length) {}
/**
* Count occurrences of a repeated field in a protobuf buffer.
@@ -732,13 +740,6 @@ class ProtoDecodableMessage : public ProtoMessage {
* @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);
protected:
~ProtoDecodableMessage() = default;
/// Store one decoded field; \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.
/// 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) {}
};
class ProtoSize {
+12 -5
View File
@@ -2661,15 +2661,22 @@ def build_message_type(
cpp = ""
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 += " switch (tag) {\n"
o += indent("\n".join(decode), " ") + "\n"
o += indent("\n".join(decode), " ").replace("this->", "msg.") + "\n"
o += " }\n"
o += "}\n"
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)
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
if fixed_vector_fields:
@@ -2679,8 +2686,8 @@ def build_message_type(
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" this->{field_name}.init(count_{field_name});\n"
# Call parent decode to populate the fields
o += " ProtoDecodableMessage::decode(buffer, length);\n"
# Then the shared loop fills them
o += " ProtoDecodableMessage::decode_fields(this, buffer, length, &decode_field);\n"
o += "}\n"
cpp += o
# Generate the decode() declaration in header (public method)
@@ -292,11 +292,11 @@ def test_message_gets_a_single_decode_field_override() -> None:
desc.field.add(name="count", number=2, type=UINT32)
desc.field.add(name="level", number=3, type=FLOAT)
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 (
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
)