ESPHome 2025.12.0-dev
Loading...
Searching...
No Matches
proto.h
Go to the documentation of this file.
1#pragma once
2
5#include "esphome/core/log.h"
7
8#include <cassert>
9#include <cstring>
10#include <vector>
11
12#ifdef ESPHOME_LOG_HAS_VERY_VERBOSE
13#define HAS_PROTO_MESSAGE_DUMP
14#endif
15
16namespace esphome::api {
17
18// Protocol Buffer wire type constants
19// See https://protobuf.dev/programming-guides/encoding/#structure
20constexpr uint8_t WIRE_TYPE_VARINT = 0; // int32, int64, uint32, uint64, sint32, sint64, bool, enum
21constexpr uint8_t WIRE_TYPE_LENGTH_DELIMITED = 2; // string, bytes, embedded messages, packed repeated fields
22constexpr uint8_t WIRE_TYPE_FIXED32 = 5; // fixed32, sfixed32, float
23constexpr uint8_t WIRE_TYPE_MASK = 0b111; // Mask to extract wire type from tag
24
25// Helper functions for ZigZag encoding/decoding
26inline constexpr uint32_t encode_zigzag32(int32_t value) {
27 return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31));
28}
29
30inline constexpr uint64_t encode_zigzag64(int64_t value) {
31 return (static_cast<uint64_t>(value) << 1) ^ (static_cast<uint64_t>(value >> 63));
32}
33
34inline constexpr int32_t decode_zigzag32(uint32_t value) {
35 return (value & 1) ? static_cast<int32_t>(~(value >> 1)) : static_cast<int32_t>(value >> 1);
36}
37
38inline constexpr int64_t decode_zigzag64(uint64_t value) {
39 return (value & 1) ? static_cast<int64_t>(~(value >> 1)) : static_cast<int64_t>(value >> 1);
40}
41
42/*
43 * StringRef Ownership Model for API Protocol Messages
44 * ===================================================
45 *
46 * StringRef is used for zero-copy string handling in outgoing (SOURCE_SERVER) messages.
47 * It holds a pointer and length to existing string data without copying.
48 *
49 * CRITICAL: The referenced string data MUST remain valid until message encoding completes.
50 *
51 * Safe StringRef Patterns:
52 * 1. String literals: StringRef("literal") - Always safe (static storage duration)
53 * 2. Member variables: StringRef(this->member_string_) - Safe if object outlives encoding
54 * 3. Global/static strings: StringRef(GLOBAL_CONSTANT) - Always safe
55 * 4. Local variables: Safe ONLY if encoding happens before function returns:
56 * std::string temp = compute_value();
57 * msg.set_field(StringRef(temp));
58 * return this->send_message(msg); // temp is valid during encoding
59 *
60 * Unsafe Patterns (WILL cause crashes/corruption):
61 * 1. Temporaries: msg.set_field(StringRef(obj.get_string())) // get_string() returns by value
62 * 2. Concatenation: msg.set_field(StringRef(str1 + str2)) // Result is temporary
63 *
64 * For unsafe patterns, store in a local variable first:
65 * std::string temp = get_string(); // or str1 + str2
66 * msg.set_field(StringRef(temp));
67 *
68 * The send_*_response pattern ensures proper lifetime management by encoding
69 * within the same function scope where temporaries are created.
70 */
71
74 public:
76 explicit ProtoVarInt(uint64_t value) : value_(value) {}
77
78 static optional<ProtoVarInt> parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed) {
79 if (len == 0) {
80 if (consumed != nullptr)
81 *consumed = 0;
82 return {};
83 }
84
85 // Most common case: single-byte varint (values 0-127)
86 if ((buffer[0] & 0x80) == 0) {
87 if (consumed != nullptr)
88 *consumed = 1;
89 return ProtoVarInt(buffer[0]);
90 }
91
92 // General case for multi-byte varints
93 // Since we know buffer[0]'s high bit is set, initialize with its value
94 uint64_t result = buffer[0] & 0x7F;
95 uint8_t bitpos = 7;
96
97 // Start from the second byte since we've already processed the first
98 for (uint32_t i = 1; i < len; i++) {
99 uint8_t val = buffer[i];
100 result |= uint64_t(val & 0x7F) << uint64_t(bitpos);
101 bitpos += 7;
102 if ((val & 0x80) == 0) {
103 if (consumed != nullptr)
104 *consumed = i + 1;
105 return ProtoVarInt(result);
106 }
107 }
108
109 if (consumed != nullptr)
110 *consumed = 0;
111 return {}; // Incomplete or invalid varint
112 }
113
114 constexpr uint16_t as_uint16() const { return this->value_; }
115 constexpr uint32_t as_uint32() const { return this->value_; }
116 constexpr uint64_t as_uint64() const { return this->value_; }
117 constexpr bool as_bool() const { return this->value_; }
118 constexpr int32_t as_int32() const {
119 // Not ZigZag encoded
120 return static_cast<int32_t>(this->as_int64());
121 }
122 constexpr int64_t as_int64() const {
123 // Not ZigZag encoded
124 return static_cast<int64_t>(this->value_);
125 }
126 constexpr int32_t as_sint32() const {
127 // with ZigZag encoding
128 return decode_zigzag32(static_cast<uint32_t>(this->value_));
129 }
130 constexpr int64_t as_sint64() const {
131 // with ZigZag encoding
132 return decode_zigzag64(this->value_);
133 }
145 void encode_to_buffer_unchecked(uint8_t *buffer, size_t len) {
146 uint64_t val = this->value_;
147 if (val <= 0x7F) {
148 buffer[0] = val;
149 return;
150 }
151 size_t i = 0;
152 while (val && i < len) {
153 uint8_t temp = val & 0x7F;
154 val >>= 7;
155 if (val) {
156 buffer[i++] = temp | 0x80;
157 } else {
158 buffer[i++] = temp;
159 }
160 }
161 }
162 void encode(std::vector<uint8_t> &out) {
163 uint64_t val = this->value_;
164 if (val <= 0x7F) {
165 out.push_back(val);
166 return;
167 }
168 while (val) {
169 uint8_t temp = val & 0x7F;
170 val >>= 7;
171 if (val) {
172 out.push_back(temp | 0x80);
173 } else {
174 out.push_back(temp);
175 }
176 }
177 }
178
179 protected:
180 uint64_t value_;
181};
182
183// Forward declaration for decode_to_message and encode_to_writer
184class ProtoMessage;
186
188 public:
189 explicit ProtoLengthDelimited(const uint8_t *value, size_t length) : value_(value), length_(length) {}
190 std::string as_string() const { return std::string(reinterpret_cast<const char *>(this->value_), this->length_); }
191
192 // Direct access to raw data without string allocation
193 const uint8_t *data() const { return this->value_; }
194 size_t size() const { return this->length_; }
195
206
207 protected:
208 const uint8_t *const value_;
209 const size_t length_;
210};
211
213 public:
214 explicit Proto32Bit(uint32_t value) : value_(value) {}
215 uint32_t as_fixed32() const { return this->value_; }
216 int32_t as_sfixed32() const { return static_cast<int32_t>(this->value_); }
217 float as_float() const {
218 union {
219 uint32_t raw;
220 float value;
221 } s{};
222 s.raw = this->value_;
223 return s.value;
224 }
225
226 protected:
227 const uint32_t value_;
228};
229
230// NOTE: Proto64Bit class removed - wire type 1 (64-bit fixed) not supported
231
233 public:
234 ProtoWriteBuffer(std::vector<uint8_t> *buffer) : buffer_(buffer) {}
235 void write(uint8_t value) { this->buffer_->push_back(value); }
236 void encode_varint_raw(ProtoVarInt value) { value.encode(*this->buffer_); }
237 void encode_varint_raw(uint32_t value) { this->encode_varint_raw(ProtoVarInt(value)); }
250 void encode_field_raw(uint32_t field_id, uint32_t type) {
251 uint32_t val = (field_id << 3) | (type & WIRE_TYPE_MASK);
252 this->encode_varint_raw(val);
253 }
254 void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) {
255 if (len == 0 && !force)
256 return;
257
258 this->encode_field_raw(field_id, 2); // type 2: Length-delimited string
259 this->encode_varint_raw(len);
260
261 // Using resize + memcpy instead of insert provides significant performance improvement:
262 // ~10-11x faster for 16-32 byte strings, ~3x faster for 64-byte strings
263 // as it avoids iterator checks and potential element moves that insert performs
264 size_t old_size = this->buffer_->size();
265 this->buffer_->resize(old_size + len);
266 std::memcpy(this->buffer_->data() + old_size, string, len);
267 }
268 void encode_string(uint32_t field_id, const std::string &value, bool force = false) {
269 this->encode_string(field_id, value.data(), value.size(), force);
270 }
271 void encode_string(uint32_t field_id, const StringRef &ref, bool force = false) {
272 this->encode_string(field_id, ref.c_str(), ref.size(), force);
273 }
274 void encode_bytes(uint32_t field_id, const uint8_t *data, size_t len, bool force = false) {
275 this->encode_string(field_id, reinterpret_cast<const char *>(data), len, force);
276 }
277 void encode_uint32(uint32_t field_id, uint32_t value, bool force = false) {
278 if (value == 0 && !force)
279 return;
280 this->encode_field_raw(field_id, 0); // type 0: Varint - uint32
281 this->encode_varint_raw(value);
282 }
283 void encode_uint64(uint32_t field_id, uint64_t value, bool force = false) {
284 if (value == 0 && !force)
285 return;
286 this->encode_field_raw(field_id, 0); // type 0: Varint - uint64
287 this->encode_varint_raw(ProtoVarInt(value));
288 }
289 void encode_bool(uint32_t field_id, bool value, bool force = false) {
290 if (!value && !force)
291 return;
292 this->encode_field_raw(field_id, 0); // type 0: Varint - bool
293 this->write(0x01);
294 }
295 void encode_fixed32(uint32_t field_id, uint32_t value, bool force = false) {
296 if (value == 0 && !force)
297 return;
298
299 this->encode_field_raw(field_id, 5); // type 5: 32-bit fixed32
300 this->write((value >> 0) & 0xFF);
301 this->write((value >> 8) & 0xFF);
302 this->write((value >> 16) & 0xFF);
303 this->write((value >> 24) & 0xFF);
304 }
305 // NOTE: Wire type 1 (64-bit fixed: double, fixed64, sfixed64) is intentionally
306 // not supported to reduce overhead on embedded systems. All ESPHome devices are
307 // 32-bit microcontrollers where 64-bit operations are expensive. If 64-bit support
308 // is needed in the future, the necessary encoding/decoding functions must be added.
309 void encode_float(uint32_t field_id, float value, bool force = false) {
310 if (value == 0.0f && !force)
311 return;
312
313 union {
314 float value;
315 uint32_t raw;
316 } val{};
317 val.value = value;
318 this->encode_fixed32(field_id, val.raw);
319 }
320 void encode_int32(uint32_t field_id, int32_t value, bool force = false) {
321 if (value < 0) {
322 // negative int32 is always 10 byte long
323 this->encode_int64(field_id, value, force);
324 return;
325 }
326 this->encode_uint32(field_id, static_cast<uint32_t>(value), force);
327 }
328 void encode_int64(uint32_t field_id, int64_t value, bool force = false) {
329 this->encode_uint64(field_id, static_cast<uint64_t>(value), force);
330 }
331 void encode_sint32(uint32_t field_id, int32_t value, bool force = false) {
332 this->encode_uint32(field_id, encode_zigzag32(value), force);
333 }
334 void encode_sint64(uint32_t field_id, int64_t value, bool force = false) {
335 this->encode_uint64(field_id, encode_zigzag64(value), force);
336 }
337 void encode_message(uint32_t field_id, const ProtoMessage &value, bool force = false);
338 std::vector<uint8_t> *get_buffer() const { return buffer_; }
339
340 protected:
341 std::vector<uint8_t> *buffer_;
342};
343
344// Forward declaration
345class ProtoSize;
346
348 public:
349 virtual ~ProtoMessage() = default;
350 // Default implementation for messages with no fields
351 virtual void encode(ProtoWriteBuffer buffer) const {}
352 // Default implementation for messages with no fields
353 virtual void calculate_size(ProtoSize &size) const {}
354#ifdef HAS_PROTO_MESSAGE_DUMP
355 std::string dump() const;
356 virtual void dump_to(std::string &out) const = 0;
357 virtual const char *message_name() const { return "unknown"; }
358#endif
359};
360
361// Base class for messages that support decoding
363 public:
364 virtual void decode(const uint8_t *buffer, size_t length);
365
375 static uint32_t count_repeated_field(const uint8_t *buffer, size_t length, uint32_t target_field_id);
376
377 protected:
378 virtual bool decode_varint(uint32_t field_id, ProtoVarInt value) { return false; }
379 virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value) { return false; }
380 virtual bool decode_32bit(uint32_t field_id, Proto32Bit value) { return false; }
381 // NOTE: decode_64bit removed - wire type 1 not supported
382};
383
385 private:
386 uint32_t total_size_ = 0;
387
388 public:
407 ProtoSize() = default;
408
409 uint32_t get_size() const { return total_size_; }
410
417 static constexpr uint32_t varint(uint32_t value) {
418 // Optimized varint size calculation using leading zeros
419 // Each 7 bits requires one byte in the varint encoding
420 if (value < 128)
421 return 1; // 7 bits, common case for small values
422
423 // For larger values, count bytes needed based on the position of the highest bit set
424 if (value < 16384) {
425 return 2; // 14 bits
426 } else if (value < 2097152) {
427 return 3; // 21 bits
428 } else if (value < 268435456) {
429 return 4; // 28 bits
430 } else {
431 return 5; // 32 bits (maximum for uint32_t)
432 }
433 }
434
441 static constexpr uint32_t varint(uint64_t value) {
442 // Handle common case of values fitting in uint32_t (vast majority of use cases)
443 if (value <= UINT32_MAX) {
444 return varint(static_cast<uint32_t>(value));
445 }
446
447 // For larger values, determine size based on highest bit position
448 if (value < (1ULL << 35)) {
449 return 5; // 35 bits
450 } else if (value < (1ULL << 42)) {
451 return 6; // 42 bits
452 } else if (value < (1ULL << 49)) {
453 return 7; // 49 bits
454 } else if (value < (1ULL << 56)) {
455 return 8; // 56 bits
456 } else if (value < (1ULL << 63)) {
457 return 9; // 63 bits
458 } else {
459 return 10; // 64 bits (maximum for uint64_t)
460 }
461 }
462
472 static constexpr uint32_t varint(int32_t value) {
473 // Negative values are sign-extended to 64 bits in protocol buffers,
474 // which always results in a 10-byte varint for negative int32
475 if (value < 0) {
476 return 10; // Negative int32 is always 10 bytes long
477 }
478 // For non-negative values, use the uint32_t implementation
479 return varint(static_cast<uint32_t>(value));
480 }
481
488 static constexpr uint32_t varint(int64_t value) {
489 // For int64_t, we convert to uint64_t and calculate the size
490 // This works because the bit pattern determines the encoding size,
491 // and we've handled negative int32 values as a special case above
492 return varint(static_cast<uint64_t>(value));
493 }
494
502 static constexpr uint32_t field(uint32_t field_id, uint32_t type) {
503 uint32_t tag = (field_id << 3) | (type & WIRE_TYPE_MASK);
504 return varint(tag);
505 }
506
524 inline void add_int32(uint32_t field_id_size, int32_t value) {
525 if (value != 0) {
526 add_int32_force(field_id_size, value);
527 }
528 }
529
533 inline void add_int32_force(uint32_t field_id_size, int32_t value) {
534 // Always calculate size when forced
535 // Negative values are encoded as 10-byte varints in protobuf
536 total_size_ += field_id_size + (value < 0 ? 10 : varint(static_cast<uint32_t>(value)));
537 }
538
542 inline void add_uint32(uint32_t field_id_size, uint32_t value) {
543 if (value != 0) {
544 add_uint32_force(field_id_size, value);
545 }
546 }
547
551 inline void add_uint32_force(uint32_t field_id_size, uint32_t value) {
552 // Always calculate size when force is true
553 total_size_ += field_id_size + varint(value);
554 }
555
559 inline void add_bool(uint32_t field_id_size, bool value) {
560 if (value) {
561 // Boolean fields always use 1 byte when true
562 total_size_ += field_id_size + 1;
563 }
564 }
565
569 inline void add_bool_force(uint32_t field_id_size, bool value) {
570 // Always calculate size when force is true
571 // Boolean fields always use 1 byte
572 total_size_ += field_id_size + 1;
573 }
574
578 inline void add_float(uint32_t field_id_size, float value) {
579 if (value != 0.0f) {
580 total_size_ += field_id_size + 4;
581 }
582 }
583
584 // NOTE: add_double_field removed - wire type 1 (64-bit: double) not supported
585 // to reduce overhead on embedded systems
586
590 inline void add_fixed32(uint32_t field_id_size, uint32_t value) {
591 if (value != 0) {
592 total_size_ += field_id_size + 4;
593 }
594 }
595
596 // NOTE: add_fixed64_field removed - wire type 1 (64-bit: fixed64) not supported
597 // to reduce overhead on embedded systems
598
602 inline void add_sfixed32(uint32_t field_id_size, int32_t value) {
603 if (value != 0) {
604 total_size_ += field_id_size + 4;
605 }
606 }
607
608 // NOTE: add_sfixed64_field removed - wire type 1 (64-bit: sfixed64) not supported
609 // to reduce overhead on embedded systems
610
616 inline void add_sint32(uint32_t field_id_size, int32_t value) {
617 if (value != 0) {
618 add_sint32_force(field_id_size, value);
619 }
620 }
621
627 inline void add_sint32_force(uint32_t field_id_size, int32_t value) {
628 // Always calculate size when force is true
629 // ZigZag encoding for sint32
630 total_size_ += field_id_size + varint(encode_zigzag32(value));
631 }
632
636 inline void add_int64(uint32_t field_id_size, int64_t value) {
637 if (value != 0) {
638 add_int64_force(field_id_size, value);
639 }
640 }
641
645 inline void add_int64_force(uint32_t field_id_size, int64_t value) {
646 // Always calculate size when force is true
647 total_size_ += field_id_size + varint(value);
648 }
649
653 inline void add_uint64(uint32_t field_id_size, uint64_t value) {
654 if (value != 0) {
655 add_uint64_force(field_id_size, value);
656 }
657 }
658
662 inline void add_uint64_force(uint32_t field_id_size, uint64_t value) {
663 // Always calculate size when force is true
664 total_size_ += field_id_size + varint(value);
665 }
666
667 // NOTE: sint64 support functions (add_sint64_field, add_sint64_field_force) removed
668 // sint64 type is not supported by ESPHome API to reduce overhead on embedded systems
669
673 inline void add_length(uint32_t field_id_size, size_t len) {
674 if (len != 0) {
675 add_length_force(field_id_size, len);
676 }
677 }
678
683 inline void add_length_force(uint32_t field_id_size, size_t len) {
684 // Always calculate size when force is true
685 // Field ID + length varint + data bytes
686 total_size_ += field_id_size + varint(static_cast<uint32_t>(len)) + static_cast<uint32_t>(len);
687 }
688
697 inline void add_precalculated_size(uint32_t size) { total_size_ += size; }
698
707 inline void add_message_field(uint32_t field_id_size, uint32_t nested_size) {
708 if (nested_size != 0) {
709 add_message_field_force(field_id_size, nested_size);
710 }
711 }
712
718 inline void add_message_field_force(uint32_t field_id_size, uint32_t nested_size) {
719 // Always calculate size when force is true
720 // Field ID + length varint + nested message content
721 total_size_ += field_id_size + varint(nested_size) + nested_size;
722 }
723
733 inline void add_message_object(uint32_t field_id_size, const ProtoMessage &message) {
734 // Calculate nested message size by creating a temporary ProtoSize
735 ProtoSize nested_calc;
736 message.calculate_size(nested_calc);
737 uint32_t nested_size = nested_calc.get_size();
738
739 // Use the base implementation with the calculated nested_size
740 add_message_field(field_id_size, nested_size);
741 }
742
748 inline void add_message_object_force(uint32_t field_id_size, const ProtoMessage &message) {
749 // Calculate nested message size by creating a temporary ProtoSize
750 ProtoSize nested_calc;
751 message.calculate_size(nested_calc);
752 uint32_t nested_size = nested_calc.get_size();
753
754 // Use the base implementation with the calculated nested_size
755 add_message_field_force(field_id_size, nested_size);
756 }
757
767 template<typename MessageType>
768 inline void add_repeated_message(uint32_t field_id_size, const std::vector<MessageType> &messages) {
769 // Skip if the vector is empty
770 if (!messages.empty()) {
771 // Use the force version for all messages in the repeated field
772 for (const auto &message : messages) {
773 add_message_object_force(field_id_size, message);
774 }
775 }
776 }
777
785 template<typename MessageType>
786 inline void add_repeated_message(uint32_t field_id_size, const FixedVector<MessageType> &messages) {
787 // Skip if the fixed vector is empty
788 if (!messages.empty()) {
789 // Use the force version for all messages in the repeated field
790 for (const auto &message : messages) {
791 add_message_object_force(field_id_size, message);
792 }
793 }
794 }
795};
796
797// Implementation of encode_message - must be after ProtoMessage is defined
798inline void ProtoWriteBuffer::encode_message(uint32_t field_id, const ProtoMessage &value, bool force) {
799 this->encode_field_raw(field_id, 2); // type 2: Length-delimited message
800
801 // Calculate the message size first
802 ProtoSize msg_size;
803 value.calculate_size(msg_size);
804 uint32_t msg_length_bytes = msg_size.get_size();
805
806 // Calculate how many bytes the length varint needs
807 uint32_t varint_length_bytes = ProtoSize::varint(msg_length_bytes);
808
809 // Reserve exact space for the length varint
810 size_t begin = this->buffer_->size();
811 this->buffer_->resize(this->buffer_->size() + varint_length_bytes);
812
813 // Write the length varint directly
814 ProtoVarInt(msg_length_bytes).encode_to_buffer_unchecked(this->buffer_->data() + begin, varint_length_bytes);
815
816 // Now encode the message content - it will append to the buffer
817 value.encode(*this);
818
819 // Verify that the encoded size matches what we calculated
820 assert(this->buffer_->size() == begin + varint_length_bytes + msg_length_bytes);
821}
822
823// Implementation of decode_to_message - must be after ProtoDecodableMessage is defined
825 msg.decode(this->value_, this->length_);
826}
827
828template<typename T> const char *proto_enum_to_string(T value);
829
831 public:
832 protected:
833 virtual bool is_authenticated() = 0;
834 virtual bool is_connection_setup() = 0;
835 virtual void on_fatal_error() = 0;
836#ifdef USE_API_PASSWORD
837 virtual void on_unauthenticated_access() = 0;
838#endif
839 virtual void on_no_setup_connection() = 0;
847 virtual ProtoWriteBuffer create_buffer(uint32_t reserve_size) = 0;
848 virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type) = 0;
849 virtual void read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data) = 0;
850
851 // Optimized method that pre-allocates buffer based on message size
852 bool send_message_(const ProtoMessage &msg, uint8_t message_type) {
853 ProtoSize size;
854 msg.calculate_size(size);
855 uint32_t msg_size = size.get_size();
856
857 // Create a pre-sized buffer
858 auto buffer = this->create_buffer(msg_size);
859
860 // Encode message into the buffer
861 msg.encode(buffer);
862
863 // Send the buffer
864 return this->send_buffer(buffer, message_type);
865 }
866
867 // Authentication helper methods
869 if (!this->is_connection_setup()) {
871 return false;
872 }
873 return true;
874 }
875
876 inline bool check_authenticated_() {
877#ifdef USE_API_PASSWORD
878 if (!this->check_connection_setup_()) {
879 return false;
880 }
881 if (!this->is_authenticated()) {
883 return false;
884 }
885 return true;
886#else
887 return this->check_connection_setup_();
888#endif
889 }
890};
891
892} // namespace esphome::api
uint8_t raw[35]
Definition bl0939.h:0
Fixed-capacity vector - allocates once at runtime, never reallocates This avoids std::vector template...
Definition helpers.h:184
bool empty() const
Definition helpers.h:339
StringRef is a reference to a string owned by something else.
Definition string_ref.h:22
constexpr const char * c_str() const
Definition string_ref.h:69
constexpr size_type size() const
Definition string_ref.h:70
uint32_t as_fixed32() const
Definition proto.h:215
int32_t as_sfixed32() const
Definition proto.h:216
float as_float() const
Definition proto.h:217
const uint32_t value_
Definition proto.h:227
Proto32Bit(uint32_t value)
Definition proto.h:214
virtual bool decode_32bit(uint32_t field_id, Proto32Bit value)
Definition proto.h:380
virtual bool decode_varint(uint32_t field_id, ProtoVarInt value)
Definition proto.h:378
virtual void decode(const uint8_t *buffer, size_t length)
Definition proto.cpp:73
virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value)
Definition proto.h:379
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:10
void decode_to_message(ProtoDecodableMessage &msg) const
Decode the length-delimited data into an existing ProtoDecodableMessage instance.
Definition proto.h:824
const uint8_t *const value_
Definition proto.h:208
const uint8_t * data() const
Definition proto.h:193
ProtoLengthDelimited(const uint8_t *value, size_t length)
Definition proto.h:189
std::string as_string() const
Definition proto.h:190
virtual void encode(ProtoWriteBuffer buffer) const
Definition proto.h:351
virtual const char * message_name() const
Definition proto.h:357
std::string dump() const
Definition proto.cpp:143
virtual ~ProtoMessage()=default
virtual void calculate_size(ProtoSize &size) const
Definition proto.h:353
virtual void dump_to(std::string &out) const =0
virtual void read_message(uint32_t msg_size, uint32_t msg_type, uint8_t *msg_data)=0
virtual void on_unauthenticated_access()=0
virtual ProtoWriteBuffer create_buffer(uint32_t reserve_size)=0
Create a buffer with a reserved size.
virtual void on_fatal_error()=0
virtual bool is_connection_setup()=0
virtual bool is_authenticated()=0
virtual void on_no_setup_connection()=0
bool send_message_(const ProtoMessage &msg, uint8_t message_type)
Definition proto.h:852
virtual bool send_buffer(ProtoWriteBuffer buffer, uint8_t message_type)=0
void add_message_object(uint32_t field_id_size, const ProtoMessage &message)
Calculates and adds the size of a nested message field to the total message size.
Definition proto.h:733
static constexpr uint32_t varint(uint32_t value)
Calculates the size in bytes needed to encode a uint32_t value as a varint.
Definition proto.h:417
void add_message_field_force(uint32_t field_id_size, uint32_t nested_size)
Calculates and adds the size of a nested message field to the total message size (force version)
Definition proto.h:718
void add_message_object_force(uint32_t field_id_size, const ProtoMessage &message)
Calculates and adds the size of a nested message field to the total message size (force version)
Definition proto.h:748
void add_float(uint32_t field_id_size, float value)
Calculates and adds the size of a float field to the total message size.
Definition proto.h:578
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:502
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:472
void add_sfixed32(uint32_t field_id_size, int32_t value)
Calculates and adds the size of a sfixed32 field to the total message size.
Definition proto.h:602
void add_uint32_force(uint32_t field_id_size, uint32_t value)
Calculates and adds the size of a uint32 field to the total message size (force version)
Definition proto.h:551
void add_int32_force(uint32_t field_id_size, int32_t value)
Calculates and adds the size of an int32 field to the total message size (force version)
Definition proto.h:533
void add_repeated_message(uint32_t field_id_size, const FixedVector< MessageType > &messages)
Calculates and adds the sizes of all messages in a repeated field to the total message size (FixedVec...
Definition proto.h:786
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:488
void add_int64_force(uint32_t field_id_size, int64_t value)
Calculates and adds the size of an int64 field to the total message size (force version)
Definition proto.h:645
void add_sint32(uint32_t field_id_size, int32_t value)
Calculates and adds the size of a sint32 field to the total message size.
Definition proto.h:616
void add_message_field(uint32_t field_id_size, uint32_t nested_size)
Calculates and adds the size of a nested message field to the total message size.
Definition proto.h:707
void add_bool_force(uint32_t field_id_size, bool value)
Calculates and adds the size of a boolean field to the total message size (force version)
Definition proto.h:569
void add_int64(uint32_t field_id_size, int64_t value)
Calculates and adds the size of an int64 field to the total message size.
Definition proto.h:636
void add_bool(uint32_t field_id_size, bool value)
Calculates and adds the size of a boolean field to the total message size.
Definition proto.h:559
uint32_t get_size() const
Definition proto.h:409
void add_uint32(uint32_t field_id_size, uint32_t value)
Calculates and adds the size of a uint32 field to the total message size.
Definition proto.h:542
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:441
void add_repeated_message(uint32_t field_id_size, const std::vector< MessageType > &messages)
Calculates and adds the sizes of all messages in a repeated field to the total message size.
Definition proto.h:768
void add_uint64(uint32_t field_id_size, uint64_t value)
Calculates and adds the size of a uint64 field to the total message size.
Definition proto.h:653
void add_length_force(uint32_t field_id_size, size_t len)
Calculates and adds the size of a length-delimited field (string/bytes) to the total message size (re...
Definition proto.h:683
void add_int32(uint32_t field_id_size, int32_t value)
Common parameters for all add_*_field methods.
Definition proto.h:524
void add_precalculated_size(uint32_t size)
Adds a pre-calculated size directly to the total.
Definition proto.h:697
void add_sint32_force(uint32_t field_id_size, int32_t value)
Calculates and adds the size of a sint32 field to the total message size (force version)
Definition proto.h:627
void add_uint64_force(uint32_t field_id_size, uint64_t value)
Calculates and adds the size of a uint64 field to the total message size (force version)
Definition proto.h:662
void add_fixed32(uint32_t field_id_size, uint32_t value)
Calculates and adds the size of a fixed32 field to the total message size.
Definition proto.h:590
ProtoSize()=default
ProtoSize class for Protocol Buffer serialization size calculation.
void add_length(uint32_t field_id_size, size_t len)
Calculates and adds the size of a length-delimited field (string/bytes) to the total message size.
Definition proto.h:673
Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit.
Definition proto.h:73
constexpr uint16_t as_uint16() const
Definition proto.h:114
constexpr uint64_t as_uint64() const
Definition proto.h:116
constexpr int32_t as_int32() const
Definition proto.h:118
void encode_to_buffer_unchecked(uint8_t *buffer, size_t len)
Encode the varint value to a pre-allocated buffer without bounds checking.
Definition proto.h:145
void encode(std::vector< uint8_t > &out)
Definition proto.h:162
constexpr uint32_t as_uint32() const
Definition proto.h:115
constexpr int64_t as_int64() const
Definition proto.h:122
constexpr bool as_bool() const
Definition proto.h:117
ProtoVarInt(uint64_t value)
Definition proto.h:76
constexpr int32_t as_sint32() const
Definition proto.h:126
constexpr int64_t as_sint64() const
Definition proto.h:130
static optional< ProtoVarInt > parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed)
Definition proto.h:78
void encode_varint_raw(uint32_t value)
Definition proto.h:237
void encode_string(uint32_t field_id, const std::string &value, bool force=false)
Definition proto.h:268
void write(uint8_t value)
Definition proto.h:235
void encode_int64(uint32_t field_id, int64_t value, bool force=false)
Definition proto.h:328
void encode_float(uint32_t field_id, float value, bool force=false)
Definition proto.h:309
void encode_int32(uint32_t field_id, int32_t value, bool force=false)
Definition proto.h:320
void encode_sint64(uint32_t field_id, int64_t value, bool force=false)
Definition proto.h:334
void encode_string(uint32_t field_id, const char *string, size_t len, bool force=false)
Definition proto.h:254
void encode_bool(uint32_t field_id, bool value, bool force=false)
Definition proto.h:289
ProtoWriteBuffer(std::vector< uint8_t > *buffer)
Definition proto.h:234
void encode_uint64(uint32_t field_id, uint64_t value, bool force=false)
Definition proto.h:283
void encode_string(uint32_t field_id, const StringRef &ref, bool force=false)
Definition proto.h:271
void encode_uint32(uint32_t field_id, uint32_t value, bool force=false)
Definition proto.h:277
void encode_sint32(uint32_t field_id, int32_t value, bool force=false)
Definition proto.h:331
void encode_field_raw(uint32_t field_id, uint32_t type)
Encode a field key (tag/wire type combination).
Definition proto.h:250
void encode_message(uint32_t field_id, const ProtoMessage &value, bool force=false)
Definition proto.h:798
std::vector< uint8_t > * get_buffer() const
Definition proto.h:338
void encode_bytes(uint32_t field_id, const uint8_t *data, size_t len, bool force=false)
Definition proto.h:274
void encode_fixed32(uint32_t field_id, uint32_t value, bool force=false)
Definition proto.h:295
void encode_varint_raw(ProtoVarInt value)
Definition proto.h:236
std::vector< uint8_t > * buffer_
Definition proto.h:341
const char * message
Definition component.cpp:38
uint16_t type
mopeka_std_values val[4]
constexpr uint32_t encode_zigzag32(int32_t value)
Definition proto.h:26
constexpr uint8_t WIRE_TYPE_VARINT
Definition proto.h:20
const char * proto_enum_to_string(T value)
constexpr uint64_t encode_zigzag64(int64_t value)
Definition proto.h:30
constexpr uint8_t WIRE_TYPE_MASK
Definition proto.h:23
constexpr uint8_t WIRE_TYPE_LENGTH_DELIMITED
Definition proto.h:21
constexpr int32_t decode_zigzag32(uint32_t value)
Definition proto.h:34
constexpr uint8_t WIRE_TYPE_FIXED32
Definition proto.h:22
constexpr int64_t decode_zigzag64(uint64_t value)
Definition proto.h:38
std::string size_t len
Definition helpers.h:500
uint16_t length
Definition tt21100.cpp:0