mirror of
https://github.com/esphome/esphome.git
synced 2026-09-11 15:27:33 +00:00
[api] Share the fixed32 emission between float and fixed32 fields
One helper next to the other precomputed tag paths decides how a single byte tag fixed32 field is written; the float and fixed32 types only differ in the value expression. Drop the non forced std::string encode_string overload, which the generator never emits, and build the generator tests from one block of field type constants.
This commit is contained in:
@@ -3838,8 +3838,8 @@ uint8_t *DateTimeStateResponse::encode(ProtoWriteBuffer &buffer PROTO_ENCODE_DEB
|
||||
uint8_t *__restrict__ pos = buffer.get_pos();
|
||||
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 (this->epoch_seconds != 0) [[likely]] {
|
||||
pos = ProtoEncode::write_tag_and_fixed32(pos PROTO_ENCODE_DEBUG_ARG, 29, this->epoch_seconds);
|
||||
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
|
||||
pos = ProtoEncode::encode_uint32(pos PROTO_ENCODE_DEBUG_ARG, 4, this->device_id);
|
||||
|
||||
@@ -457,10 +457,6 @@ class ProtoEncode {
|
||||
return pos;
|
||||
return encode_string_force(pos PROTO_ENCODE_DEBUG_ARG, field_id, string, len);
|
||||
}
|
||||
static inline uint8_t *encode_string(uint8_t *__restrict__ pos PROTO_ENCODE_DEBUG_PARAM, uint32_t field_id,
|
||||
const std::string &value) {
|
||||
return encode_string(pos PROTO_ENCODE_DEBUG_ARG, field_id, value.data(), value.size());
|
||||
}
|
||||
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());
|
||||
|
||||
@@ -324,6 +324,24 @@ class TypeInfo(ABC):
|
||||
f"pos = ProtoEncode::encode_raw(pos, {data_expr}, {len_expr});"
|
||||
)
|
||||
|
||||
def _encode_fixed32_with_precomputed_tag(self, value_expr: str) -> str | None:
|
||||
"""Emit a fixed32 field through the shared tag+value writer when the tag is one byte.
|
||||
|
||||
Returns None for multi-byte tags, which go through the generic helper.
|
||||
"""
|
||||
tag = self.calculate_tag()
|
||||
if tag >= 128:
|
||||
return None
|
||||
if self.force:
|
||||
return (
|
||||
f"pos = ProtoEncode::write_tag_and_fixed32(pos, {tag}, {value_expr});"
|
||||
)
|
||||
return (
|
||||
f"if (uint32_t raw = {value_expr}; raw != 0) [[likely]] {{\n"
|
||||
f" pos = ProtoEncode::write_tag_and_fixed32(pos, {tag}, raw);\n"
|
||||
"}"
|
||||
)
|
||||
|
||||
@property
|
||||
def encode_content(self) -> str:
|
||||
if result := self._encode_with_precomputed_tag(f"this->{self.field_name}"):
|
||||
@@ -637,18 +655,11 @@ class FloatType(FixedSizeTypeMixin, TypeInfo):
|
||||
|
||||
@property
|
||||
def encode_content(self) -> str:
|
||||
tag = self.calculate_tag()
|
||||
if tag >= 128:
|
||||
return super().encode_content
|
||||
# Single-byte tag: share the outlined tag+fixed32 writer instead of the generic helper
|
||||
value = f"float_to_raw(this->{self.field_name})"
|
||||
if self.force:
|
||||
return f"pos = ProtoEncode::write_tag_and_fixed32(pos, {tag}, {value});"
|
||||
return (
|
||||
f"if (uint32_t raw = {value}; raw != 0) [[likely]] {{\n"
|
||||
f" pos = ProtoEncode::write_tag_and_fixed32(pos, {tag}, raw);\n"
|
||||
"}"
|
||||
)
|
||||
if result := self._encode_fixed32_with_precomputed_tag(
|
||||
f"float_to_raw(this->{self.field_name})"
|
||||
):
|
||||
return result
|
||||
return super().encode_content
|
||||
|
||||
def dump(self, name: str) -> str:
|
||||
o = f'snprintf(buffer, sizeof(buffer), "%g", {name});\n'
|
||||
@@ -786,17 +797,11 @@ class Fixed32Type(FixedSizeTypeMixin, TypeInfo):
|
||||
|
||||
@property
|
||||
def encode_content(self) -> str:
|
||||
tag = self.calculate_tag()
|
||||
if tag >= 128:
|
||||
return super().encode_content
|
||||
# Single-byte tag: share the outlined tag+fixed32 writer instead of the generic helper
|
||||
if self.force:
|
||||
return f"pos = ProtoEncode::write_tag_and_fixed32(pos, {tag}, this->{self.field_name});"
|
||||
return (
|
||||
f"if (this->{self.field_name} != 0) [[likely]] {{\n"
|
||||
f" pos = ProtoEncode::write_tag_and_fixed32(pos, {tag}, this->{self.field_name});\n"
|
||||
"}"
|
||||
)
|
||||
if result := self._encode_fixed32_with_precomputed_tag(
|
||||
f"this->{self.field_name}"
|
||||
):
|
||||
return result
|
||||
return super().encode_content
|
||||
|
||||
def get_size_calculation(self, name: str, force: bool = False) -> str:
|
||||
field_id_size = self.calculate_field_id_size()
|
||||
|
||||
@@ -45,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:
|
||||
@@ -127,16 +134,16 @@ def _encode_field(
|
||||
|
||||
|
||||
SCALAR_TYPES = [
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_BOOL,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_UINT32,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_INT32,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_UINT64,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_INT64,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_SINT32,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_FLOAT,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_FIXED32,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_STRING,
|
||||
descriptor_pb2.FieldDescriptorProto.TYPE_BYTES,
|
||||
BOOL,
|
||||
UINT32,
|
||||
INT32,
|
||||
UINT64,
|
||||
INT64,
|
||||
SINT32,
|
||||
FLOAT,
|
||||
FIXED32,
|
||||
STRING,
|
||||
BYTES,
|
||||
]
|
||||
|
||||
|
||||
@@ -165,10 +172,6 @@ def test_forced_fields_use_the_force_overload_or_raw_writes(field_type: int) ->
|
||||
), content
|
||||
|
||||
|
||||
FLOAT = descriptor_pb2.FieldDescriptorProto.TYPE_FLOAT
|
||||
FIXED32 = descriptor_pb2.FieldDescriptorProto.TYPE_FIXED32
|
||||
|
||||
|
||||
@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)
|
||||
|
||||
Reference in New Issue
Block a user