ESPHome 2025.9.0
Loading...
Searching...
No Matches
proto.cpp
Go to the documentation of this file.
1#include "proto.h"
2#include <cinttypes>
4#include "esphome/core/log.h"
5
6namespace esphome::api {
7
8static const char *const TAG = "api.proto";
9
10void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) {
11 const uint8_t *ptr = buffer;
12 const uint8_t *end = buffer + length;
13
14 while (ptr < end) {
15 uint32_t consumed;
16
17 // Parse field header
18 auto res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
19 if (!res.has_value()) {
20 ESP_LOGV(TAG, "Invalid field start at offset %ld", (long) (ptr - buffer));
21 return;
22 }
23
24 uint32_t tag = res->as_uint32();
25 uint32_t field_type = tag & 0b111;
26 uint32_t field_id = tag >> 3;
27 ptr += consumed;
28
29 switch (field_type) {
30 case 0: { // VarInt
31 res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
32 if (!res.has_value()) {
33 ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer));
34 return;
35 }
36 if (!this->decode_varint(field_id, *res)) {
37 ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32());
38 }
39 ptr += consumed;
40 break;
41 }
42 case 2: { // Length-delimited
43 res = ProtoVarInt::parse(ptr, end - ptr, &consumed);
44 if (!res.has_value()) {
45 ESP_LOGV(TAG, "Invalid Length Delimited at offset %ld", (long) (ptr - buffer));
46 return;
47 }
48 uint32_t field_length = res->as_uint32();
49 ptr += consumed;
50 if (ptr + field_length > end) {
51 ESP_LOGV(TAG, "Out-of-bounds Length Delimited at offset %ld", (long) (ptr - buffer));
52 return;
53 }
54 if (!this->decode_length(field_id, ProtoLengthDelimited(ptr, field_length))) {
55 ESP_LOGV(TAG, "Cannot decode Length Delimited field %" PRIu32 "!", field_id);
56 }
57 ptr += field_length;
58 break;
59 }
60 case 5: { // 32-bit
61 if (ptr + 4 > end) {
62 ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer));
63 return;
64 }
65 uint32_t val = encode_uint32(ptr[3], ptr[2], ptr[1], ptr[0]);
66 if (!this->decode_32bit(field_id, Proto32Bit(val))) {
67 ESP_LOGV(TAG, "Cannot decode 32-bit field %" PRIu32 " with value %" PRIu32 "!", field_id, val);
68 }
69 ptr += 4;
70 break;
71 }
72 default:
73 ESP_LOGV(TAG, "Invalid field type %u at offset %ld", field_type, (long) (ptr - buffer));
74 return;
75 }
76 }
77}
78
79#ifdef HAS_PROTO_MESSAGE_DUMP
80std::string ProtoMessage::dump() const {
81 std::string out;
82 this->dump_to(out);
83 return out;
84}
85#endif
86
87} // namespace esphome::api
virtual bool decode_32bit(uint32_t field_id, Proto32Bit value)
Definition proto.h:358
virtual bool decode_varint(uint32_t field_id, ProtoVarInt value)
Definition proto.h:356
void decode(const uint8_t *buffer, size_t length)
Definition proto.cpp:10
virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value)
Definition proto.h:357
std::string dump() const
Definition proto.cpp:80
virtual void dump_to(std::string &out) const =0
static optional< ProtoVarInt > parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed)
Definition proto.h:71
mopeka_std_values val[4]
constexpr uint32_t encode_uint32(uint8_t byte1, uint8_t byte2, uint8_t byte3, uint8_t byte4)
Encode a 32-bit value given four bytes in most to least significant byte order.
Definition helpers.h:182
uint8_t end[39]
Definition sun_gtil2.cpp:17
uint16_t length
Definition tt21100.cpp:0