diff --git a/esphome/components/api/api_connection.cpp b/esphome/components/api/api_connection.cpp index 3064ff09b1..f69181b527 100644 --- a/esphome/components/api/api_connection.cpp +++ b/esphome/components/api/api_connection.cpp @@ -2267,7 +2267,12 @@ bool APIConnection::send_message_(uint32_t payload_size, uint16_t message_type, // Capacity reserved above, cannot fail (void) shared_buf.resize(write_start + payload_size); ProtoWriteBuffer buffer{&shared_buf, write_start}; - encode_fn(msg, buffer PROTO_ENCODE_DEBUG_INIT(&shared_buf)); + uint8_t *end = encode_fn(msg, buffer PROTO_ENCODE_DEBUG_INIT(&shared_buf)); +#ifdef ESPHOME_DEBUG_API + proto_check_encode_end(end, shared_buf.data() + shared_buf.size()); +#else + (void) end; +#endif return this->send_buffer(ProtoWriteBuffer{&shared_buf}, message_type); } // encode_to_buffer is defined inline in api_connection.h (ESPHOME_ALWAYS_INLINE) diff --git a/esphome/components/api/api_connection_buffer.h b/esphome/components/api/api_connection_buffer.h index 08520249bf..5fbe171b52 100644 --- a/esphome/components/api/api_connection_buffer.h +++ b/esphome/components/api/api_connection_buffer.h @@ -46,7 +46,13 @@ inline uint16_t ESPHOME_ALWAYS_INLINE APIConnection::encode_to_buffer(uint32_t c return 0; } ProtoWriteBuffer buffer{&shared_buf, shared_buf.size() - calculated_size}; - encode_fn(msg, buffer PROTO_ENCODE_DEBUG_INIT(&shared_buf)); + uint8_t *end = encode_fn(msg, buffer PROTO_ENCODE_DEBUG_INIT(&shared_buf)); +#ifdef ESPHOME_DEBUG_API + // A body that writes fewer bytes than calculate_size() promised would ship stale buffer bytes + proto_check_encode_end(end, shared_buf.data() + shared_buf.size()); +#else + (void) end; +#endif return total_calculated_size; } diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index 7f162d9c15..c31cd3c615 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -33,10 +33,10 @@ bool HelloRequest::decode_length(uint32_t field_id, ProtoLengthDelimited value) } uint8_t *HelloResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->api_version_major); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->api_version_minor); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->server_info); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 34, this->name); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->api_version_major); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->api_version_minor); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->server_info); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 34, this->name); return pos; } uint32_t HelloResponse::calculate_size() const { @@ -59,7 +59,7 @@ bool DisconnectRequest::decode_varint(uint32_t field_id, proto_varint_value_t va } uint8_t *DisconnectRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->reason)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->reason)); return pos; } uint32_t DisconnectRequest::calculate_size() const { @@ -70,8 +70,8 @@ uint32_t DisconnectRequest::calculate_size() const { #ifdef USE_AREAS uint8_t *AreaInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->area_id); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->area_id); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); return pos; } uint32_t AreaInfo::calculate_size() const { @@ -84,9 +84,9 @@ uint32_t AreaInfo::calculate_size() const { #ifdef USE_DEVICES uint8_t *DeviceInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->device_id); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->area_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->device_id); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->area_id); return pos; } uint32_t DeviceInfo::calculate_size() const { @@ -100,9 +100,9 @@ uint32_t DeviceInfo::calculate_size() const { #ifdef USE_SERIAL_PROXY uint8_t *SerialProxyInfo::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->port_type)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->configured_line_states); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->port_type)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->configured_line_states); return pos; } uint32_t SerialProxyInfo::calculate_size() const { @@ -115,66 +115,66 @@ uint32_t SerialProxyInfo::calculate_size() const { #endif uint8_t *DeviceInfoResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->mac_address); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 34, this->esphome_version); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 42, this->compilation_time); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 50, this->model); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->mac_address); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 34, this->esphome_version); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 42, this->compilation_time); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 50, this->model); #ifdef USE_DEEP_SLEEP - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->has_deep_sleep); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->has_deep_sleep); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 66, this->project_name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 66, this->project_name); #endif #ifdef ESPHOME_PROJECT_NAME - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 74, this->project_version); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 74, this->project_version); #endif #ifdef USE_WEBSERVER - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->webserver_port); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->webserver_port); #endif #ifdef USE_BLUETOOTH_PROXY - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, this->bluetooth_proxy_feature_flags); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, this->bluetooth_proxy_feature_flags); #endif - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 98, this->manufacturer); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 106, this->friendly_name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 98, this->manufacturer); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 106, this->friendly_name); #ifdef USE_VOICE_ASSISTANT - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 17, this->voice_assistant_feature_flags); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 17, this->voice_assistant_feature_flags); #endif #ifdef USE_AREAS - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 16, this->suggested_area, true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 16, this->suggested_area); #endif #ifdef USE_BLUETOOTH_PROXY - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 18, this->bluetooth_mac_address, true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->bluetooth_mac_address); #endif #ifdef USE_API_NOISE - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 19, this->api_encryption_supported); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 19, this->api_encryption_supported); #endif #ifdef USE_DEVICES for (const auto &it : this->devices) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 20, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 20, it); } #endif #ifdef USE_AREAS for (const auto &it : this->areas) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 21, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 21, it); } #endif #ifdef USE_AREAS - ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 22, this->area); + pos = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 22, this->area); #endif #ifdef USE_ZWAVE_PROXY - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 23, this->zwave_proxy_feature_flags); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 23, this->zwave_proxy_feature_flags); #endif #ifdef USE_ZWAVE_PROXY - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 24, this->zwave_home_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 24, this->zwave_home_id); #endif #ifdef USE_SERIAL_PROXY for (const auto &it : this->serial_proxies) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 25, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 25, it); } #endif #ifdef USE_API_NOISE - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 26, this->api_encryption_provisionable); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 26, this->api_encryption_provisionable); #endif return pos; } @@ -246,8 +246,8 @@ uint32_t DeviceInfoResponse::calculate_size() const { #ifdef USE_BLUETOOTH_PROXY uint8_t *BluetoothProxyCapabilities::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->feature_flags); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->mac_address); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->feature_flags); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 18, this->mac_address); return pos; } uint32_t BluetoothProxyCapabilities::calculate_size() const { @@ -260,7 +260,7 @@ uint32_t BluetoothProxyCapabilities::calculate_size() const { #ifdef USE_VOICE_ASSISTANT uint8_t *VoiceAssistantCapabilities::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->feature_flags); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->feature_flags); return pos; } uint32_t VoiceAssistantCapabilities::calculate_size() const { @@ -272,8 +272,8 @@ uint32_t VoiceAssistantCapabilities::calculate_size() const { #ifdef USE_ZWAVE_PROXY uint8_t *ZWaveProxyCapabilities::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->feature_flags); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->home_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->feature_flags); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->home_id); return pos; } uint32_t ZWaveProxyCapabilities::calculate_size() const { @@ -286,17 +286,17 @@ uint32_t ZWaveProxyCapabilities::calculate_size() const { uint8_t *DeviceCapabilitiesResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); #ifdef USE_BLUETOOTH_PROXY - ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 1, this->bluetooth_proxy); + pos = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 1, this->bluetooth_proxy); #endif #ifdef USE_VOICE_ASSISTANT - ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, this->voice_assistant); + pos = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, this->voice_assistant); #endif #ifdef USE_ZWAVE_PROXY - ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, this->zwave_proxy); + pos = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, this->zwave_proxy); #endif #ifdef USE_SERIAL_PROXY for (const auto &it : this->serial_proxies) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); } #endif return pos; @@ -322,18 +322,18 @@ uint32_t DeviceCapabilitiesResponse::calculate_size() const { #ifdef USE_BINARY_SENSOR uint8_t *ListEntitiesBinarySensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_class); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->is_status_binary_sensor); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->is_status_binary_sensor); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->icon); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, static_cast(this->entity_category)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif return pos; } @@ -356,11 +356,11 @@ uint32_t ListEntitiesBinarySensorResponse::calculate_size() const { } uint8_t *BinarySensorStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -378,21 +378,21 @@ uint32_t BinarySensorStateResponse::calculate_size() const { #ifdef USE_COVER uint8_t *ListEntitiesCoverResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->assumed_state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_position); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_tilt); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->assumed_state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_position); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_tilt); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->icon); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->entity_category)); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supports_stop); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supports_stop); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_id); #endif return pos; } @@ -418,12 +418,16 @@ uint32_t ListEntitiesCoverResponse::calculate_size() const { } uint8_t *CoverStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->position); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 4, this->tilt); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, static_cast(this->current_operation)); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + if (uint32_t raw = float_to_raw(this->position); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, raw); + } + if (uint32_t raw = float_to_raw(this->tilt); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 37, raw); + } + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, static_cast(this->current_operation)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); #endif return pos; } @@ -479,23 +483,23 @@ bool CoverCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_FAN uint8_t *ListEntitiesFanResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_oscillation); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_speed); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_direction); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supported_speed_count); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_oscillation); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_speed); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->supports_direction); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supported_speed_count); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->icon); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->entity_category)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->entity_category)); for (const char *it : *this->supported_preset_modes) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 12, it, strlen(it), true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 12, it, strlen(it)); } #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_id); #endif return pos; } @@ -525,14 +529,14 @@ uint32_t ListEntitiesFanResponse::calculate_size() const { } uint8_t *FanStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->oscillating); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, static_cast(this->direction)); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->speed_level); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, this->preset_mode); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->oscillating); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, static_cast(this->direction)); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->speed_level); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, this->preset_mode); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif return pos; } @@ -613,24 +617,28 @@ bool FanCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_LIGHT uint8_t *ListEntitiesLightResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); for (const auto &it : *this->supported_color_modes) { - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast(it), true); + pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast(it)); + } + if (uint32_t raw = float_to_raw(this->min_mireds); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 77, raw); + } + if (uint32_t raw = float_to_raw(this->max_mireds); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 85, raw); } - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 9, this->min_mireds); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->max_mireds); for (const char *it : *this->effects) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, it, strlen(it), true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 11, it, strlen(it)); } - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 13, this->disabled_by_default); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 13, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 14, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 14, this->icon); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, static_cast(this->entity_category)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 15, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, this->device_id); #endif return pos; } @@ -661,21 +669,39 @@ uint32_t ListEntitiesLightResponse::calculate_size() const { } uint8_t *LightStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->brightness); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->color_mode)); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->color_brightness); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 4, this->red); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 5, this->green); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 6, this->blue); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 7, this->white); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->color_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 12, this->cold_white); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 13, this->warm_white); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->effect); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + if (uint32_t raw = float_to_raw(this->brightness); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, raw); + } + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->color_mode)); + if (uint32_t raw = float_to_raw(this->color_brightness); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 85, raw); + } + if (uint32_t raw = float_to_raw(this->red); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 37, raw); + } + if (uint32_t raw = float_to_raw(this->green); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 45, raw); + } + if (uint32_t raw = float_to_raw(this->blue); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 53, raw); + } + if (uint32_t raw = float_to_raw(this->white); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 61, raw); + } + if (uint32_t raw = float_to_raw(this->color_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 69, raw); + } + if (uint32_t raw = float_to_raw(this->cold_white); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 101, raw); + } + if (uint32_t raw = float_to_raw(this->warm_white); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 109, raw); + } + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->effect); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); #endif return pos; } @@ -811,21 +837,21 @@ bool LightCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SENSOR uint8_t *ListEntitiesSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->unit_of_measurement); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->accuracy_decimals); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->force_update); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_class); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->state_class)); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->unit_of_measurement); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->accuracy_decimals); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->force_update); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_class); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->state_class)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); #endif return pos; } @@ -853,11 +879,13 @@ __attribute__((optimize("O2"))) // NOLINT(clang-diagnostic-unknown-attributes) uint8_t * SensorStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + if (uint32_t raw = float_to_raw(this->state); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, raw); + } + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -877,18 +905,18 @@ SensorStateResponse::calculate_size() const { #ifdef USE_SWITCH uint8_t *ListEntitiesSwitchResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->assumed_state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast(this->entity_category)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->assumed_state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_class); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif return pos; } @@ -911,10 +939,10 @@ uint32_t ListEntitiesSwitchResponse::calculate_size() const { } uint8_t *SwitchStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif return pos; } @@ -956,17 +984,17 @@ bool SwitchCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_TEXT_SENSOR uint8_t *ListEntitiesTextSensorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif return pos; } @@ -988,11 +1016,11 @@ uint32_t ListEntitiesTextSensorResponse::calculate_size() const { } uint8_t *TextSensorStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -1024,10 +1052,10 @@ __attribute__((optimize("O2"))) // NOLINT(clang-diagnostic-unknown-attributes) uint8_t * SubscribeLogsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->level), true); - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 26); - ProtoEncode::encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, this->message_len_); - ProtoEncode::encode_raw(pos PROTO_ENCODE_DEBUG_ARG, this->message_ptr_, this->message_len_); + pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->level)); + pos = ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 26); + pos = ProtoEncode::encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, this->message_len_); + pos = ProtoEncode::encode_raw(pos PROTO_ENCODE_DEBUG_ARG, this->message_ptr_, this->message_len_); return pos; } __attribute__((optimize("O2"))) // NOLINT(clang-diagnostic-unknown-attributes) @@ -1053,7 +1081,7 @@ bool NoiseEncryptionSetKeyRequest::decode_length(uint32_t field_id, ProtoLengthD } uint8_t *NoiseEncryptionSetKeyResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->success); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->success); return pos; } uint32_t NoiseEncryptionSetKeyResponse::calculate_size() const { @@ -1065,8 +1093,8 @@ uint32_t NoiseEncryptionSetKeyResponse::calculate_size() const { #ifdef USE_API_HOMEASSISTANT_SERVICES uint8_t *HomeassistantServiceMap::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->value); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->key); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->value); return pos; } uint32_t HomeassistantServiceMap::calculate_size() const { @@ -1077,25 +1105,25 @@ uint32_t HomeassistantServiceMap::calculate_size() const { } uint8_t *HomeassistantActionRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->service); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->service); for (auto &it : this->data) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, it); } for (auto &it : this->data_template) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); } for (auto &it : this->variables) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); } - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->is_event); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->is_event); #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->call_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->call_id); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->wants_response); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->wants_response); #endif #ifdef USE_API_HOMEASSISTANT_ACTION_RESPONSES_JSON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->response_template); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->response_template); #endif return pos; } @@ -1166,9 +1194,9 @@ bool HomeassistantActionResponse::decode_length(uint32_t field_id, ProtoLengthDe #ifdef USE_API_HOMEASSISTANT_STATES uint8_t *SubscribeHomeAssistantStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->entity_id); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->attribute); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->once); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->entity_id); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->attribute); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->once); return pos; } uint32_t SubscribeHomeAssistantStateResponse::calculate_size() const { @@ -1273,13 +1301,13 @@ bool GetTimeResponse::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_API_USER_DEFINED_ACTIONS uint8_t *ListEntitiesServicesArgument::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->type)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->type)); #ifdef USE_API_USER_DEFINED_ACTION_METADATA - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->description); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->description); #endif #ifdef USE_API_USER_DEFINED_ACTION_METADATA - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->example); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->example); #endif return pos; } @@ -1297,14 +1325,14 @@ uint32_t ListEntitiesServicesArgument::calculate_size() const { } uint8_t *ListEntitiesServicesResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->name); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); for (auto &it : this->args) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast(this->supports_response)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast(this->supports_response)); #ifdef USE_API_USER_DEFINED_ACTION_METADATA - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->description); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->description); #endif return pos; } @@ -1430,11 +1458,11 @@ void ExecuteServiceRequest::decode(const uint8_t *buffer, size_t length) { #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES uint8_t *ExecuteServiceResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->call_id); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error_message); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->call_id); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error_message); #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES_JSON - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 4, this->response_data, this->response_data_len); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 4, this->response_data, this->response_data_len); #endif return pos; } @@ -1452,16 +1480,16 @@ uint32_t ExecuteServiceResponse::calculate_size() const { #ifdef USE_CAMERA uint8_t *ListEntitiesCameraResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->icon); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif return pos; } @@ -1482,11 +1510,11 @@ uint32_t ListEntitiesCameraResponse::calculate_size() const { } uint8_t *CameraImageResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data_ptr_, this->data_len_); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->done); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data_ptr_, this->data_len_); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->done); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -1517,48 +1545,54 @@ bool CameraImageRequest::decode_varint(uint32_t field_id, proto_varint_value_t v #ifdef USE_CLIMATE uint8_t *ListEntitiesClimateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_current_temperature); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_two_point_target_temperature); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->supports_current_temperature); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->supports_two_point_target_temperature); for (const auto &it : *this->supported_modes) { - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(it), true); + pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(it)); } - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->visual_min_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 9, this->visual_max_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->visual_target_temperature_step); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supports_action); + if (uint32_t raw = float_to_raw(this->visual_min_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 69, raw); + } + if (uint32_t raw = float_to_raw(this->visual_max_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 77, raw); + } + if (uint32_t raw = float_to_raw(this->visual_target_temperature_step); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 85, raw); + } + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supports_action); for (const auto &it : *this->supported_fan_modes) { - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast(it), true); + pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast(it)); } for (const auto &it : *this->supported_swing_modes) { - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, static_cast(it), true); + pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 14, static_cast(it)); } for (const char *it : *this->supported_custom_fan_modes) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 15, it, strlen(it), true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 15, it, strlen(it)); } for (const auto &it : *this->supported_presets) { - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, static_cast(it), true); + pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 16, static_cast(it)); } for (const char *it : *this->supported_custom_presets) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 17, it, strlen(it), true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 17, it, strlen(it)); } - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 18, this->disabled_by_default); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 18, this->disabled_by_default); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 19, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 19, this->icon); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 20, static_cast(this->entity_category)); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 21, this->visual_current_temperature_step); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 22, this->supports_current_humidity); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 23, this->supports_target_humidity); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 24, this->visual_min_humidity); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 25, this->visual_max_humidity); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 20, static_cast(this->entity_category)); + pos = ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 21, this->visual_current_temperature_step); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 22, this->supports_current_humidity); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 23, this->supports_target_humidity); + pos = ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 24, this->visual_min_humidity); + pos = ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 25, this->visual_max_humidity); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 26, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 26, this->device_id); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 27, this->feature_flags); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 28, static_cast(this->temperature_unit)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 27, this->feature_flags); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 28, static_cast(this->temperature_unit)); return pos; } uint32_t ListEntitiesClimateResponse::calculate_size() const { @@ -1613,22 +1647,34 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { } uint8_t *ClimateStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->mode)); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->current_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 4, this->target_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 5, this->target_temperature_low); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 6, this->target_temperature_high); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast(this->action)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, static_cast(this->fan_mode)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->swing_mode)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->custom_fan_mode); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast(this->preset)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->custom_preset); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 14, this->current_humidity); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 15, this->target_humidity); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->mode)); + if (uint32_t raw = float_to_raw(this->current_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, raw); + } + if (uint32_t raw = float_to_raw(this->target_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 37, raw); + } + if (uint32_t raw = float_to_raw(this->target_temperature_low); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 45, raw); + } + if (uint32_t raw = float_to_raw(this->target_temperature_high); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 53, raw); + } + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast(this->action)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, static_cast(this->fan_mode)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->swing_mode)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->custom_fan_mode); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast(this->preset)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->custom_preset); + if (uint32_t raw = float_to_raw(this->current_humidity); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 117, raw); + } + if (uint32_t raw = float_to_raw(this->target_humidity); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 125, raw); + } #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 16, this->device_id); #endif return pos; } @@ -1748,25 +1794,31 @@ bool ClimateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_WATER_HEATER uint8_t *ListEntitiesWaterHeaterResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); #endif - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->min_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 9, this->max_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 10, this->target_temperature_step); - for (const auto &it : *this->supported_modes) { - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(it), true); + if (uint32_t raw = float_to_raw(this->min_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 69, raw); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supported_features); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast(this->temperature_unit)); + if (uint32_t raw = float_to_raw(this->max_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 77, raw); + } + if (uint32_t raw = float_to_raw(this->target_temperature_step); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 85, raw); + } + for (const auto &it : *this->supported_modes) { + pos = ProtoEncode::encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(it)); + } + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->supported_features); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 13, static_cast(this->temperature_unit)); return pos; } uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { @@ -1794,16 +1846,24 @@ uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { } uint8_t *WaterHeaterStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->current_temperature); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->target_temperature); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast(this->mode)); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + if (uint32_t raw = float_to_raw(this->current_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, raw); + } + if (uint32_t raw = float_to_raw(this->target_temperature); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, raw); + } + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast(this->mode)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_id); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->state); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 7, this->target_temperature_low); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->target_temperature_high); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->state); + if (uint32_t raw = float_to_raw(this->target_temperature_low); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 61, raw); + } + if (uint32_t raw = float_to_raw(this->target_temperature_high); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 69, raw); + } return pos; } uint32_t WaterHeaterStateResponse::calculate_size() const { @@ -1864,22 +1924,28 @@ bool WaterHeaterCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value #ifdef USE_NUMBER uint8_t *ListEntitiesNumberResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 6, this->min_value); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 7, this->max_value); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 8, this->step); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->entity_category)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->unit_of_measurement); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast(this->mode)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_class); + if (uint32_t raw = float_to_raw(this->min_value); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 53, raw); + } + if (uint32_t raw = float_to_raw(this->max_value); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 61, raw); + } + if (uint32_t raw = float_to_raw(this->step); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 69, raw); + } + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->unit_of_measurement); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, static_cast(this->mode)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 13, this->device_class); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 14, this->device_id); #endif return pos; } @@ -1906,11 +1972,13 @@ uint32_t ListEntitiesNumberResponse::calculate_size() const { } uint8_t *NumberStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + if (uint32_t raw = float_to_raw(this->state); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, raw); + } + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -1953,19 +2021,19 @@ bool NumberCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SELECT uint8_t *ListEntitiesSelectResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif for (const char *it : *this->options) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, it, strlen(it), true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 6, it, strlen(it)); } - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 7, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif return pos; } @@ -1991,11 +2059,11 @@ uint32_t ListEntitiesSelectResponse::calculate_size() const { } uint8_t *SelectStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -2046,21 +2114,21 @@ bool SelectCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_SIREN uint8_t *ListEntitiesSirenResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); for (const char *it : *this->tones) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, it, strlen(it), true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 7, it, strlen(it)); } - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supports_duration); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->supports_volume); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supports_duration); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->supports_volume); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); #endif return pos; } @@ -2088,10 +2156,10 @@ uint32_t ListEntitiesSirenResponse::calculate_size() const { } uint8_t *SirenStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif return pos; } @@ -2162,20 +2230,20 @@ bool SirenCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_LOCK uint8_t *ListEntitiesLockResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->assumed_state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->supports_open); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->requires_code); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->code_format); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 8, this->assumed_state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->supports_open); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->requires_code); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 11, this->code_format); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); #endif return pos; } @@ -2200,10 +2268,10 @@ uint32_t ListEntitiesLockResponse::calculate_size() const { } uint8_t *LockStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->state)); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->state)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif return pos; } @@ -2259,17 +2327,17 @@ bool LockCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_BUTTON uint8_t *ListEntitiesButtonResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif return pos; } @@ -2315,11 +2383,11 @@ bool ButtonCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_MEDIA_PLAYER uint8_t *MediaPlayerSupportedFormat::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->format); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->sample_rate); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->num_channels); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast(this->purpose)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->sample_bytes); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->format); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->sample_rate); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->num_channels); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, static_cast(this->purpose)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->sample_bytes); return pos; } uint32_t MediaPlayerSupportedFormat::calculate_size() const { @@ -2333,21 +2401,21 @@ uint32_t MediaPlayerSupportedFormat::calculate_size() const { } uint8_t *ListEntitiesMediaPlayerResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); for (auto &it : this->supported_formats) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 9, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 9, it); } #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->feature_flags); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->feature_flags); return pos; } uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { @@ -2373,12 +2441,14 @@ uint32_t ListEntitiesMediaPlayerResponse::calculate_size() const { } uint8_t *MediaPlayerStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->state)); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->volume); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 4, this->muted); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->state)); + if (uint32_t raw = float_to_raw(this->volume); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, raw); + } + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 4, this->muted); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->device_id); #endif return pos; } @@ -2465,20 +2535,20 @@ BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCO uint8_t *__restrict__ pos = buffer.get_pos(); for (uint16_t i = 0; i < this->advertisements_len; i++) { auto &sub_msg = this->advertisements[i]; - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 10); + pos = ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 10); uint8_t *len_pos = pos; - ProtoEncode::reserve_byte(pos PROTO_ENCODE_DEBUG_ARG); - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 8); - ProtoEncode::encode_varint_raw_48bit(pos PROTO_ENCODE_DEBUG_ARG, sub_msg.address); - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 16); - ProtoEncode::encode_varint_raw_short(pos PROTO_ENCODE_DEBUG_ARG, encode_zigzag32(sub_msg.rssi)); + pos = ProtoEncode::reserve_byte(pos PROTO_ENCODE_DEBUG_ARG); + pos = ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 8); + pos = ProtoEncode::encode_varint_raw_48bit(pos PROTO_ENCODE_DEBUG_ARG, sub_msg.address); + pos = ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 16); + pos = ProtoEncode::encode_varint_raw_short(pos PROTO_ENCODE_DEBUG_ARG, encode_zigzag32(sub_msg.rssi)); if (sub_msg.address_type) { - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 24); - ProtoEncode::encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, sub_msg.address_type); + pos = ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 24); + pos = ProtoEncode::encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, sub_msg.address_type); } - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 34); - ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, static_cast(sub_msg.data_len)); - ProtoEncode::encode_raw(pos PROTO_ENCODE_DEBUG_ARG, sub_msg.data, sub_msg.data_len); + pos = ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, 34); + pos = ProtoEncode::write_raw_byte(pos PROTO_ENCODE_DEBUG_ARG, static_cast(sub_msg.data_len)); + pos = ProtoEncode::encode_raw(pos PROTO_ENCODE_DEBUG_ARG, sub_msg.data, sub_msg.data_len); *len_pos = static_cast(pos - len_pos - 1); } return pos; @@ -2520,10 +2590,10 @@ bool BluetoothDeviceRequest::decode_varint(uint32_t field_id, proto_varint_value } uint8_t *BluetoothDeviceConnectionResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->connected); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->mtu); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->error); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->connected); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->mtu); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->error); return pos; } uint32_t BluetoothDeviceConnectionResponse::calculate_size() const { @@ -2547,11 +2617,11 @@ bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, proto_var uint8_t *BluetoothGATTDescriptor::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); if (this->uuid[0] != 0 || this->uuid[1] != 0) { - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0], true); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1], true); + pos = ProtoEncode::encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0]); + pos = ProtoEncode::encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1]); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->short_uuid); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->short_uuid); return pos; } uint32_t BluetoothGATTDescriptor::calculate_size() const { @@ -2567,15 +2637,15 @@ uint32_t BluetoothGATTDescriptor::calculate_size() const { uint8_t *BluetoothGATTCharacteristic::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); if (this->uuid[0] != 0 || this->uuid[1] != 0) { - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0], true); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1], true); + pos = ProtoEncode::encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0]); + pos = ProtoEncode::encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1]); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->properties); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->properties); for (auto &it : this->descriptors) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, it); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->short_uuid); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->short_uuid); return pos; } uint32_t BluetoothGATTCharacteristic::calculate_size() const { @@ -2597,14 +2667,14 @@ uint32_t BluetoothGATTCharacteristic::calculate_size() const { uint8_t *BluetoothGATTService::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); if (this->uuid[0] != 0 || this->uuid[1] != 0) { - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0], true); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1], true); + pos = ProtoEncode::encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[0]); + pos = ProtoEncode::encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, 1, this->uuid[1]); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); for (auto &it : this->characteristics) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 3, it); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->short_uuid); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->short_uuid); return pos; } uint32_t BluetoothGATTService::calculate_size() const { @@ -2624,9 +2694,9 @@ uint32_t BluetoothGATTService::calculate_size() const { } uint8_t *BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); for (auto &it : this->services) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 2, it); } return pos; } @@ -2642,7 +2712,7 @@ uint32_t BluetoothGATTGetServicesResponse::calculate_size() const { } uint8_t *BluetoothGATTGetServicesDoneResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); return pos; } uint32_t BluetoothGATTGetServicesDoneResponse::calculate_size() const { @@ -2665,9 +2735,9 @@ bool BluetoothGATTReadRequest::decode_varint(uint32_t field_id, proto_varint_val } uint8_t *BluetoothGATTReadResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data_ptr_, this->data_len_); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data_ptr_, this->data_len_); return pos; } uint32_t BluetoothGATTReadResponse::calculate_size() const { @@ -2761,9 +2831,9 @@ bool BluetoothGATTNotifyRequest::decode_varint(uint32_t field_id, proto_varint_v } uint8_t *BluetoothGATTNotifyDataResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data_ptr_, this->data_len_); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data_ptr_, this->data_len_); return pos; } uint32_t BluetoothGATTNotifyDataResponse::calculate_size() const { @@ -2775,11 +2845,11 @@ uint32_t BluetoothGATTNotifyDataResponse::calculate_size() const { } uint8_t *BluetoothConnectionsFreeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->free); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->limit); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->free); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->limit); for (const auto &it : this->allocated) { if (it != 0) { - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 3, it, true); + pos = ProtoEncode::encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, 3, it); } } return pos; @@ -2797,9 +2867,9 @@ uint32_t BluetoothConnectionsFreeResponse::calculate_size() const { } uint8_t *BluetoothGATTErrorResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); return pos; } uint32_t BluetoothGATTErrorResponse::calculate_size() const { @@ -2811,8 +2881,8 @@ uint32_t BluetoothGATTErrorResponse::calculate_size() const { } uint8_t *BluetoothGATTWriteResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); return pos; } uint32_t BluetoothGATTWriteResponse::calculate_size() const { @@ -2823,8 +2893,8 @@ uint32_t BluetoothGATTWriteResponse::calculate_size() const { } uint8_t *BluetoothGATTNotifyResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->handle); return pos; } uint32_t BluetoothGATTNotifyResponse::calculate_size() const { @@ -2835,9 +2905,9 @@ uint32_t BluetoothGATTNotifyResponse::calculate_size() const { } uint8_t *BluetoothDevicePairingResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->paired); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->paired); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); return pos; } uint32_t BluetoothDevicePairingResponse::calculate_size() const { @@ -2849,9 +2919,9 @@ uint32_t BluetoothDevicePairingResponse::calculate_size() const { } uint8_t *BluetoothDeviceUnpairingResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); return pos; } uint32_t BluetoothDeviceUnpairingResponse::calculate_size() const { @@ -2863,9 +2933,9 @@ uint32_t BluetoothDeviceUnpairingResponse::calculate_size() const { } uint8_t *BluetoothDeviceClearCacheResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->success); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->error); return pos; } uint32_t BluetoothDeviceClearCacheResponse::calculate_size() const { @@ -2879,9 +2949,9 @@ uint32_t BluetoothDeviceClearCacheResponse::calculate_size() const { #ifdef USE_BLUETOOTH_PROXY uint8_t *BluetoothScannerStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->state)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->mode)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->configured_mode)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->state)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->mode)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->configured_mode)); return pos; } uint32_t BluetoothScannerStateResponse::calculate_size() const { @@ -2918,9 +2988,11 @@ bool SubscribeVoiceAssistantRequest::decode_varint(uint32_t field_id, proto_vari } uint8_t *VoiceAssistantAudioSettings::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->noise_suppression_level); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->auto_gain); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 3, this->volume_multiplier); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->noise_suppression_level); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->auto_gain); + if (uint32_t raw = float_to_raw(this->volume_multiplier); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, raw); + } return pos; } uint32_t VoiceAssistantAudioSettings::calculate_size() const { @@ -2932,11 +3004,11 @@ uint32_t VoiceAssistantAudioSettings::calculate_size() const { } uint8_t *VoiceAssistantRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->start); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->conversation_id); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->flags); - ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, this->audio_settings); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->wake_word_phrase); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->start); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->conversation_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->flags); + pos = ProtoEncode::encode_optional_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 4, this->audio_settings); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->wake_word_phrase); return pos; } uint32_t VoiceAssistantRequest::calculate_size() const { @@ -3026,9 +3098,9 @@ bool VoiceAssistantAudio::decode_length(uint32_t field_id, ProtoLengthDelimited } uint8_t *VoiceAssistantAudio::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 1, this->data, this->data_len); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->end); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data2, this->data2_len); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 1, this->data, this->data_len); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->end); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 3, this->data2, this->data2_len); return pos; } uint32_t VoiceAssistantAudio::calculate_size() const { @@ -3103,7 +3175,7 @@ bool VoiceAssistantAnnounceRequest::decode_length(uint32_t field_id, ProtoLength } uint8_t *VoiceAssistantAnnounceFinished::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->success); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 1, this->success); return pos; } uint32_t VoiceAssistantAnnounceFinished::calculate_size() const { @@ -3113,10 +3185,10 @@ uint32_t VoiceAssistantAnnounceFinished::calculate_size() const { } uint8_t *VoiceAssistantWakeWord::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->id); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->wake_word); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 1, this->id); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->wake_word); for (auto &it : this->trained_languages) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 3, it, true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 3, it); } return pos; } @@ -3185,12 +3257,12 @@ bool VoiceAssistantConfigurationRequest::decode_length(uint32_t field_id, ProtoL uint8_t *VoiceAssistantConfigurationResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); for (auto &it : this->available_wake_words) { - ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 1, it); + pos = ProtoEncode::encode_sub_message(pos PROTO_ENCODE_DEBUG_ARG, buffer, 1, it); } for (const auto &it : *this->active_wake_words) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, it, true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 2, it); } - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->max_active_wake_words); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->max_active_wake_words); return pos; } uint32_t VoiceAssistantConfigurationResponse::calculate_size() const { @@ -3222,19 +3294,19 @@ bool VoiceAssistantSetConfiguration::decode_length(uint32_t field_id, ProtoLengt #ifdef USE_ALARM_CONTROL_PANEL uint8_t *ListEntitiesAlarmControlPanelResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supported_features); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->requires_code); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->requires_code_to_arm); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->supported_features); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->requires_code); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->requires_code_to_arm); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); #endif return pos; } @@ -3258,10 +3330,10 @@ uint32_t ListEntitiesAlarmControlPanelResponse::calculate_size() const { } uint8_t *AlarmControlPanelStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->state)); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->state)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif return pos; } @@ -3314,20 +3386,20 @@ bool AlarmControlPanelCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit #ifdef USE_TEXT uint8_t *ListEntitiesTextResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->min_length); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->max_length); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->pattern); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->mode)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->min_length); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->max_length); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->pattern); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, static_cast(this->mode)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); #endif return pos; } @@ -3352,11 +3424,11 @@ uint32_t ListEntitiesTextResponse::calculate_size() const { } uint8_t *TextStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->missing_state); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -3407,16 +3479,16 @@ bool TextCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_DATE uint8_t *ListEntitiesDateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif return pos; } @@ -3437,13 +3509,13 @@ uint32_t ListEntitiesDateResponse::calculate_size() const { } uint8_t *DateStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->year); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->month); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->day); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->year); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->month); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->day); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); #endif return pos; } @@ -3494,16 +3566,16 @@ bool DateCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_TIME uint8_t *ListEntitiesTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif return pos; } @@ -3524,13 +3596,13 @@ uint32_t ListEntitiesTimeResponse::calculate_size() const { } uint8_t *TimeStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->hour); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->minute); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->second); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->hour); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->minute); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 5, this->second); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, this->device_id); #endif return pos; } @@ -3581,20 +3653,20 @@ bool TimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_EVENT uint8_t *ListEntitiesEventResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); for (const char *it : *this->event_types) { - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, it, strlen(it), true); + pos = ProtoEncode::encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, 9, it, strlen(it)); } #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->device_id); #endif return pos; } @@ -3621,10 +3693,10 @@ uint32_t ListEntitiesEventResponse::calculate_size() const { } uint8_t *EventResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->event_type); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 2, this->event_type); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->device_id); #endif return pos; } @@ -3641,20 +3713,20 @@ uint32_t EventResponse::calculate_size() const { #ifdef USE_VALVE uint8_t *ListEntitiesValveResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->assumed_state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->supports_position); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 11, this->supports_stop); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 9, this->assumed_state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 10, this->supports_position); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 11, this->supports_stop); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 12, this->device_id); #endif return pos; } @@ -3679,11 +3751,13 @@ uint32_t ListEntitiesValveResponse::calculate_size() const { } uint8_t *ValveStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 2, this->position); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->current_operation)); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + if (uint32_t raw = float_to_raw(this->position); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, raw); + } + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->current_operation)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -3732,16 +3806,16 @@ bool ValveCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_DATETIME_DATETIME uint8_t *ListEntitiesDateTimeResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_id); #endif return pos; } @@ -3762,11 +3836,13 @@ uint32_t ListEntitiesDateTimeResponse::calculate_size() const { } uint8_t *DateTimeStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); - ProtoEncode::encode_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 3, this->epoch_seconds); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + if (uint32_t raw = this->epoch_seconds; raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, raw); + } #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id); #endif return pos; } @@ -3809,17 +3885,17 @@ bool DateTimeCommandRequest::decode_32bit(uint32_t field_id, Proto32Bit value) { #ifdef USE_UPDATE uint8_t *ListEntitiesUpdateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 5, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 6, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, static_cast(this->entity_category)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->device_class); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->device_id); #endif return pos; } @@ -3841,18 +3917,20 @@ uint32_t ListEntitiesUpdateResponse::calculate_size() const { } uint8_t *UpdateStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->in_progress); - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 4, this->has_progress); - ProtoEncode::encode_float(pos PROTO_ENCODE_DEBUG_ARG, 5, this->progress); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->current_version); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, this->latest_version); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->title); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->release_summary); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->release_url); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 13, this->key); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 2, this->missing_state); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 3, this->in_progress); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 4, this->has_progress); + if (uint32_t raw = float_to_raw(this->progress); raw != 0) [[likely]] { + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 45, raw); + } + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 6, this->current_version); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 7, this->latest_version); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 8, this->title); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 9, this->release_summary); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 10, this->release_url); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->device_id); #endif return pos; } @@ -3916,7 +3994,7 @@ __attribute__((optimize("O2"))) // NOLINT(clang-diagnostic-unknown-attributes) uint8_t * ZWaveProxyFrame::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 1, this->data, this->data_len); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 1, this->data, this->data_len); return pos; } __attribute__((optimize("O2"))) // NOLINT(clang-diagnostic-unknown-attributes) @@ -3950,8 +4028,8 @@ bool ZWaveProxyRequest::decode_length(uint32_t field_id, ProtoLengthDelimited va } uint8_t *ZWaveProxyRequest::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->type)); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data, this->data_len); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->type)); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data, this->data_len); return pos; } uint32_t ZWaveProxyRequest::calculate_size() const { @@ -3962,8 +4040,8 @@ uint32_t ZWaveProxyRequest::calculate_size() const { } uint8_t *ZWaveProxyRequestResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->type)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->status)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, static_cast(this->type)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->status)); return pos; } uint32_t ZWaveProxyRequestResponse::calculate_size() const { @@ -3976,19 +4054,19 @@ uint32_t ZWaveProxyRequestResponse::calculate_size() const { #ifdef USE_INFRARED uint8_t *ListEntitiesInfraredResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->capabilities); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->receiver_frequency); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->capabilities); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->receiver_frequency); return pos; } uint32_t ListEntitiesInfraredResponse::calculate_size() const { @@ -4059,11 +4137,11 @@ uint8_t * InfraredRFReceiveEvent::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->device_id); #endif - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); for (const auto &it : *this->timings) { - ProtoEncode::encode_sint32(pos PROTO_ENCODE_DEBUG_ARG, 3, it, true); + pos = ProtoEncode::encode_sint32_force(pos PROTO_ENCODE_DEBUG_ARG, 3, it); } return pos; } @@ -4086,21 +4164,21 @@ InfraredRFReceiveEvent::calculate_size() const { #ifdef USE_RADIO_FREQUENCY uint8_t *ListEntitiesRadioFrequencyResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); - ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); - ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 10, this->object_id); + pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 21, this->key); + pos = ProtoEncode::encode_short_string_force(pos PROTO_ENCODE_DEBUG_ARG, 26, this->name); #ifdef USE_ENTITY_ICON - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->icon); #endif - ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast(this->entity_category)); + pos = ProtoEncode::encode_bool(pos PROTO_ENCODE_DEBUG_ARG, 5, this->disabled_by_default); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 6, static_cast(this->entity_category)); #ifdef USE_DEVICES - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 7, this->device_id); #endif - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->capabilities); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->frequency_min); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->frequency_max); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->supported_modulations); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 8, this->capabilities); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 9, this->frequency_min); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 10, this->frequency_max); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 11, this->supported_modulations); return pos; } uint32_t ListEntitiesRadioFrequencyResponse::calculate_size() const { @@ -4153,8 +4231,8 @@ __attribute__((optimize("O2"))) // NOLINT(clang-diagnostic-unknown-attributes) uint8_t * SerialProxyDataReceived::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); - ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data_ptr_, this->data_len_); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); + pos = ProtoEncode::encode_bytes(pos PROTO_ENCODE_DEBUG_ARG, 2, this->data_ptr_, this->data_len_); return pos; } __attribute__((optimize("O2"))) // NOLINT(clang-diagnostic-unknown-attributes) @@ -4212,9 +4290,9 @@ bool SerialProxyGetModemPinsRequest::decode_varint(uint32_t field_id, proto_vari } uint8_t *SerialProxyGetModemPinsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->line_states); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->status)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->line_states); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->status)); return pos; } uint32_t SerialProxyGetModemPinsResponse::calculate_size() const { @@ -4239,10 +4317,10 @@ bool SerialProxyRequest::decode_varint(uint32_t field_id, proto_varint_value_t v } uint8_t *SerialProxyRequestResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->type)); - ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->status)); - ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->error_message); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 1, this->instance); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 2, static_cast(this->type)); + pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 3, static_cast(this->status)); + pos = ProtoEncode::encode_string(pos PROTO_ENCODE_DEBUG_ARG, 4, this->error_message); return pos; } uint32_t SerialProxyRequestResponse::calculate_size() const { @@ -4292,8 +4370,8 @@ bool BluetoothSetConnectionParamsRequest::decode_varint(uint32_t field_id, proto } uint8_t *BluetoothSetConnectionParamsResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEBUG_PARAM) const { uint8_t *__restrict__ pos = buffer.get_pos(); - ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); - ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->error); + pos = ProtoEncode::encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, 1, this->address); + pos = ProtoEncode::encode_int32(pos PROTO_ENCODE_DEBUG_ARG, 2, this->error); return pos; } uint32_t BluetoothSetConnectionParamsResponse::calculate_size() const { diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 236e4a474a..61ac5f7701 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -195,6 +195,12 @@ void proto_check_bounds_failed(const uint8_t *pos, size_t bytes, const uint8_t * ESP_LOGE(TAG, "Proto encode bounds check failed in %s: need %zu bytes, %td available", caller, bytes, end - pos); abort(); } +void proto_check_encode_end(const uint8_t *end, const uint8_t *expected) { + if (end == expected) + return; + ESP_LOGE(TAG, "Proto encode ended %td bytes off the calculated size", end - expected); + abort(); +} void ProtoWriteBuffer::debug_check_bounds_(size_t bytes, const char *caller) { if (this->pos_ + bytes > this->buffer_->data() + this->buffer_->size()) { ESP_LOGE(TAG, "ProtoWriteBuffer bounds check failed in %s: bytes=%zu offset=%td buf_size=%zu", caller, bytes, diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index a226e080e8..fab5194edc 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -221,6 +221,9 @@ class Proto32Bit { proto_check_bounds_failed(pos, n, proto_debug_end_, __builtin_FUNCTION()); \ } while (0) void proto_check_bounds_failed(const uint8_t *pos, size_t bytes, const uint8_t *end, const char *caller); +/// Aborts unless an encode body ended exactly where calculate_size() promised. A plain check rather than +/// assert(), so NDEBUG cannot switch it off. +void proto_check_encode_end(const uint8_t *end, const uint8_t *expected); #else #define PROTO_ENCODE_DEBUG_PARAM #define PROTO_ENCODE_DEBUG_ARG @@ -287,19 +290,31 @@ class ProtoWriteBuffer { uint8_t *pos_; }; +// A four byte unaligned store is a memcpy call on ESP-IDF (-fno-builtin-memcpy) and on ARM cores without +// unaligned access (Cortex-M0+, ARM9), so those targets share one outlined byte store helper per fixed32 +// field. Elsewhere the write inlines to a single store, or on ESP8266 to a few stores that measured +// faster than a call, so it stays inline. +#if defined(USE_ESP32) || (defined(__arm__) && !defined(__ARM_FEATURE_UNALIGNED)) +#define PROTO_OUTLINE_FOR_SIZE __attribute__((noinline)) +#define PROTO_FIXED32_BYTE_STORES true +#else +#define PROTO_OUTLINE_FOR_SIZE inline +#define PROTO_FIXED32_BYTE_STORES false +#endif + // Varint encoding thresholds — used by both proto_encode_* free functions and ProtoSize. constexpr uint32_t VARINT_MAX_1_BYTE = 1 << 7; // 128 constexpr uint32_t VARINT_MAX_2_BYTE = 1 << 14; // 16384 -/// Static encode helpers for generated encode() functions. -/// Generated code hoists buffer.pos_ into a local uint8_t *__restrict__ pos, -/// then calls these methods which take pos by reference. No struct, no overhead. -/// For sub-messages, pos is synced back to buffer before the call and reloaded after. +/// Static encode helpers for the generated encode bodies. Each takes the write cursor by value and +/// returns it advanced, so outlined calls at -Os chain through the return register instead of a +/// stack slot. Helpers without a _force suffix skip fields holding the proto3 default. class ProtoEncode { public: /// Write a multi-byte varint directly through a pos pointer. template - static inline void encode_varint_raw_loop(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, T value) { + [[nodiscard]] static inline uint8_t *encode_varint_raw_loop(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + T value) { do { PROTO_ENCODE_CHECK_BOUNDS(pos, 1); *pos++ = static_cast(value | 0x80); @@ -307,48 +322,49 @@ class ProtoEncode { } while (value > 0x7F); PROTO_ENCODE_CHECK_BOUNDS(pos, 1); *pos++ = static_cast(value); + return pos; } - static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - uint32_t value) { + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + encode_varint_raw(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint32_t value) { if (value < VARINT_MAX_1_BYTE) [[likely]] { PROTO_ENCODE_CHECK_BOUNDS(pos, 1); *pos++ = static_cast(value); - return; + return pos; } - encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); + return encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); } /// Encode a varint that is expected to be 1-2 bytes (e.g. zigzag RSSI, small lengths). - static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_short(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - uint32_t value) { + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + encode_varint_raw_short(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint32_t value) { if (value < VARINT_MAX_1_BYTE) [[likely]] { PROTO_ENCODE_CHECK_BOUNDS(pos, 1); *pos++ = static_cast(value); - return; + return pos; } if (value < VARINT_MAX_2_BYTE) [[likely]] { PROTO_ENCODE_CHECK_BOUNDS(pos, 2); *pos++ = static_cast(value | 0x80); *pos++ = static_cast(value >> 7); - return; + return pos; } - encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); + return encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); } - static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - uint64_t value) { + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + encode_varint_raw_64(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint64_t value) { if (value < VARINT_MAX_1_BYTE) [[likely]] { PROTO_ENCODE_CHECK_BOUNDS(pos, 1); *pos++ = static_cast(value); - return; + return pos; } - encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); + return encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, value); } /// Encode a 48-bit MAC address (stored in a uint64) as varint. /// Real MAC addresses occupy the full 48 bits (OUI in upper 24), so the /// fast path -- any non-zero bit in the top 6 of 48 -- emits exactly 7 bytes /// with no per-byte branch. Falls back to the general loop otherwise. /// Caller must guarantee value fits in 48 bits (checked in debug builds). - static inline void ESPHOME_ALWAYS_INLINE encode_varint_raw_48bit(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - uint64_t value) { + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + encode_varint_raw_48bit(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint64_t value) { #ifdef ESPHOME_DEBUG_API assert(value < (1ULL << (MAC_ADDRESS_SIZE * 8)) && "encode_varint_raw_48bit: value exceeds 48 bits"); #endif @@ -363,38 +379,39 @@ class ProtoEncode { pos[4] = static_cast((value >> 28) | 0x80); pos[5] = static_cast((value >> 35) | 0x80); pos[6] = static_cast(value >> 42); - pos += 7; - return; + return pos + 7; } - encode_varint_raw_64(pos PROTO_ENCODE_DEBUG_ARG, value); + return encode_varint_raw_64(pos PROTO_ENCODE_DEBUG_ARG, value); } - static inline void ESPHOME_ALWAYS_INLINE encode_field_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - uint32_t field_id, uint32_t type) { - encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, (field_id << 3) | type); + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + encode_field_raw(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, uint32_t type) { + return encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, (field_id << 3) | type); } /// Write a single precomputed tag byte. Tag must be < 128. - static inline void ESPHOME_ALWAYS_INLINE write_raw_byte(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - uint8_t b) { + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + write_raw_byte(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t b) { PROTO_ENCODE_CHECK_BOUNDS(pos, 1); *pos++ = b; + return pos; } /// Reserve one byte for later backpatch (e.g., sub-message length). /// Advances pos past the reserved byte without writing a value. - static inline void ESPHOME_ALWAYS_INLINE reserve_byte(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM) { + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + reserve_byte(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM) { PROTO_ENCODE_CHECK_BOUNDS(pos, 1); - pos++; + return pos + 1; } /// Write raw bytes to the buffer (no tag, no length prefix). - static inline void ESPHOME_ALWAYS_INLINE encode_raw(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - const void *data, size_t len) { + [[nodiscard]] static inline uint8_t *ESPHOME_ALWAYS_INLINE + encode_raw(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, const void *data, size_t len) { PROTO_ENCODE_CHECK_BOUNDS(pos, len); std::memcpy(pos, data, len); - pos += len; + return pos + len; } /// Encode tag + 1-byte length + raw string data. For strings with max_data_length < 128. /// Tag must be a single-byte varint (< 128). Always encodes (no zero check). - static inline void encode_short_string_force(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, - const StringRef &ref) { + [[nodiscard]] static inline uint8_t *encode_short_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint8_t tag, const StringRef &ref) { #ifdef ESPHOME_DEBUG_API assert(ref.size() < 128 && "encode_short_string_force: string exceeds max_data_length < 128"); #endif @@ -402,137 +419,191 @@ class ProtoEncode { pos[0] = tag; pos[1] = static_cast(ref.size()); std::memcpy(pos + 2, ref.c_str(), ref.size()); - pos += 2 + ref.size(); + return pos + 2 + ref.size(); } - /// Write a precomputed tag byte + 32-bit value in one operation. - static inline void ESPHOME_ALWAYS_INLINE write_tag_and_fixed32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - uint8_t tag, uint32_t value) { + /// Write a precomputed tag byte + 32-bit value. Outlined on embedded: one copy beats inline stores per field. + [[nodiscard]] static PROTO_OUTLINE_FOR_SIZE uint8_t *write_tag_and_fixed32( + uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint8_t tag, uint32_t value) { PROTO_ENCODE_CHECK_BOUNDS(pos, 5); pos[0] = tag; -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - std::memcpy(pos + 1, &value, 4); -#else - pos[1] = static_cast(value & 0xFF); - pos[2] = static_cast((value >> 8) & 0xFF); - pos[3] = static_cast((value >> 16) & 0xFF); - pos[4] = static_cast((value >> 24) & 0xFF); -#endif - pos += 5; + write_fixed32_le(pos + 1, value); + return pos + 5; } - static inline void encode_string(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - const char *string, size_t len, bool force = false) { - if (len == 0 && !force) - return; - encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 2); // type 2: Length-delimited string + [[nodiscard]] static inline uint8_t *encode_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, const char *string, size_t len) { + pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 2); // type 2: Length-delimited string // NOLINTNEXTLINE(readability-inconsistent-ifelse-braces) -- false positive on [[likely]] attribute if (len < VARINT_MAX_1_BYTE) [[likely]] { PROTO_ENCODE_CHECK_BOUNDS(pos, 1 + len); *pos++ = static_cast(len); } else { - encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, len); + pos = encode_varint_raw_loop(pos PROTO_ENCODE_DEBUG_ARG, len); PROTO_ENCODE_CHECK_BOUNDS(pos, len); } std::memcpy(pos, string, len); - pos += len; + return pos + len; } - static inline void encode_string(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - const std::string &value, bool force = false) { - encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, value.data(), value.size(), force); + [[nodiscard]] static inline uint8_t *encode_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, const char *string, size_t len) { + if (len == 0) + return pos; + return encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, string, len); } - static inline void encode_string(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - const StringRef &ref, bool force = false) { - encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, ref.c_str(), ref.size(), force); + [[nodiscard]] static inline uint8_t *encode_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, const std::string &value) { + return encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, value.data(), value.size()); } - static inline void encode_bytes(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - const uint8_t *data, size_t len, bool force = false) { - encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, reinterpret_cast(data), len, force); + [[nodiscard]] static inline uint8_t *encode_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, const StringRef &ref) { + return encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, ref.c_str(), ref.size()); } - static inline void encode_uint32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - uint32_t value, bool force = false) { - if (value == 0 && !force) - return; - encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); - encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, value); + [[nodiscard]] static inline uint8_t *encode_string_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, const StringRef &ref) { + return encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, ref.c_str(), ref.size()); } - static inline void encode_uint64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - uint64_t value, bool force = false) { - if (value == 0 && !force) - return; - encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); - encode_varint_raw_64(pos PROTO_ENCODE_DEBUG_ARG, value); + [[nodiscard]] static inline uint8_t *encode_bytes(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, const uint8_t *data, size_t len) { + return encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, reinterpret_cast(data), len); } - static inline void encode_bool(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, bool value, - bool force = false) { - if (!value && !force) - return; - encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); + [[nodiscard]] static inline uint8_t *encode_bytes_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, const uint8_t *data, size_t len) { + return encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, reinterpret_cast(data), len); + } + [[nodiscard]] static inline uint8_t *encode_uint32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, uint32_t value) { + pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); + return encode_varint_raw(pos PROTO_ENCODE_DEBUG_ARG, value); + } + [[nodiscard]] static inline uint8_t *encode_uint32(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, uint32_t value) { + if (value == 0) + return pos; + return encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, value); + } + [[nodiscard]] static inline uint8_t *encode_uint64_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, uint64_t value) { + pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); + return encode_varint_raw_64(pos PROTO_ENCODE_DEBUG_ARG, value); + } + [[nodiscard]] static inline uint8_t *encode_uint64(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, uint64_t value) { + if (value == 0) + return pos; + return encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, value); + } + [[nodiscard]] static inline uint8_t *encode_bool_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, bool value) { + pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 0); PROTO_ENCODE_CHECK_BOUNDS(pos, 1); *pos++ = value ? 0x01 : 0x00; + return pos; } - static inline void encode_fixed32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - uint32_t value, bool force = false) { - if (value == 0 && !force) - return; - encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 5); + [[nodiscard]] static inline uint8_t *encode_bool(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, bool value) { + if (!value) + return pos; + return encode_bool_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, value); + } + /// Tag + fixed32 for multi-byte tags; single-byte tags use write_tag_and_fixed32. + [[nodiscard]] static PROTO_OUTLINE_FOR_SIZE uint8_t *encode_fixed32_force( + uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, uint32_t value) { + pos = encode_field_raw(pos PROTO_ENCODE_DEBUG_ARG, field_id, 5); PROTO_ENCODE_CHECK_BOUNDS(pos, 4); -#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ - std::memcpy(pos, &value, 4); - pos += 4; -#else - *pos++ = (value >> 0) & 0xFF; - *pos++ = (value >> 8) & 0xFF; - *pos++ = (value >> 16) & 0xFF; - *pos++ = (value >> 24) & 0xFF; -#endif + write_fixed32_le(pos, value); + return pos + 4; + } + [[nodiscard]] static inline uint8_t *encode_fixed32(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, uint32_t value) { + if (value == 0) + return pos; + return encode_fixed32_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, value); } // NOTE: Wire type 1 (64-bit fixed: double, fixed64, sfixed64) is intentionally // not supported to reduce overhead on embedded systems. All ESPHome devices are // 32-bit microcontrollers where 64-bit operations are expensive. If 64-bit support // is needed in the future, the necessary encoding/decoding functions must be added. - static inline void encode_float(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, float value, - bool force = false) { - uint32_t raw = float_to_raw(value); - if (raw == 0 && !force) - return; - encode_fixed32(pos PROTO_ENCODE_DEBUG_ARG, field_id, raw); + [[nodiscard]] static inline uint8_t *encode_float(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, float value) { + return encode_fixed32(pos PROTO_ENCODE_DEBUG_ARG, field_id, float_to_raw(value)); } - static inline void encode_int32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, int32_t value, - bool force = false) { + [[nodiscard]] static inline uint8_t *encode_float_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, float value) { + return encode_fixed32_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, float_to_raw(value)); + } + [[nodiscard]] static inline uint8_t *encode_int32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int32_t value) { if (value < 0) { // negative int32 is always 10 byte long - encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast(value), force); - return; + return encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast(value)); } - encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast(value), force); + return encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast(value)); } - static inline void encode_int64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, int64_t value, - bool force = false) { - encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast(value), force); + [[nodiscard]] static inline uint8_t *encode_int32(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int32_t value) { + if (value == 0) + return pos; + return encode_int32_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, value); } - static inline void encode_sint32(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - int32_t value, bool force = false) { - encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag32(value), force); + [[nodiscard]] static inline uint8_t *encode_int64(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int64_t value) { + return encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast(value)); } - static inline void encode_sint64(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id, - int64_t value, bool force = false) { - encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag64(value), force); + [[nodiscard]] static inline uint8_t *encode_int64_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int64_t value) { + return encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, static_cast(value)); } - /// Sub-message encoding: sync pos to buffer, delegate, get pos from return value. + [[nodiscard]] static inline uint8_t *encode_sint32(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int32_t value) { + return encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag32(value)); + } + [[nodiscard]] static inline uint8_t *encode_sint32_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int32_t value) { + return encode_uint32_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag32(value)); + } + [[nodiscard]] static inline uint8_t *encode_sint64(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int64_t value) { + return encode_uint64(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag64(value)); + } + [[nodiscard]] static inline uint8_t *encode_sint64_force(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + uint32_t field_id, int64_t value) { + return encode_uint64_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, encode_zigzag64(value)); + } + /// Sub-message encoding: sync pos to buffer, delegate, read the cursor back. template - static inline void encode_sub_message(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, ProtoWriteBuffer &buffer, - uint32_t field_id, const T &value) { + [[nodiscard]] static inline uint8_t *encode_sub_message(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + ProtoWriteBuffer &buffer, uint32_t field_id, const T &value) { buffer.set_pos(pos); buffer.encode_sub_message(field_id, value); - pos = buffer.get_pos(); + return buffer.get_pos(); } template - static inline void encode_optional_sub_message(uint8_t *__restrict__ &pos PROTO_ENCODE_DEBUG_PARAM, - ProtoWriteBuffer &buffer, uint32_t field_id, const T &value) { + [[nodiscard]] static inline uint8_t *encode_optional_sub_message(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, + ProtoWriteBuffer &buffer, uint32_t field_id, + const T &value) { buffer.set_pos(pos); buffer.encode_optional_sub_message(field_id, value); - pos = buffer.get_pos(); + return buffer.get_pos(); + } + + private: + /// Unaligned little endian store of four bytes: byte stores where the outlined helper lives (ESP-IDF, ARM + /// without unaligned access), otherwise a memcpy the compiler folds into one store. Callers bounds check + /// and advance the cursor themselves. + static inline void ESPHOME_ALWAYS_INLINE write_fixed32_le(uint8_t *__restrict__ pos, uint32_t value) { + if constexpr (PROTO_FIXED32_BYTE_STORES) { + // Spelled out so the outlined helper does not itself become a memcpy call + pos[0] = static_cast(value); + pos[1] = static_cast(value >> 8); + pos[2] = static_cast(value >> 16); + pos[3] = static_cast(value >> 24); + } else { + const uint32_t le = convert_little_endian(value); + __builtin_memcpy(pos, &le, 4); + } } }; +#undef PROTO_OUTLINE_FOR_SIZE +#undef PROTO_FIXED32_BYTE_STORES #ifdef HAS_PROTO_MESSAGE_DUMP /** diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index ca1c5736c8..66d47a10de 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -126,9 +126,10 @@ def camel_to_snake(name: str) -> str: return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower() -def force_str(force: bool) -> str: - """Convert a boolean force value to string format for C++ code.""" - return str(force).lower() +def _encode_call(func: str, *args: str, force: bool = False) -> str: + """Emit one ProtoEncode call; every helper takes the cursor and returns it advanced.""" + suffix = "_force" if force else "" + return f"pos = ProtoEncode::{func}{suffix}({', '.join(('pos', *args))});" class TypeInfo(ABC): @@ -264,14 +265,16 @@ class TypeInfo(ABC): # write_raw_byte(tag) + raw encode instead of the full encode_* method, # eliminating the zero-check branch and encode_field_raw indirection. # {value} is replaced with the actual field expression. - RAW_ENCODE_MAP: dict[str, str] = { - "encode_uint32": "ProtoEncode::encode_varint_raw(pos, {value});", - "encode_uint64": "ProtoEncode::encode_varint_raw_64(pos, {value});", - "encode_sint32": "ProtoEncode::encode_varint_raw_short(pos, encode_zigzag32({value}));", - "encode_sint64": "ProtoEncode::encode_varint_raw_64(pos, encode_zigzag64({value}));", - "encode_int64": "ProtoEncode::encode_varint_raw_64(pos, static_cast({value}));", - "encode_bool": "ProtoEncode::write_raw_byte(pos, {value} ? 0x01 : 0x00);", + RAW_ENCODE_MAP: dict[str, tuple[str, str]] = { + "encode_uint32": ("encode_varint_raw", "{value}"), + "encode_uint64": ("encode_varint_raw_64", "{value}"), + "encode_sint32": ("encode_varint_raw_short", "encode_zigzag32({value})"), + "encode_sint64": ("encode_varint_raw_64", "encode_zigzag64({value})"), + "encode_int64": ("encode_varint_raw_64", "static_cast({value})"), + "encode_bool": ("write_raw_byte", "{value} ? 0x01 : 0x00"), } + # Fixed32 value expression for the shared tag+fixed32 writer; None for other wire types + fixed32_value_template: str | None = None def _encode_with_precomputed_tag(self, value_expr: str) -> str | None: """Try to emit a precomputed-tag encode for a field. @@ -288,12 +291,17 @@ class TypeInfo(ABC): return None max_val = self.max_value # Only use RAW_ENCODE_MAP for forced fields or fields with max_value - raw_expr = None + raw = None if self.force or max_val is not None: - raw_expr = self.RAW_ENCODE_MAP.get(self.encode_func) - if raw_expr is None: + raw = self.RAW_ENCODE_MAP.get(self.encode_func) + if raw is None: return None - body = f"ProtoEncode::write_raw_byte(pos, {tag});\n{raw_expr.format(value=value_expr)}" + func, arg = raw + body = ( + _encode_call("write_raw_byte", str(tag)) + + "\n" + + _encode_call(func, arg.format(value=value_expr)) + ) if self.force: return body # Non-forced with max_value: inline zero-check + raw encode @@ -314,23 +322,43 @@ class TypeInfo(ABC): return None # When max_len < 128, length varint is always 1 byte len_encode = ( - f"ProtoEncode::write_raw_byte(pos, static_cast({len_expr}));" + _encode_call("write_raw_byte", f"static_cast({len_expr})") if max_len is not None and max_len < 128 - else f"ProtoEncode::encode_varint_raw(pos, {len_expr});" + else _encode_call("encode_varint_raw", len_expr) ) + return "\n".join( + ( + _encode_call("write_raw_byte", str(tag)), + len_encode, + _encode_call("encode_raw", data_expr, len_expr), + ) + ) + + def _encode_fixed32_with_precomputed_tag(self, value_expr: str) -> str | None: + """Single-byte tag fixed32 write, or None for multi-byte tags.""" + tag = self.calculate_tag() + if tag >= 128: + return None + if self.force: + return _encode_call("write_tag_and_fixed32", str(tag), value_expr) return ( - f"ProtoEncode::write_raw_byte(pos, {tag});\n" - f"{len_encode}\n" - f"ProtoEncode::encode_raw(pos, {data_expr}, {len_expr});" + f"if (uint32_t raw = {value_expr}; raw != 0) [[likely]] {{\n" + f" {_encode_call('write_tag_and_fixed32', str(tag), 'raw')}\n" + "}" ) @property def encode_content(self) -> str: - if result := self._encode_with_precomputed_tag(f"this->{self.field_name}"): + value = f"this->{self.field_name}" + if result := self._encode_with_precomputed_tag(value): return result - if self.force: - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name}, true);" - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name});" + if self.fixed32_value_template is not None and ( + result := self._encode_fixed32_with_precomputed_tag( + self.fixed32_value_template.format(value=value) + ) + ): + return result + return _encode_call(self.encode_func, str(self.number), value, force=self.force) encode_func = None @@ -635,6 +663,8 @@ class FloatType(FixedSizeTypeMixin, TypeInfo): encode_func = "encode_float" wire_type = WireType.FIXED32 # Uses wire type 5 + fixed32_value_template = "float_to_raw({value})" + def dump(self, name: str) -> str: o = f'snprintf(buffer, sizeof(buffer), "%g", {name});\n' o += "out.append(buffer);" @@ -697,11 +727,11 @@ class UInt64Type(VarintTypeMixin, TypeInfo): return self._get_simple_size_calculation(name, force, "uint64") @property - def RAW_ENCODE_MAP(self) -> dict[str, str]: # noqa: N802 + def RAW_ENCODE_MAP(self) -> dict[str, tuple[str, str]]: # noqa: N802 if self.mac_address: return { **TypeInfo.RAW_ENCODE_MAP, - "encode_uint64": "ProtoEncode::encode_varint_raw_48bit(pos, {value});", + "encode_uint64": ("encode_varint_raw_48bit", "{value}"), } return TypeInfo.RAW_ENCODE_MAP @@ -769,15 +799,7 @@ class Fixed32Type(FixedSizeTypeMixin, TypeInfo): o += "out.append(buffer);" return o - @property - def encode_content(self) -> str: - tag = self.calculate_tag() - if self.force and tag < 128: - # Emit combined tag+value write: precomputed tag + direct memcpy - return f"ProtoEncode::write_tag_and_fixed32(pos, {tag}, this->{self.field_name});" - if self.force: - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name}, true);" - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, this->{self.field_name});" + fixed32_value_template = "{value}" def get_size_calculation(self, name: str, force: bool = False) -> str: field_id_size = self.calculate_field_id_size() @@ -851,9 +873,12 @@ class StringType(TypeInfo): f"this->{self.field_name}_ref_.size()", ): return result - if self.force: - return f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name}_ref_, true);" - return f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name}_ref_);" + return _encode_call( + "encode_string", + str(self.number), + f"this->{self.field_name}_ref_", + force=self.force, + ) def dump(self, name): # If name is 'it', this is a repeated field element - always use string @@ -951,7 +976,9 @@ class MessageType(TypeInfo): @property def encode_content(self) -> str: # Sub-message encoding needs buffer for backpatch/sync - return f"ProtoEncode::{self.encode_func}(pos, buffer, {self.number}, this->{self.field_name});" + return _encode_call( + self.encode_func, "buffer", str(self.number), f"this->{self.field_name}" + ) @property def decode_length(self) -> str: @@ -1058,9 +1085,13 @@ class BytesType(TypeInfo): f"this->{self.field_name}_ptr_", f"this->{self.field_name}_len_" ): return result - if self.force: - return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_, true);" - return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);" + return _encode_call( + "encode_bytes", + str(self.number), + f"this->{self.field_name}_ptr_", + f"this->{self.field_name}_len_", + force=self.force, + ) def dump(self, name: str) -> str: ptr_dump = f"format_hex_pretty(this->{self.field_name}_ptr_, this->{self.field_name}_len_)" @@ -1170,9 +1201,13 @@ class PointerToBytesBufferType(PointerToBufferTypeBase): f"this->{self.field_name}", f"this->{self.field_name}_len" ): return result - if self.force: - return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" - return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len);" + return _encode_call( + "encode_bytes", + str(self.number), + f"this->{self.field_name}", + f"this->{self.field_name}_len", + force=self.force, + ) @property def decode_length_content(self) -> str | None: @@ -1224,16 +1259,19 @@ class PointerToStringBufferType(PointerToBufferTypeBase): if max_len is not None and max_len < 128 and self.force: tag = self.calculate_tag() if tag < 128: - return f"ProtoEncode::encode_short_string_force(pos, {tag}, this->{self.field_name});" + return _encode_call( + "encode_short_string_force", str(tag), f"this->{self.field_name}" + ) if result := self._encode_bytes_with_precomputed_tag( f"this->{self.field_name}.c_str()", f"this->{self.field_name}.size()", ): return result - if self.force: - return f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name}, true);" - return ( - f"ProtoEncode::encode_string(pos, {self.number}, this->{self.field_name});" + return _encode_call( + "encode_string", + str(self.number), + f"this->{self.field_name}", + force=self.force, ) @property @@ -1421,9 +1459,13 @@ class FixedArrayBytesType(TypeInfo): f"this->{self.field_name}", f"this->{self.field_name}_len", max_len=max_len ): return result - if self.force: - return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len, true);" - return f"ProtoEncode::encode_bytes(pos, {self.number}, this->{self.field_name}, this->{self.field_name}_len);" + return _encode_call( + "encode_bytes", + str(self.number), + f"this->{self.field_name}", + f"this->{self.field_name}_len", + force=self.force, + ) def dump(self, name: str) -> str: return f"out.append(format_hex_pretty({name}, {name}_len));" @@ -1520,9 +1562,9 @@ class EnumType(VarintTypeMixin, TypeInfo): @property def encode_content(self) -> str: value_expr = f"static_cast(this->{self.field_name})" - if self.force: - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, {value_expr}, true);" - return f"ProtoEncode::{self.encode_func}(pos, {self.number}, {value_expr});" + return _encode_call( + self.encode_func, str(self.number), value_expr, force=self.force + ) def dump(self, name: str) -> str: return f"out.append_p(proto_enum_to_string<{self.cpp_type}>({name}));" @@ -1701,9 +1743,9 @@ def _generate_inline_encode_block( lines = [] lines.append(f"auto &sub_msg = {element};") - lines.append(f"ProtoEncode::write_raw_byte(pos, {tag});") + lines.append(_encode_call("write_raw_byte", str(tag))) lines.append("uint8_t *len_pos = pos;") - lines.append("ProtoEncode::reserve_byte(pos);") + lines.append(_encode_call("reserve_byte")) # Generate inline field encoding for each sub-message field for field in sub_desc.field: @@ -1775,17 +1817,22 @@ class FixedArrayRepeatedType(TypeInfo): def _encode_element(self, element: str) -> str: """Helper to generate encode statement for a single element.""" if isinstance(self._ti, EnumType): - return f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, static_cast({element}), true);" + return _encode_call( + self._ti.encode_func, + str(self.number), + f"static_cast({element})", + force=True, + ) # Repeated message elements use encode_sub_message (force=true is default) if isinstance(self._ti, MessageType): if _is_inline_encode(self._ti.cpp_type): return _generate_inline_encode_block( self.number, self._ti.cpp_type, element ) - return f"ProtoEncode::encode_sub_message(pos, buffer, {self.number}, {element});" - return ( - f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, {element}, true);" - ) + return _encode_call( + "encode_sub_message", "buffer", str(self.number), element + ) + return _encode_call(self._ti.encode_func, str(self.number), element, force=True) @property def cpp_type(self) -> str: @@ -2137,13 +2184,18 @@ class RepeatedTypeInfo(TypeInfo): def _encode_element_call(self, element: str) -> str: """Helper to generate encode call for a single element.""" if isinstance(self._ti, EnumType): - return f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, static_cast({element}), true);" + return _encode_call( + self._ti.encode_func, + str(self.number), + f"static_cast({element})", + force=True, + ) # Repeated message elements use encode_sub_message (force=true is default) if isinstance(self._ti, MessageType): - return f"ProtoEncode::encode_sub_message(pos, buffer, {self.number}, {element});" - return ( - f"ProtoEncode::{self._ti.encode_func}(pos, {self.number}, {element}, true);" - ) + return _encode_call( + "encode_sub_message", "buffer", str(self.number), element + ) + return _encode_call(self._ti.encode_func, str(self.number), element, force=True) @property def encode_content(self) -> str: @@ -2152,7 +2204,7 @@ class RepeatedTypeInfo(TypeInfo): # Special handling for const char* elements (when container_no_template contains "const char") if "const char" in self._container_no_template: o = f"for (const char *it : *this->{self.field_name}) {{\n" - o += f" ProtoEncode::{self._ti.encode_func}(pos, {self.number}, it, strlen(it), true);\n" + o += f" {_encode_call(self._ti.encode_func, str(self.number), 'it', 'strlen(it)', force=True)}\n" else: o = f"for (const auto &it : *this->{self.field_name}) {{\n" o += f" {self._encode_element_call('it')}\n" diff --git a/tests/components/api/test_proto_mac_varint.cpp b/tests/components/api/test_proto_mac_varint.cpp index 9ea6ce1cd9..46af7cd836 100644 --- a/tests/components/api/test_proto_mac_varint.cpp +++ b/tests/components/api/test_proto_mac_varint.cpp @@ -59,7 +59,7 @@ static void verify_mac(uint64_t mac, size_t expected_bytes) { #ifdef ESPHOME_DEBUG_API uint8_t *proto_debug_end_ = api_buf.data() + api_buf.size(); #endif - ProtoEncode::encode_varint_raw_48bit(pos PROTO_ENCODE_DEBUG_ARG, mac); + pos = ProtoEncode::encode_varint_raw_48bit(pos PROTO_ENCODE_DEBUG_ARG, mac); size_t new_len = pos - api_buf.data(); EXPECT_EQ(new_len, expected_bytes) << "mac=0x" << std::hex << mac << std::dec; diff --git a/tests/integration/fixtures/api_encode_boundaries.yaml b/tests/integration/fixtures/api_encode_boundaries.yaml new file mode 100644 index 0000000000..e6842d2571 --- /dev/null +++ b/tests/integration/fixtures/api_encode_boundaries.yaml @@ -0,0 +1,58 @@ +esphome: + name: api-encode-boundaries-test + # Top-level area fills DeviceInfoResponse.suggested_area (field 16, a two-byte tag) + area: + id: kitchen_area + name: Kitchen + on_boot: + - sensor.template.publish: + id: zero_then_value + state: 0.0 + +host: +api: +logger: + level: DEBUG + +sensor: + - platform: template + name: "Zero Then Value" + id: zero_then_value + # Negative int32 takes the ten byte varint path + accuracy_decimals: -2 + update_interval: never + +text_sensor: + - platform: template + name: "Long Text" + id: long_text + update_interval: never + +number: + - platform: template + name: "Negative Number" + optimistic: true + min_value: -1000 + max_value: 1000 + step: 0.5 + initial_value: -123.5 + +select: + - platform: template + name: "Long Option Select" + optimistic: true + options: + - short + - "option-with-a-name-long-enough-that-its-length-prefix-needs-two-varint-bytes-when-the-list-entities-response-is-encoded-xxxxxxxxxx" + initial_option: short + +button: + - platform: template + name: "Publish Values" + on_press: + - sensor.template.publish: + id: zero_then_value + state: 12.5 + - text_sensor.template.publish: + id: long_text + state: !lambda return std::string(200, 'y'); diff --git a/tests/integration/state_utils.py b/tests/integration/state_utils.py index 9c0debbc5c..8b8e30c8df 100644 --- a/tests/integration/state_utils.py +++ b/tests/integration/state_utils.py @@ -3,7 +3,7 @@ from __future__ import annotations import asyncio -from collections.abc import Callable +from collections.abc import Awaitable, Callable import logging from typing import TypeVar @@ -57,6 +57,58 @@ async def wait_for_state( return await asyncio.wait_for(future, timeout=timeout) +class StateWaiter: + """Route one state subscription to any number of predicate waits.""" + + def __init__(self) -> None: + self._waiters: list[ + tuple[Callable[[EntityState], bool], asyncio.Future[EntityState]] + ] = [] + + def on_state(self, state: EntityState) -> None: + for predicate, future in self._waiters: + if future.done(): + continue + try: + matched = predicate(state) + except Exception as exc: # noqa: BLE001 the wait re-raises it, the callback must not die + future.set_exception(exc) + continue + if matched: + future.set_result(state) + + def expect( + self, + predicate: Callable[[EntityState], bool], + timeout: float = 5.0, + label: str | None = None, + ) -> Awaitable[EntityState]: + """Arm a wait for the next state matching ``predicate`` and return the awaitable for it. + + The wait is armed here, at call time, so it can be created before the action that produces + the state and awaited afterwards; states seen before this call never match. + """ + entry = (predicate, asyncio.get_running_loop().create_future()) + self._waiters.append(entry) + return self._wait(entry, timeout, label) + + async def _wait( + self, + entry: tuple[Callable[[EntityState], bool], asyncio.Future[EntityState]], + timeout: float, + label: str | None, + ) -> EntityState: + try: + async with asyncio.timeout(timeout): + return await entry[1] + except TimeoutError: + raise TimeoutError( + f"no state matched {label or entry[0]} within {timeout}s" + ) from None + finally: + self._waiters.remove(entry) + + def find_entity[T: EntityInfo]( entities: list[EntityInfo], object_id_substring: str, diff --git a/tests/integration/test_api_encode_boundaries.py b/tests/integration/test_api_encode_boundaries.py new file mode 100644 index 0000000000..765dccbf4e --- /dev/null +++ b/tests/integration/test_api_encode_boundaries.py @@ -0,0 +1,76 @@ +"""Encode paths at their branch boundaries: zero skipped float, fixed32 state, negative int32, +length prefixes of two varint bytes and two byte field tags.""" + +from __future__ import annotations + +import asyncio + +from aioesphomeapi import ( + NumberState, + SelectInfo, + SensorInfo, + SensorState, + TextSensorState, +) +import pytest + +from .state_utils import InitialStateHelper, StateWaiter, require_entity +from .types import APIClientConnectedFactory, RunCompiledFunction + +LONG_OPTION = ( + "option-with-a-name-long-enough-that-its-length-prefix-needs-two-varint-bytes-" + "when-the-list-entities-response-is-encoded-xxxxxxxxxx" +) + + +@pytest.mark.asyncio +async def test_api_encode_boundaries( + yaml_config: str, + run_compiled: RunCompiledFunction, + api_client_connected: APIClientConnectedFactory, +) -> None: + async with run_compiled(yaml_config), api_client_connected() as client: + device_info, (entities, _) = await asyncio.gather( + client.device_info(), client.list_entities_services() + ) + assert device_info.suggested_area == "Kitchen" + + sensor = require_entity(entities, "zero_then_value", SensorInfo) + assert sensor.accuracy_decimals == -2 + select = require_entity(entities, "long_option_select", SelectInfo) + assert len(LONG_OPTION) >= 128 + assert select.options == ["short", LONG_OPTION] + text = require_entity(entities, "long_text") + number = require_entity(entities, "negative_number") + button = require_entity(entities, "publish_values") + + initial = InitialStateHelper(entities) + waiter = StateWaiter() + client.subscribe_states(initial.on_state_wrapper(waiter.on_state)) + await initial.wait_for_initial_states() + + # A float of exactly zero is skipped on the wire and must still read as 0.0, not missing + first = initial.initial_states[sensor.key] + assert isinstance(first, SensorState) + assert first.state == 0.0 and not first.missing_state + first_number = initial.initial_states[number.key] + assert isinstance(first_number, NumberState) + assert first_number.state == -123.5 + + # Arm both waits before the press so no ordering of the replies can slip past them + sensor_seen = waiter.expect( + lambda s: ( + isinstance(s, SensorState) and s.key == sensor.key and s.state == 12.5 + ), + label="sensor 12.5", + ) + text_seen = waiter.expect( + lambda s: ( + isinstance(s, TextSensorState) + and s.key == text.key + and s.state == "y" * 200 + ), + label="text 200 x y", + ) + client.button_command(button.key) + await asyncio.gather(sensor_seen, text_seen) diff --git a/tests/unit_tests/components/api/test_api_proto.py b/tests/unit_tests/components/api/test_api_proto.py index 31297911f5..a194511f2b 100644 --- a/tests/unit_tests/components/api/test_api_proto.py +++ b/tests/unit_tests/components/api/test_api_proto.py @@ -380,3 +380,13 @@ def test_api_version_minor_is_at_least_15() -> None: "clients to see api_version >= 1.15 in HelloResponse before they will " "ever request it." ) + + +def test_generated_encode_calls_keep_the_cursor() -> None: + """No generated ProtoEncode call may drop the returned cursor.""" + dropped = [ + line + for line in CPP_TEXT.splitlines() + if "ProtoEncode::" in line and "pos = ProtoEncode::" not in line + ] + assert not dropped, dropped[:5] diff --git a/tests/unit_tests/components/api/test_api_protobuf_generator.py b/tests/unit_tests/components/api/test_api_protobuf_generator.py index 797125ba8f..c182520c5a 100644 --- a/tests/unit_tests/components/api/test_api_protobuf_generator.py +++ b/tests/unit_tests/components/api/test_api_protobuf_generator.py @@ -15,9 +15,11 @@ import pytest sys.path.insert(0, str(Path(__file__).parents[4] / "script" / "api_protobuf")) +import aioesphomeapi.api_options_pb2 as pb # noqa: E402 from api_protobuf import ( # noqa: E402 MAX_MESSAGE_ID, _make_ifdef_line, + create_field_type_info, get_varint64_ifdef, validate_message_id, ) @@ -43,7 +45,14 @@ UINT64 = descriptor_pb2.FieldDescriptorProto.TYPE_UINT64 INT64 = descriptor_pb2.FieldDescriptorProto.TYPE_INT64 SINT64 = descriptor_pb2.FieldDescriptorProto.TYPE_SINT64 UINT32 = descriptor_pb2.FieldDescriptorProto.TYPE_UINT32 +INT32 = descriptor_pb2.FieldDescriptorProto.TYPE_INT32 +SINT32 = descriptor_pb2.FieldDescriptorProto.TYPE_SINT32 FIXED64 = descriptor_pb2.FieldDescriptorProto.TYPE_FIXED64 +FIXED32 = descriptor_pb2.FieldDescriptorProto.TYPE_FIXED32 +FLOAT = descriptor_pb2.FieldDescriptorProto.TYPE_FLOAT +BOOL = descriptor_pb2.FieldDescriptorProto.TYPE_BOOL +STRING = descriptor_pb2.FieldDescriptorProto.TYPE_STRING +BYTES = descriptor_pb2.FieldDescriptorProto.TYPE_BYTES def test_no_varint64_fields() -> None: @@ -107,3 +116,69 @@ def test_message_id_at_maximum_is_accepted() -> None: def test_message_id_above_maximum_is_rejected() -> None: with pytest.raises(ValueError, match="exceeds the plaintext"): validate_message_id(MAX_MESSAGE_ID + 1, "TooBigMessage") + + +def _field( + field_type: int, number: int = 1, *, force: bool = False, repeated: bool = False +) -> descriptor_pb2.FieldDescriptorProto: + field = descriptor_pb2.FieldDescriptorProto( + name="value", number=number, type=field_type + ) + if repeated: + field.label = descriptor_pb2.FieldDescriptorProto.LABEL_REPEATED + if force: + field.options.Extensions[pb.force] = True + return field + + +def _encode_field( + field_type: int, number: int = 1, force: bool = False, repeated: bool = False +) -> str: + """Return the encode statement the generator emits for one encode-only field.""" + field = _field(field_type, number, force=force, repeated=repeated) + return create_field_type_info( + field, needs_decode=False, needs_encode=True + ).encode_content + + +SCALAR_TYPES = [ + BOOL, + UINT32, + INT32, + UINT64, + INT64, + SINT32, + FLOAT, + FIXED32, + STRING, + BYTES, +] + + +@pytest.mark.parametrize("field_type", SCALAR_TYPES) +def test_forced_fields_use_the_force_overload_or_raw_writes(field_type: int) -> None: + content = _encode_field(field_type, force=True) + assert ( + "_force(" in content + or "write_raw_byte(" in content + or "write_tag_and_fixed32(" in content + ), content + + +@pytest.mark.parametrize("field_type", [FLOAT, FIXED32]) +def test_single_byte_tag_fixed32_shares_the_outlined_writer(field_type: int) -> None: + unconditional = _encode_field(field_type, force=True) + assert unconditional.count("write_tag_and_fixed32(pos, 13,") == 1, unconditional + guarded = _encode_field(field_type, force=False) + assert guarded.startswith("if ("), guarded + assert "[[likely]]" in guarded + assert "write_tag_and_fixed32(pos, 13," in guarded + + +@pytest.mark.parametrize("field_type", [FLOAT, FIXED32]) +def test_multi_byte_tag_fixed32_falls_back_to_the_generic_helper( + field_type: int, +) -> None: + content = _encode_field(field_type, number=16) + assert "write_tag_and_fixed32" not in content, content + assert content.startswith("pos = ProtoEncode::encode_"), content