diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 4c6d2fc495..7c472fb5d4 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -220,10 +220,6 @@ class ProtoWriteBuffer { ProtoWriteBuffer(std::vector *buffer) : buffer_(buffer), pos_(buffer->data() + buffer->size()) {} ProtoWriteBuffer(std::vector *buffer, size_t write_pos) : buffer_(buffer), pos_(buffer->data() + write_pos) {} - void write(uint8_t value) { - this->debug_check_bounds_(1); - *this->pos_++ = value; - } void encode_varint_raw(uint32_t value) { while (value > 0x7F) { this->debug_check_bounds_(1); @@ -254,10 +250,7 @@ class ProtoWriteBuffer { * * Following https://protobuf.dev/programming-guides/encoding/#structure */ - void encode_field_raw(uint32_t field_id, uint32_t type) { - uint32_t val = (field_id << 3) | (type & WIRE_TYPE_MASK); - this->encode_varint_raw(val); - } + void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); } void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) { if (len == 0 && !force) return; @@ -303,10 +296,17 @@ class ProtoWriteBuffer { return; this->encode_field_raw(field_id, 5); // type 5: 32-bit fixed32 - this->write((value >> 0) & 0xFF); - this->write((value >> 8) & 0xFF); - this->write((value >> 16) & 0xFF); - this->write((value >> 24) & 0xFF); + this->debug_check_bounds_(4); +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + // Protobuf fixed32 is little-endian, so direct copy works + std::memcpy(this->pos_, &value, 4); + this->pos_ += 4; +#else + *this->pos_++ = (value >> 0) & 0xFF; + *this->pos_++ = (value >> 8) & 0xFF; + *this->pos_++ = (value >> 16) & 0xFF; + *this->pos_++ = (value >> 24) & 0xFF; +#endif } // NOTE: Wire type 1 (64-bit fixed: double, fixed64, sfixed64) is intentionally // not supported to reduce overhead on embedded systems. All ESPHome devices are @@ -936,6 +936,7 @@ inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessa // The copy writes msg_length_bytes bytes starting from our current pos_. // We then advance our pos_ by the known message size. value.encode(*this); + this->debug_check_bounds_(msg_length_bytes); this->pos_ += msg_length_bytes; }