From a19a6f2a0e1c11fe4f45473d380cf10db1078a20 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 29 Mar 2026 14:26:50 -1000 Subject: [PATCH] [api] Return header length from write_plaintext_header instead of pointer Returning total_header_len lets callers compute msg_len directly (header_len + payload_size) instead of reloading frame_header_padding_ from memory and doing pointer subtraction after encode_varint calls clobber registers. Saves ~10 bytes in write_protobuf_packet. --- .../api/api_frame_helper_plaintext.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/esphome/components/api/api_frame_helper_plaintext.cpp b/esphome/components/api/api_frame_helper_plaintext.cpp index ee0661c998c..53ee58590de 100644 --- a/esphome/components/api/api_frame_helper_plaintext.cpp +++ b/esphome/components/api/api_frame_helper_plaintext.cpp @@ -235,9 +235,9 @@ APIError APIPlaintextFrameHelper::read_packet(ReadPacketBuffer *buffer) { return APIError::OK; } // Write plaintext header into pre-allocated padding before payload. -// Returns pointer to start of frame (header + payload are contiguous). -ESPHOME_ALWAYS_INLINE static inline uint8_t *write_plaintext_header(uint8_t *buf_start, const MessageInfo &msg, - uint8_t frame_header_padding) { +// Returns the total header length (indicator + varints). +ESPHOME_ALWAYS_INLINE static inline uint8_t write_plaintext_header(uint8_t *buf_start, const MessageInfo &msg, + uint8_t frame_header_padding) { // Calculate varint sizes for header layout using inline ternary to avoid varint_slow call overhead uint8_t size_varint_len = msg.payload_size < ProtoSize::VARINT_THRESHOLD_1_BYTE ? 1 @@ -279,7 +279,7 @@ ESPHOME_ALWAYS_INLINE static inline uint8_t *write_plaintext_header(uint8_t *buf encode_varint_to_buffer(msg.payload_size, buf_start + header_offset + 1); encode_varint_to_buffer(msg.message_type, buf_start + header_offset + 1 + size_varint_len); - return buf_start + header_offset; + return total_header_len; } APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWriteBuffer buffer) { @@ -289,9 +289,9 @@ APIError APIPlaintextFrameHelper::write_protobuf_packet(uint8_t type, ProtoWrite MessageInfo msg{type, 0, static_cast(buffer.get_buffer()->size() - frame_header_padding_)}; uint8_t *buffer_data = buffer.get_buffer()->data(); - uint8_t *msg_start = write_plaintext_header(buffer_data, msg, frame_header_padding_); - uint8_t msg_header_len = static_cast(buffer_data + frame_header_padding_ - msg_start); - uint16_t msg_len = static_cast(msg_header_len + msg.payload_size); + uint8_t header_len = write_plaintext_header(buffer_data, msg, frame_header_padding_); + uint8_t *msg_start = buffer_data + frame_header_padding_ - header_len; + uint16_t msg_len = static_cast(header_len + msg.payload_size); LOG_PACKET_SENDING(msg_start, msg_len); return this->write_raw_fast_buf_(msg_start, msg_len); } @@ -309,9 +309,9 @@ APIError APIPlaintextFrameHelper::write_protobuf_messages(ProtoWriteBuffer buffe const uint8_t padding = frame_header_padding_; for (const auto &msg : messages) { - uint8_t *msg_start = write_plaintext_header(buffer_data + msg.offset, msg, padding); - uint8_t msg_header_len = static_cast((buffer_data + msg.offset + padding) - msg_start); - size_t msg_len = static_cast(msg_header_len + msg.payload_size); + uint8_t header_len = write_plaintext_header(buffer_data + msg.offset, msg, padding); + uint8_t *msg_start = buffer_data + msg.offset + padding - header_len; + size_t msg_len = static_cast(header_len + msg.payload_size); iovs.push_back({msg_start, msg_len}); total_write_len += msg_len; }