[api] Address Copilot review on proxy benchmarks PR

- Make UARTFlushResult in the serial_proxy stub a scoped enum class with
  matching scoped enumerator return in flush_port(), so the stub
  signature lines up with the real esphome::uart::UARTFlushResult.
- Replace heap-leaking lazy-init in get_ir_timings_100() with a
  function-local static const std::vector populated by a regular helper
  function. Same lazy-init behavior, no leak in valgrind/ASan, no lambda
  IIFE.
- Emit field 6 (modulation = 1) in build_infrared_rf_transmit_wire() so
  the bytes match the documented field list and the decode benchmark
  also exercises the field-6 decode_varint path.
This commit is contained in:
J. Nick Koston
2026-04-29 22:40:45 -05:00
parent a0532d657f
commit 8c0e5e9d9a
2 changed files with 18 additions and 13 deletions
@@ -151,18 +151,19 @@ BENCHMARK(Decode_SerialProxyWriteRequest);
#if defined(USE_IR_RF) || defined(USE_RADIO_FREQUENCY) #if defined(USE_IR_RF) || defined(USE_RADIO_FREQUENCY)
// Heap-allocated on first use to avoid C++17 lambda IIFE patterns that some // Mark/space pairs simulating a typical RC-5 / NEC capture (100 timings).
// callgrind/valgrind versions handle awkwardly during benchmark init. static std::vector<int32_t> make_ir_timings_100() {
static const std::vector<int32_t> &get_ir_timings_100() { std::vector<int32_t> v;
static std::vector<int32_t> *timings = nullptr; v.reserve(100);
if (timings == nullptr) { for (int i = 0; i < 100; i++) {
timings = new std::vector<int32_t>(); v.push_back((i % 2 == 0) ? 560 : -560);
timings->reserve(100);
for (int i = 0; i < 100; i++) {
timings->push_back((i % 2 == 0) ? 560 : -560);
}
} }
return *timings; return v;
}
static const std::vector<int32_t> &get_ir_timings_100() {
static const std::vector<int32_t> timings = make_ir_timings_100();
return timings;
} }
static void Encode_InfraredRFReceiveEvent(benchmark::State &state) { static void Encode_InfraredRFReceiveEvent(benchmark::State &state) {
@@ -247,6 +248,10 @@ static APIBuffer build_infrared_rf_transmit_wire() {
put_varint(static_cast<uint32_t>(packed_len)); put_varint(static_cast<uint32_t>(packed_len));
std::memcpy(bytes + len, packed, packed_len); std::memcpy(bytes + len, packed, packed_len);
len += packed_len; len += packed_len;
// field 6: modulation = 1 (non-zero so it's actually emitted and exercises
// decode_varint for this field, matching the documented layout above).
put_byte(0x30);
put_varint(1);
APIBuffer buf; APIBuffer buf;
buf.resize(len); buf.resize(len);
@@ -14,7 +14,7 @@ class APIConnection;
} // namespace api } // namespace api
namespace uart { namespace uart {
enum UARTFlushResult : uint8_t { enum class UARTFlushResult : uint8_t {
UART_FLUSH_RESULT_SUCCESS, UART_FLUSH_RESULT_SUCCESS,
UART_FLUSH_RESULT_ASSUMED_SUCCESS, UART_FLUSH_RESULT_ASSUMED_SUCCESS,
UART_FLUSH_RESULT_TIMEOUT, UART_FLUSH_RESULT_TIMEOUT,
@@ -36,7 +36,7 @@ class SerialProxy {
void write_from_client(const uint8_t *data, size_t len) {} void write_from_client(const uint8_t *data, size_t len) {}
void set_modem_pins(uint32_t line_states) {} void set_modem_pins(uint32_t line_states) {}
uint32_t get_modem_pins() const { return 0; } uint32_t get_modem_pins() const { return 0; }
uart::UARTFlushResult flush_port() { return uart::UART_FLUSH_RESULT_SUCCESS; } uart::UARTFlushResult flush_port() { return uart::UARTFlushResult::UART_FLUSH_RESULT_SUCCESS; }
protected: protected:
uint32_t instance_index_{0}; uint32_t instance_index_{0};