ESPHome 2026.3.0
Loading...
Searching...
No Matches
proto.h
Go to the documentation of this file.
1#pragma once
2
3#include "api_pb2_defines.h"
4#include "api_buffer.h"
7#include "esphome/core/log.h"
9
10#include <cassert>
11#include <cstring>
12#include <vector>
13
14#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
15#define HAS_PROTO_MESSAGE_DUMP
16#endif
17
18namespace esphome::api {
19
20// Protocol Buffer wire type constants
21// See https://protobuf.dev/programming-guides/encoding/#structure
22constexpr uint8_t WIRE_TYPE_VARINT = 0; // int32, int64, uint32, uint64, sint32, sint64, bool, enum
23constexpr uint8_t WIRE_TYPE_LENGTH_DELIMITED = 2; // string, bytes, embedded messages, packed repeated fields
24constexpr uint8_t WIRE_TYPE_FIXED32 = 5; // fixed32, sfixed32, float
25constexpr uint8_t WIRE_TYPE_MASK = 0b111; // Mask to extract wire type from tag
26
27// Helper functions for ZigZag encoding/decoding
28inline constexpr uint32_t encode_zigzag32(int32_t value) {
29 return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31));
30}
31
32inline constexpr uint64_t encode_zigzag64(int64_t value) {
33 return (static_cast<uint64_t>(value) << 1) ^ (static_cast<uint64_t>(value >> 63));
34}
35
36inline constexpr int32_t decode_zigzag32(uint32_t value) {
37 return (value & 1) ? static_cast<int32_t>(~(value >> 1)) : static_cast<int32_t>(value >> 1);
38}
39
40inline constexpr int64_t decode_zigzag64(uint64_t value) {
41 return (value & 1) ? static_cast<int64_t>(~(value >> 1)) : static_cast<int64_t>(value >> 1);
42}
43
45inline uint16_t count_packed_varints(const uint8_t *data, size_t len) {
46 uint16_t count = 0;
47 while (len > 0) {
48 // Skip varint bytes until we find one without continuation bit
49 while (len > 0 && (*data & 0x80)) {
50 data++;
51 len--;
52 }
53 if (len > 0) {
54 data++;
55 len--;
56 count++;
57 }
58 }
59 return count;
60}
61
64inline void encode_varint_to_buffer(uint32_t val, uint8_t *buffer) {
65 while (val > 0x7F) {
66 *buffer++ = static_cast<uint8_t>(val | 0x80);
67 val >>= 7;
68 }
69 *buffer = static_cast<uint8_t>(val);
70}
71
72/*
73 * StringRef Ownership Model for API Protocol Messages
74 * ===================================================
75 *
76 * StringRef is used for zero-copy string handling in outgoing (SOURCE_SERVER) messages.
77 * It holds a pointer and length to existing string data without copying.
78 *
79 * CRITICAL: The referenced string data MUST remain valid until message encoding completes.
80 *
81 * Safe StringRef Patterns:
82 * 1. String literals: StringRef("literal") - Always safe (static storage duration)
83 * 2. Member variables: StringRef(this->member_string_) - Safe if object outlives encoding
84 * 3. Global/static strings: StringRef(GLOBAL_CONSTANT) - Always safe
85 * 4. Local variables: Safe ONLY if encoding happens before function returns:
86 * std::string temp = compute_value();
87 * msg.field = StringRef(temp);
88 * return this->send_message(msg); // temp is valid during encoding
89 *
90 * Unsafe Patterns (WILL cause crashes/corruption):
91 * 1. Temporaries: msg.field = StringRef(obj.get_string()) // get_string() returns by value
92 * 2. Concatenation: msg.field = StringRef(str1 + str2) // Result is temporary
93 *
94 * For unsafe patterns, store in a local variable first:
95 * std::string temp = get_string(); // or str1 + str2
96 * msg.field = StringRef(temp);
97 *
98 * The send_*_response pattern ensures proper lifetime management by encoding
99 * within the same function scope where temporaries are created.
100 */
101
103#ifdef USE_API_VARINT64
104using proto_varint_value_t = uint64_t;
105#else
107#endif
108
111
116 uint32_t consumed; // PROTO_VARINT_PARSE_FAILED = parse failed
117
118 constexpr bool has_value() const { return this->consumed != PROTO_VARINT_PARSE_FAILED; }
119};
120
123 public:
126 static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse_non_empty(const uint8_t *buffer, uint32_t len) {
127#ifdef ESPHOME_DEBUG_API
128 assert(len > 0);
129#endif
130 // Fast path: single-byte varints (0-127) are the most common case
131 // (booleans, small enums, field tags, small message sizes/types).
132 if ((buffer[0] & 0x80) == 0) [[likely]]
133 return {buffer[0], 1};
134 return parse_slow(buffer, len);
135 }
136
139 static inline ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse(const uint8_t *buffer, uint32_t len) {
140 if (len == 0)
141 return {0, PROTO_VARINT_PARSE_FAILED};
142 return parse_non_empty(buffer, len);
143 }
144
145 protected:
146 // Slow path for multi-byte varints (>= 128), outlined to keep fast path small
147 static ProtoVarIntResult parse_slow(const uint8_t *buffer, uint32_t len) __attribute__((noinline));
148
149#ifdef USE_API_VARINT64
151 static ProtoVarIntResult parse_wide(const uint8_t *buffer, uint32_t len, uint32_t result32) __attribute__((noinline));
152#endif
153};
154
155// Forward declarations for decode_to_message and related encoding helpers
156class ProtoDecodableMessage;
157class ProtoMessage;
158class ProtoSize;
159
161 public:
162 explicit ProtoLengthDelimited(const uint8_t *value, size_t length) : value_(value), length_(length) {}
163 std::string as_string() const { return std::string(reinterpret_cast<const char *>(this->value_), this->length_); }
164
165 // Direct access to raw data without string allocation
166 const uint8_t *data() const { return this->value_; }
167 size_t size() const { return this->length_; }
168
179
180 protected:
181 const uint8_t *const value_;
182 const size_t length_;
183};
184
186 public:
187 explicit Proto32Bit(uint32_t value) : value_(value) {}
188 uint32_t as_fixed32() const { return this->value_; }
189 int32_t as_sfixed32() const { return static_cast<int32_t>(this->value_); }
190 float as_float() const {
191 union {
193 float value;
194 } s{};
195 s.raw = this->value_;
196 return s.value;
197 }
198
199 protected:
201};
202
203// NOTE: Proto64Bit class removed - wire type 1 (64-bit fixed) not supported
204
206 public:
207 ProtoWriteBuffer(APIBuffer *buffer) : buffer_(buffer), pos_(buffer->data() + buffer->size()) {}
208 ProtoWriteBuffer(APIBuffer *buffer, size_t write_pos) : buffer_(buffer), pos_(buffer->data() + write_pos) {}
209 inline void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint32_t value) {
210 if (value < 128) [[likely]] {
211 this->debug_check_bounds_(1);
212 *this->pos_++ = static_cast<uint8_t>(value);
213 return;
214 }
215 this->encode_varint_raw_slow_(value);
216 }
218 while (value > 0x7F) {
219 this->debug_check_bounds_(1);
220 *this->pos_++ = static_cast<uint8_t>(value | 0x80);
221 value >>= 7;
222 }
223 this->debug_check_bounds_(1);
224 *this->pos_++ = static_cast<uint8_t>(value);
225 }
238 void encode_field_raw(uint32_t field_id, uint32_t type) { this->encode_varint_raw((field_id << 3) | type); }
239 void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) {
240 if (len == 0 && !force)
241 return;
242
243 this->encode_field_raw(field_id, 2); // type 2: Length-delimited string
244 this->encode_varint_raw(len);
245 // Direct memcpy into pre-sized buffer — avoids push_back() per-byte capacity checks
246 // and vector::insert() iterator overhead. ~10-11x faster for 16-32 byte strings.
247 this->debug_check_bounds_(len);
248 std::memcpy(this->pos_, string, len);
249 this->pos_ += len;
250 }
251 void encode_string(uint32_t field_id, const std::string &value, bool force = false) {
252 this->encode_string(field_id, value.data(), value.size(), force);
253 }
254 void encode_string(uint32_t field_id, const StringRef &ref, bool force = false) {
255 this->encode_string(field_id, ref.c_str(), ref.size(), force);
256 }
257 void encode_bytes(uint32_t field_id, const uint8_t *data, size_t len, bool force = false) {
258 this->encode_string(field_id, reinterpret_cast<const char *>(data), len, force);
259 }
260 void encode_uint32(uint32_t field_id, uint32_t value, bool force = false) {
261 if (value == 0 && !force)
262 return;
263 this->encode_field_raw(field_id, 0); // type 0: Varint - uint32
264 this->encode_varint_raw(value);
265 }
266 void encode_uint64(uint32_t field_id, uint64_t value, bool force = false) {
267 if (value == 0 && !force)
268 return;
269 this->encode_field_raw(field_id, 0); // type 0: Varint - uint64
270 this->encode_varint_raw_64(value);
271 }
272 void encode_bool(uint32_t field_id, bool value, bool force = false) {
273 if (!value && !force)
274 return;
275 this->encode_field_raw(field_id, 0); // type 0: Varint - bool
276 this->debug_check_bounds_(1);
277 *this->pos_++ = value ? 0x01 : 0x00;
278 }
279 // noinline: 51 call sites; inlining causes net code growth vs a single out-of-line copy
280 __attribute__((noinline)) void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) {
281 if (value == 0 && !force)
282 return;
283
284 this->encode_field_raw(field_id, 5); // type 5: 32-bit fixed32
285 this->debug_check_bounds_(4);
286#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
287 // Protobuf fixed32 is little-endian, so direct copy works
288 std::memcpy(this->pos_, &value, 4);
289 this->pos_ += 4;
290#else
291 *this->pos_++ = (value >> 0) & 0xFF;
292 *this->pos_++ = (value >> 8) & 0xFF;
293 *this->pos_++ = (value >> 16) & 0xFF;
294 *this->pos_++ = (value >> 24) & 0xFF;
295#endif
296 }
297 // NOTE: Wire type 1 (64-bit fixed: double, fixed64, sfixed64) is intentionally
298 // not supported to reduce overhead on embedded systems. All ESPHome devices are
299 // 32-bit microcontrollers where 64-bit operations are expensive. If 64-bit support
300 // is needed in the future, the necessary encoding/decoding functions must be added.
301 void encode_float(uint32_t field_id, float value, bool force = false) {
302 if (value == 0.0f && !force)
303 return;
304
305 union {
306 float value;
308 } val{};
309 val.value = value;
310 this->encode_fixed32(field_id, val.raw);
311 }
312 void encode_int32(uint32_t field_id, int32_t value, bool force = false) {
313 if (value < 0) {
314 // negative int32 is always 10 byte long
315 this->encode_int64(field_id, value, force);
316 return;
317 }
318 this->encode_uint32(field_id, static_cast<uint32_t>(value), force);
319 }
320 void encode_int64(uint32_t field_id, int64_t value, bool force = false) {
321 this->encode_uint64(field_id, static_cast<uint64_t>(value), force);
322 }
323 void encode_sint32(uint32_t field_id, int32_t value, bool force = false) {
324 this->encode_uint32(field_id, encode_zigzag32(value), force);
325 }
326 void encode_sint64(uint32_t field_id, int64_t value, bool force = false) {
327 this->encode_uint64(field_id, encode_zigzag64(value), force);
328 }
330 void encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values);
333 template<typename T> void encode_sub_message(uint32_t field_id, const T &value);
336 template<typename T> void encode_optional_sub_message(uint32_t field_id, const T &value);
337
338 // Non-template core for encode_sub_message — backpatch approach.
339 void encode_sub_message(uint32_t field_id, const void *value, void (*encode_fn)(const void *, ProtoWriteBuffer &));
340 // Non-template core for encode_optional_sub_message.
341 void encode_optional_sub_message(uint32_t field_id, uint32_t nested_size, const void *value,
342 void (*encode_fn)(const void *, ProtoWriteBuffer &));
343 APIBuffer *get_buffer() const { return buffer_; }
344
345 protected:
346 // Slow path for encode_varint_raw values >= 128, outlined to keep fast path small
348
349#ifdef ESPHOME_DEBUG_API
350 void debug_check_bounds_(size_t bytes, const char *caller = __builtin_FUNCTION());
351 void debug_check_encode_size_(uint32_t field_id, uint32_t expected, ptrdiff_t actual);
352#else
353 void debug_check_bounds_([[maybe_unused]] size_t bytes) {}
354#endif
355
357 uint8_t *pos_;
358};
359
360#ifdef HAS_PROTO_MESSAGE_DUMP
367 public:
368 // Matches default tx_buffer_size in logger component
369 static constexpr size_t CAPACITY = 512;
370
371 DumpBuffer() : pos_(0) { buf_[0] = '\0'; }
372
373 DumpBuffer &append(const char *str) {
374 if (str) {
375 append_impl_(str, strlen(str));
376 }
377 return *this;
378 }
379
380 DumpBuffer &append(const char *str, size_t len) {
381 append_impl_(str, len);
382 return *this;
383 }
384
385 DumpBuffer &append(size_t n, char c) {
386 size_t space = CAPACITY - 1 - pos_;
387 if (n > space)
388 n = space;
389 if (n > 0) {
390 memset(buf_ + pos_, c, n);
391 pos_ += n;
392 buf_[pos_] = '\0';
393 }
394 return *this;
395 }
396
397 const char *c_str() const { return buf_; }
398 size_t size() const { return pos_; }
399
401 char *data() { return buf_; }
403 size_t pos() const { return pos_; }
405 void set_pos(size_t pos) {
406 if (pos >= CAPACITY) {
407 pos_ = CAPACITY - 1;
408 } else {
409 pos_ = pos;
410 }
411 buf_[pos_] = '\0';
412 }
413
414 private:
415 void append_impl_(const char *str, size_t len) {
416 size_t space = CAPACITY - 1 - pos_;
417 if (len > space)
418 len = space;
419 if (len > 0) {
420 memcpy(buf_ + pos_, str, len);
421 pos_ += len;
422 buf_[pos_] = '\0';
423 }
424 }
425
426 char buf_[CAPACITY];
427 size_t pos_;
428};
429#endif
430
432 public:
433 // Non-virtual defaults for messages with no fields.
434 // Concrete message classes hide these with their own implementations.
435 // All call sites use templates to preserve the concrete type, so virtual
436 // dispatch is not needed. This eliminates per-message vtable entries for
437 // encode/calculate_size, saving ~1.3 KB of flash across all message types.
438 void encode(ProtoWriteBuffer &buffer) const {}
439 uint32_t calculate_size() const { return 0; }
440#ifdef HAS_PROTO_MESSAGE_DUMP
441 virtual const char *dump_to(DumpBuffer &out) const = 0;
442 virtual const char *message_name() const { return "unknown"; }
443#endif
444
445#ifndef USE_HOST
446 protected:
447#endif
448 // Non-virtual destructor is protected to prevent polymorphic deletion.
449 // On host platform, made public to allow value-initialization of std::array
450 // members (e.g. DeviceInfoResponse::devices) without clang errors.
451 ~ProtoMessage() = default;
452};
453
454// Base class for messages that support decoding
456 public:
457 virtual void decode(const uint8_t *buffer, size_t length);
458
468 static uint32_t count_repeated_field(const uint8_t *buffer, size_t length, uint32_t target_field_id);
469
470 protected:
472 virtual bool decode_varint(uint32_t field_id, proto_varint_value_t value) { return false; }
473 virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value) { return false; }
474 virtual bool decode_32bit(uint32_t field_id, Proto32Bit value) { return false; }
475 // NOTE: decode_64bit removed - wire type 1 not supported
476};
477
479 public:
486 static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint(uint32_t value) {
487 if (value < 128) [[likely]]
488 return 1; // Fast path: 7 bits, most common case
489 if (__builtin_is_constant_evaluated())
490 return varint_wide(value);
491 return varint_slow(value);
492 }
493
494 private:
495 // Slow path for varint >= 128, outlined to keep fast path small
496 static uint32_t varint_slow(uint32_t value) __attribute__((noinline));
497 // Shared cascade for values >= 128 (used by both constexpr and noinline paths)
498 static constexpr inline uint32_t ESPHOME_ALWAYS_INLINE varint_wide(uint32_t value) {
499 if (value < 16384)
500 return 2;
501 if (value < 2097152)
502 return 3;
503 if (value < 268435456)
504 return 4;
505 return 5;
506 }
507
508 public:
515 static constexpr uint32_t varint(uint64_t value) {
516 // Handle common case of values fitting in uint32_t (vast majority of use cases)
517 if (value <= UINT32_MAX) {
518 return varint(static_cast<uint32_t>(value));
519 }
520
521 // For larger values, determine size based on highest bit position
522 if (value < (1ULL << 35)) {
523 return 5; // 35 bits
524 } else if (value < (1ULL << 42)) {
525 return 6; // 42 bits
526 } else if (value < (1ULL << 49)) {
527 return 7; // 49 bits
528 } else if (value < (1ULL << 56)) {
529 return 8; // 56 bits
530 } else if (value < (1ULL << 63)) {
531 return 9; // 63 bits
532 } else {
533 return 10; // 64 bits (maximum for uint64_t)
534 }
535 }
536
546 static constexpr uint32_t varint(int32_t value) {
547 // Negative values are sign-extended to 64 bits in protocol buffers,
548 // which always results in a 10-byte varint for negative int32
549 if (value < 0) {
550 return 10; // Negative int32 is always 10 bytes long
551 }
552 // For non-negative values, use the uint32_t implementation
553 return varint(static_cast<uint32_t>(value));
554 }
555
562 static constexpr uint32_t varint(int64_t value) {
563 // For int64_t, we convert to uint64_t and calculate the size
564 // This works because the bit pattern determines the encoding size,
565 // and we've handled negative int32 values as a special case above
566 return varint(static_cast<uint64_t>(value));
567 }
568
576 static constexpr uint32_t field(uint32_t field_id, uint32_t type) {
577 uint32_t tag = (field_id << 3) | (type & WIRE_TYPE_MASK);
578 return varint(tag);
579 }
580
581 // Static methods that RETURN size contribution (no ProtoSize object needed).
582 // Used by generated calculate_size() methods to accumulate into a plain uint32_t register.
583 static constexpr uint32_t calc_int32(uint32_t field_id_size, int32_t value) {
584 return value ? field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value))) : 0;
585 }
586 static constexpr uint32_t calc_int32_force(uint32_t field_id_size, int32_t value) {
587 return field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value)));
588 }
589 static constexpr uint32_t calc_uint32(uint32_t field_id_size, uint32_t value) {
590 return value ? field_id_size + varint(value) : 0;
591 }
592 static constexpr uint32_t calc_uint32_force(uint32_t field_id_size, uint32_t value) {
593 return field_id_size + varint(value);
594 }
595 static constexpr uint32_t calc_bool(uint32_t field_id_size, bool value) { return value ? field_id_size + 1 : 0; }
596 static constexpr uint32_t calc_bool_force(uint32_t field_id_size) { return field_id_size + 1; }
597 static constexpr uint32_t calc_float(uint32_t field_id_size, float value) {
598 return value != 0.0f ? field_id_size + 4 : 0;
599 }
600 static constexpr uint32_t calc_fixed32(uint32_t field_id_size, uint32_t value) {
601 return value ? field_id_size + 4 : 0;
602 }
603 static constexpr uint32_t calc_sfixed32(uint32_t field_id_size, int32_t value) {
604 return value ? field_id_size + 4 : 0;
605 }
606 static constexpr uint32_t calc_sint32(uint32_t field_id_size, int32_t value) {
607 return value ? field_id_size + varint(encode_zigzag32(value)) : 0;
608 }
609 static constexpr uint32_t calc_sint32_force(uint32_t field_id_size, int32_t value) {
610 return field_id_size + varint(encode_zigzag32(value));
611 }
612 static constexpr uint32_t calc_int64(uint32_t field_id_size, int64_t value) {
613 return value ? field_id_size + varint(value) : 0;
614 }
615 static constexpr uint32_t calc_int64_force(uint32_t field_id_size, int64_t value) {
616 return field_id_size + varint(value);
617 }
618 static constexpr uint32_t calc_uint64(uint32_t field_id_size, uint64_t value) {
619 return value ? field_id_size + varint(value) : 0;
620 }
621 static constexpr uint32_t calc_uint64_force(uint32_t field_id_size, uint64_t value) {
622 return field_id_size + varint(value);
623 }
624 static constexpr uint32_t calc_length(uint32_t field_id_size, size_t len) {
625 return len ? field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len) : 0;
626 }
627 static constexpr uint32_t calc_length_force(uint32_t field_id_size, size_t len) {
628 return field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len);
629 }
630 static constexpr uint32_t calc_sint64(uint32_t field_id_size, int64_t value) {
631 return value ? field_id_size + varint(encode_zigzag64(value)) : 0;
632 }
633 static constexpr uint32_t calc_sint64_force(uint32_t field_id_size, int64_t value) {
634 return field_id_size + varint(encode_zigzag64(value));
635 }
636 static constexpr uint32_t calc_fixed64(uint32_t field_id_size, uint64_t value) {
637 return value ? field_id_size + 8 : 0;
638 }
639 static constexpr uint32_t calc_sfixed64(uint32_t field_id_size, int64_t value) {
640 return value ? field_id_size + 8 : 0;
641 }
642 static constexpr uint32_t calc_message(uint32_t field_id_size, uint32_t nested_size) {
643 return nested_size ? field_id_size + varint(nested_size) + nested_size : 0;
644 }
645 static constexpr uint32_t calc_message_force(uint32_t field_id_size, uint32_t nested_size) {
646 return field_id_size + varint(nested_size) + nested_size;
647 }
648};
649
650// Implementation of methods that depend on ProtoSize being fully defined
651
652// Implementation of encode_packed_sint32 - must be after ProtoSize is defined
653inline void ProtoWriteBuffer::encode_packed_sint32(uint32_t field_id, const std::vector<int32_t> &values) {
654 if (values.empty())
655 return;
656
657 // Calculate packed size
658 size_t packed_size = 0;
659 for (int value : values) {
660 packed_size += ProtoSize::varint(encode_zigzag32(value));
661 }
662
663 // Write tag (LENGTH_DELIMITED) + length + all zigzag-encoded values
665 this->encode_varint_raw(packed_size);
666 for (int value : values) {
668 }
669}
670
671// Encode thunk — converts void* back to concrete type for direct encode() call
672template<typename T> void proto_encode_msg(const void *msg, ProtoWriteBuffer &buf) {
673 static_cast<const T *>(msg)->encode(buf);
674}
675
676// Thin template wrapper; delegates to non-template core in proto.cpp.
677template<typename T> inline void ProtoWriteBuffer::encode_sub_message(uint32_t field_id, const T &value) {
678 this->encode_sub_message(field_id, &value, &proto_encode_msg<T>);
679}
680
681// Thin template wrapper; delegates to non-template core.
682template<typename T> inline void ProtoWriteBuffer::encode_optional_sub_message(uint32_t field_id, const T &value) {
683 this->encode_optional_sub_message(field_id, value.calculate_size(), &value, &proto_encode_msg<T>);
684}
685
686// Implementation of decode_to_message - must be after ProtoDecodableMessage is defined
688 msg.decode(this->value_, this->length_);
689}
690
691template<typename T> const char *proto_enum_to_string(T value);
692
694 public:
695 protected:
696 virtual bool is_authenticated() = 0;
697 virtual bool is_connection_setup() = 0;
698 virtual void on_fatal_error() = 0;
699 virtual void on_no_setup_connection() = 0;
700 virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) = 0;
701 virtual void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data) = 0;
702
703 // Authentication helper methods
705 if (!this->is_connection_setup()) {
707 return false;
708 }
709 return true;
710 }
711
712 inline bool check_authenticated_() { return this->check_connection_setup_(); }
713};
714
715} // namespace esphome::api
uint8_t raw[35]
Definition bl0939.h:0
StringRef is a reference to a string owned by something else.
Definition string_ref.h:26
constexpr const char * c_str() const
Definition string_ref.h:73
constexpr size_type size() const
Definition string_ref.h:74
Byte buffer that skips zero-initialization on resize().
Definition api_buffer.h:36
Fixed-size buffer for message dumps - avoids heap allocation.
Definition proto.h:366
const char * c_str() const
Definition proto.h:397
DumpBuffer & append(size_t n, char c)
Definition proto.h:385
size_t size() const
Definition proto.h:398
size_t pos() const
Get current position for use with buf_append_printf.
Definition proto.h:403
static constexpr size_t CAPACITY
Definition proto.h:369
DumpBuffer & append(const char *str, size_t len)
Definition proto.h:380
DumpBuffer & append(const char *str)
Definition proto.h:373
char * data()
Get writable buffer pointer for use with buf_append_printf.
Definition proto.h:401
void set_pos(size_t pos)
Update position after buf_append_printf call.
Definition proto.h:405
uint32_t as_fixed32() const
Definition proto.h:188
int32_t as_sfixed32() const
Definition proto.h:189
float as_float() const
Definition proto.h:190
const uint32_t value_
Definition proto.h:200
Proto32Bit(uint32_t value)
Definition proto.h:187
virtual bool decode_32bit(uint32_t field_id, Proto32Bit value)
Definition proto.h:474
virtual bool decode_varint(uint32_t field_id, proto_varint_value_t value)
Definition proto.h:472
virtual void decode(const uint8_t *buffer, size_t length)
Definition proto.cpp:206
virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value)
Definition proto.h:473
static uint32_t count_repeated_field(const uint8_t *buffer, size_t length, uint32_t target_field_id)
Count occurrences of a repeated field in a protobuf buffer.
Definition proto.cpp:60
void decode_to_message(ProtoDecodableMessage &msg) const
Decode the length-delimited data into an existing ProtoDecodableMessage instance.
Definition proto.h:687
const uint8_t *const value_
Definition proto.h:181
const uint8_t * data() const
Definition proto.h:166
ProtoLengthDelimited(const uint8_t *value, size_t length)
Definition proto.h:162
std::string as_string() const
Definition proto.h:163
void encode(ProtoWriteBuffer &buffer) const
Definition proto.h:438
uint32_t calculate_size() const
Definition proto.h:439
virtual const char * message_name() const
Definition proto.h:442
virtual const char * dump_to(DumpBuffer &out) const =0
virtual void on_fatal_error()=0
virtual bool is_connection_setup()=0
virtual bool is_authenticated()=0
virtual void read_message(uint32_t msg_size, uint32_t msg_type, const uint8_t *msg_data)=0
virtual void on_no_setup_connection()=0
virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type)=0
static constexpr uint32_t calc_uint64(uint32_t field_id_size, uint64_t value)
Definition proto.h:618
static constexpr uint32_t calc_sint32_force(uint32_t field_id_size, int32_t value)
Definition proto.h:609
static constexpr uint32_t calc_int64(uint32_t field_id_size, int64_t value)
Definition proto.h:612
static constexpr uint32_t calc_bool(uint32_t field_id_size, bool value)
Definition proto.h:595
static constexpr uint32_t calc_uint64_force(uint32_t field_id_size, uint64_t value)
Definition proto.h:621
static constexpr uint32_t calc_message(uint32_t field_id_size, uint32_t nested_size)
Definition proto.h:642
static constexpr uint32_t calc_sint32(uint32_t field_id_size, int32_t value)
Definition proto.h:606
static constexpr uint32_t calc_sint64_force(uint32_t field_id_size, int64_t value)
Definition proto.h:633
static constexpr uint32_t field(uint32_t field_id, uint32_t type)
Calculates the size in bytes needed to encode a field ID and wire type.
Definition proto.h:576
static constexpr uint32_t ESPHOME_ALWAYS_INLINE varint(uint32_t value)
Calculates the size in bytes needed to encode a uint32_t value as a varint.
Definition proto.h:486
static constexpr uint32_t calc_uint32_force(uint32_t field_id_size, uint32_t value)
Definition proto.h:592
static constexpr uint32_t calc_length_force(uint32_t field_id_size, size_t len)
Definition proto.h:627
static constexpr uint32_t varint(int32_t value)
Calculates the size in bytes needed to encode an int32_t value as a varint.
Definition proto.h:546
static constexpr uint32_t calc_int64_force(uint32_t field_id_size, int64_t value)
Definition proto.h:615
static constexpr uint32_t calc_sfixed64(uint32_t field_id_size, int64_t value)
Definition proto.h:639
static constexpr uint32_t calc_uint32(uint32_t field_id_size, uint32_t value)
Definition proto.h:589
static constexpr uint32_t calc_length(uint32_t field_id_size, size_t len)
Definition proto.h:624
static constexpr uint32_t calc_message_force(uint32_t field_id_size, uint32_t nested_size)
Definition proto.h:645
static constexpr uint32_t calc_int32(uint32_t field_id_size, int32_t value)
Definition proto.h:583
static constexpr uint32_t calc_fixed64(uint32_t field_id_size, uint64_t value)
Definition proto.h:636
static constexpr uint32_t varint(int64_t value)
Calculates the size in bytes needed to encode an int64_t value as a varint.
Definition proto.h:562
static constexpr uint32_t calc_bool_force(uint32_t field_id_size)
Definition proto.h:596
static constexpr uint32_t calc_sfixed32(uint32_t field_id_size, int32_t value)
Definition proto.h:603
static constexpr uint32_t varint(uint64_t value)
Calculates the size in bytes needed to encode a uint64_t value as a varint.
Definition proto.h:515
static constexpr uint32_t calc_float(uint32_t field_id_size, float value)
Definition proto.h:597
static constexpr uint32_t calc_sint64(uint32_t field_id_size, int64_t value)
Definition proto.h:630
static constexpr uint32_t calc_int32_force(uint32_t field_id_size, int32_t value)
Definition proto.h:586
static constexpr uint32_t calc_fixed32(uint32_t field_id_size, uint32_t value)
Definition proto.h:600
Static varint parsing methods for the protobuf wire format.
Definition proto.h:122
static ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse_non_empty(const uint8_t *buffer, uint32_t len)
Parse a varint from buffer.
Definition proto.h:126
static ProtoVarIntResult parse_wide(const uint8_t *buffer, uint32_t len, uint32_t result32) __attribute__((noinline))
Continue parsing varint bytes 4-9 with 64-bit arithmetic.
Definition proto.cpp:46
static ProtoVarIntResult parse_slow(const uint8_t *buffer, uint32_t len) __attribute__((noinline))
Definition proto.cpp:23
static ProtoVarIntResult ESPHOME_ALWAYS_INLINE parse(const uint8_t *buffer, uint32_t len)
Parse a varint from buffer (safe for empty buffers).
Definition proto.h:139
void encode_string(uint32_t field_id, const std::string &value, bool force=false)
Definition proto.h:251
void debug_check_encode_size_(uint32_t field_id, uint32_t expected, ptrdiff_t actual)
Definition proto.cpp:199
void debug_check_bounds_(size_t bytes)
Definition proto.h:353
void encode_string(uint32_t field_id, const char *string, size_t len, bool force=false)
Definition proto.h:239
__attribute__((noinline)) void encode_fixed32(uint32_t field_id
void encode_bool(uint32_t field_id, bool value, bool force=false)
Definition proto.h:272
void encode_varint_raw_slow_(uint32_t value) __attribute__((noinline))
Definition proto.cpp:13
void encode_uint64(uint32_t field_id, uint64_t value, bool force=false)
Definition proto.h:266
void encode_string(uint32_t field_id, const StringRef &ref, bool force=false)
Definition proto.h:254
void encode_uint32(uint32_t field_id, uint32_t value, bool force=false)
Definition proto.h:260
void encode_field_raw(uint32_t field_id, uint32_t type)
Encode a field key (tag/wire type combination).
Definition proto.h:238
void encode_optional_sub_message(uint32_t field_id, const T &value)
Encode an optional singular submessage field — skips if empty.
Definition proto.h:682
void encode_sub_message(uint32_t field_id, const T &value)
Single-pass encode for repeated submessage elements.
Definition proto.h:677
void debug_check_bounds_(size_t bytes, const char *caller=__builtin_FUNCTION())
Definition proto.cpp:192
void encode_bytes(uint32_t field_id, const uint8_t *data, size_t len, bool force=false)
Definition proto.h:257
APIBuffer * get_buffer() const
Definition proto.h:343
void ESPHOME_ALWAYS_INLINE encode_varint_raw(uint32_t value)
Definition proto.h:209
ProtoWriteBuffer(APIBuffer *buffer, size_t write_pos)
Definition proto.h:208
void encode_varint_raw_64(uint64_t value)
Definition proto.h:217
ProtoWriteBuffer(APIBuffer *buffer)
Definition proto.h:207
struct @65::@66 __attribute__
uint16_t type
mopeka_std_values val[3]
void proto_encode_msg(const void *msg, ProtoWriteBuffer &buf)
Definition proto.h:672
constexpr uint32_t encode_zigzag32(int32_t value)
Definition proto.h:28
constexpr uint8_t WIRE_TYPE_VARINT
Definition proto.h:22
uint64_t proto_varint_value_t
Type used for decoded varint values - uint64_t when BLE needs 64-bit addresses, uint32_t otherwise.
Definition proto.h:104
const char * proto_enum_to_string(T value)
constexpr uint64_t encode_zigzag64(int64_t value)
Definition proto.h:32
constexpr uint8_t WIRE_TYPE_MASK
Definition proto.h:25
constexpr uint32_t PROTO_VARINT_PARSE_FAILED
Sentinel value for consumed field indicating parse failure.
Definition proto.h:110
constexpr uint8_t WIRE_TYPE_LENGTH_DELIMITED
Definition proto.h:23
constexpr int32_t decode_zigzag32(uint32_t value)
Definition proto.h:36
constexpr uint8_t WIRE_TYPE_FIXED32
Definition proto.h:24
constexpr int64_t decode_zigzag64(uint64_t value)
Definition proto.h:40
void encode_varint_to_buffer(uint32_t val, uint8_t *buffer)
Encode a varint directly into a pre-allocated buffer.
Definition proto.h:64
uint16_t count_packed_varints(const uint8_t *data, size_t len)
Count number of varints in a packed buffer.
Definition proto.h:45
const char * tag
Definition log.h:74
std::string size_t len
Definition helpers.h:892
size_t size
Definition helpers.h:929
static void uint32_t
Result of parsing a varint: value + number of bytes consumed.
Definition proto.h:114
constexpr bool has_value() const
Definition proto.h:118
proto_varint_value_t value
Definition proto.h:115
uint16_t length
Definition tt21100.cpp:0