diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 4cbc8f46c2..7e01185849 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -21,8 +21,6 @@ void ProtoWriteBuffer::encode_varint_raw_slow_(uint32_t value) { } ProtoVarIntResult ProtoVarInt::parse_slow(const uint8_t *buffer, uint32_t len) { - if (len == 0) - return {0, 0}; // Multi-byte varint: first byte already checked to have high bit set uint32_t result32 = buffer[0] & 0x7F; #ifdef USE_API_VARINT64 diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index 55054ed157..ebb0ecdd79 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -130,13 +130,15 @@ class ProtoVarInt { ProtoVarInt() : value_(0) {} explicit ProtoVarInt(uint64_t value) : value_(value) {} - /// Parse a varint from buffer. Returns result with consumed=0 on failure. + /// Parse a varint from buffer. Caller must ensure len >= 1. + /// Returns result with consumed=0 on failure (truncated multi-byte varint). static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse(const uint8_t *buffer, uint32_t len) { +#ifdef ESPHOME_DEBUG_API + assert(len > 0); // All callers guarantee len > 0 +#endif // Fast path: single-byte varints (0-127) are the most common case // (booleans, small enums, field tags, small message sizes/types). - // len==0 check is folded into the condition to minimize inline size; - // parse_slow() handles len==0. - if (len != 0 && (buffer[0] & 0x80) == 0) [[likely]] + if ((buffer[0] & 0x80) == 0) [[likely]] return {buffer[0], 1}; return parse_slow(buffer, len); }