From a5780eec54ddcfa48d0f34439135bb7dfd08d278 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 7 Mar 2026 15:41:01 -1000 Subject: [PATCH] Extract varint_wide helper to deduplicate cascade The constexpr path and the noinline slow path shared the same if/else cascade for values >= 128. Extract into a private constexpr ESPHOME_ALWAYS_INLINE helper used by both. Co-Authored-By: Claude Opus 4.6 --- esphome/components/api/proto.cpp | 13 +------------ esphome/components/api/proto.h | 25 +++++++++++++++---------- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/esphome/components/api/proto.cpp b/esphome/components/api/proto.cpp index 4f16815d1b..2f51c5c2a6 100644 --- a/esphome/components/api/proto.cpp +++ b/esphome/components/api/proto.cpp @@ -8,18 +8,7 @@ namespace esphome::api { static const char *const TAG = "api.proto"; -uint32_t ProtoSize::varint_slow(uint32_t value) { - // value is guaranteed >= 128 here (fast path handled inline) - if (value < 16384) { - return 2; // 14 bits - } else if (value < 2097152) { - return 3; // 21 bits - } else if (value < 268435456) { - return 4; // 28 bits - } else { - return 5; // 32 bits (maximum for uint32_t) - } -} +uint32_t ProtoSize::varint_slow(uint32_t value) { return varint_wide(value); } #ifdef USE_API_VARINT64 optional ProtoVarInt::parse_wide(const uint8_t *buffer, uint32_t len, uint32_t *consumed, diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index ec49964035..10581a7f0a 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -514,21 +514,26 @@ class ProtoSize { static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint(uint32_t value) { if (value < 128) return 1; // Fast path: 7 bits, most common case - if (__builtin_is_constant_evaluated()) { - // Compile-time: full cascade for constexpr callers - if (value < 16384) - return 2; - if (value < 2097152) - return 3; - if (value < 268435456) - return 4; - return 5; - } + if (__builtin_is_constant_evaluated()) + return varint_wide(value); return varint_slow(value); } // Slow path for varint >= 128, outlined to keep fast path small static uint32_t varint_slow(uint32_t value) __attribute__((noinline)); + private: + // Shared cascade for values >= 128 (used by both constexpr and noinline paths) + static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint_wide(uint32_t value) { + if (value < 16384) + return 2; + if (value < 2097152) + return 3; + if (value < 268435456) + return 4; + return 5; + } + + public: /** * @brief Calculates the size in bytes needed to encode a uint64_t value as a varint *