mirror of
https://github.com/esphome/esphome.git
synced 2026-06-01 01:19:45 +08:00
[api] Emit raw tag+value writes for forced fixed32 key fields (#15051)
This commit is contained in:
File diff suppressed because it is too large
Load Diff
+100
-100
File diff suppressed because it is too large
Load Diff
@@ -236,6 +236,21 @@ class ProtoWriteBuffer {
|
|||||||
* Following https://protobuf.dev/programming-guides/encoding/#structure
|
* Following https://protobuf.dev/programming-guides/encoding/#structure
|
||||||
*/
|
*/
|
||||||
void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); }
|
void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); }
|
||||||
|
/// Write a precomputed tag byte + 32-bit value in one operation.
|
||||||
|
/// Tag must be a single-byte varint (< 128). No zero check.
|
||||||
|
inline void write_tag_and_fixed32(uint8_t tag, uint32_t value) ESPHOME_ALWAYS_INLINE {
|
||||||
|
this->debug_check_bounds_(5);
|
||||||
|
this->pos_[0] = tag;
|
||||||
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||||
|
std::memcpy(this->pos_ + 1, &value, 4);
|
||||||
|
#else
|
||||||
|
this->pos_[1] = static_cast<uint8_t>(value & 0xFF);
|
||||||
|
this->pos_[2] = static_cast<uint8_t>((value >> 8) & 0xFF);
|
||||||
|
this->pos_[3] = static_cast<uint8_t>((value >> 16) & 0xFF);
|
||||||
|
this->pos_[4] = static_cast<uint8_t>((value >> 24) & 0xFF);
|
||||||
|
#endif
|
||||||
|
this->pos_ += 5;
|
||||||
|
}
|
||||||
void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) {
|
void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) {
|
||||||
if (len == 0 && !force)
|
if (len == 0 && !force)
|
||||||
return;
|
return;
|
||||||
@@ -276,8 +291,7 @@ class ProtoWriteBuffer {
|
|||||||
this->debug_check_bounds_(1);
|
this->debug_check_bounds_(1);
|
||||||
*this->pos_++ = value ? 0x01 : 0x00;
|
*this->pos_++ = value ? 0x01 : 0x00;
|
||||||
}
|
}
|
||||||
// noinline: 51 call sites; inlining causes net code growth vs a single out-of-line copy
|
void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) {
|
||||||
__attribute__((noinline)) void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) {
|
|
||||||
if (value == 0 && !force)
|
if (value == 0 && !force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|||||||
@@ -254,14 +254,17 @@ class TypeInfo(ABC):
|
|||||||
def dump(self, name: str) -> str:
|
def dump(self, name: str) -> str:
|
||||||
"""Dump the value to the output."""
|
"""Dump the value to the output."""
|
||||||
|
|
||||||
|
def calculate_tag(self) -> int:
|
||||||
|
"""Calculate the protobuf tag (field_id << 3 | wire_type)."""
|
||||||
|
return (self.number << 3) | (self.wire_type & 0b111)
|
||||||
|
|
||||||
def calculate_field_id_size(self) -> int:
|
def calculate_field_id_size(self) -> int:
|
||||||
"""Calculates the size of a field ID in bytes.
|
"""Calculates the size of a field ID in bytes.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The number of bytes needed to encode the field ID
|
The number of bytes needed to encode the field ID
|
||||||
"""
|
"""
|
||||||
# Calculate the tag by combining field_id and wire_type
|
tag = self.calculate_tag()
|
||||||
tag = (self.number << 3) | (self.wire_type & 0b111)
|
|
||||||
|
|
||||||
# Calculate the varint size
|
# Calculate the varint size
|
||||||
if tag < 128:
|
if tag < 128:
|
||||||
@@ -556,6 +559,16 @@ class Fixed32Type(TypeInfo):
|
|||||||
o += "out.append(buffer);"
|
o += "out.append(buffer);"
|
||||||
return o
|
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"buffer.write_tag_and_fixed32({tag}, this->{self.field_name});"
|
||||||
|
if self.force:
|
||||||
|
return f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, true);"
|
||||||
|
return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});"
|
||||||
|
|
||||||
def get_size_calculation(self, name: str, force: bool = False) -> str:
|
def get_size_calculation(self, name: str, force: bool = False) -> str:
|
||||||
field_id_size = self.calculate_field_id_size()
|
field_id_size = self.calculate_field_id_size()
|
||||||
if force:
|
if force:
|
||||||
|
|||||||
Reference in New Issue
Block a user