ESPHome  2024.4.1
proto.cpp
Go to the documentation of this file.
1 #include "proto.h"
2 #include <cinttypes>
3 #include "esphome/core/log.h"
4 
5 namespace esphome {
6 namespace api {
7 
8 static const char *const TAG = "api.proto";
9 
10 void ProtoMessage::decode(const uint8_t *buffer, size_t length) {
11  uint32_t i = 0;
12  bool error = false;
13  while (i < length) {
14  uint32_t consumed;
15  auto res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
16  if (!res.has_value()) {
17  ESP_LOGV(TAG, "Invalid field start at %" PRIu32, i);
18  break;
19  }
20 
21  uint32_t field_type = (res->as_uint32()) & 0b111;
22  uint32_t field_id = (res->as_uint32()) >> 3;
23  i += consumed;
24 
25  switch (field_type) {
26  case 0: { // VarInt
27  res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
28  if (!res.has_value()) {
29  ESP_LOGV(TAG, "Invalid VarInt at %" PRIu32, i);
30  error = true;
31  break;
32  }
33  if (!this->decode_varint(field_id, *res)) {
34  ESP_LOGV(TAG, "Cannot decode VarInt field %" PRIu32 " with value %" PRIu32 "!", field_id, res->as_uint32());
35  }
36  i += consumed;
37  break;
38  }
39  case 2: { // Length-delimited
40  res = ProtoVarInt::parse(&buffer[i], length - i, &consumed);
41  if (!res.has_value()) {
42  ESP_LOGV(TAG, "Invalid Length Delimited at %" PRIu32, i);
43  error = true;
44  break;
45  }
46  uint32_t field_length = res->as_uint32();
47  i += consumed;
48  if (field_length > length - i) {
49  ESP_LOGV(TAG, "Out-of-bounds Length Delimited at %" PRIu32, i);
50  error = true;
51  break;
52  }
53  if (!this->decode_length(field_id, ProtoLengthDelimited(&buffer[i], field_length))) {
54  ESP_LOGV(TAG, "Cannot decode Length Delimited field %" PRIu32 "!", field_id);
55  }
56  i += field_length;
57  break;
58  }
59  case 5: { // 32-bit
60  if (length - i < 4) {
61  ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at %" PRIu32, i);
62  error = true;
63  break;
64  }
65  uint32_t val = encode_uint32(buffer[i + 3], buffer[i + 2], buffer[i + 1], buffer[i]);
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  i += 4;
70  break;
71  }
72  default:
73  ESP_LOGV(TAG, "Invalid field type at %" PRIu32, i);
74  error = true;
75  break;
76  }
77  if (error) {
78  break;
79  }
80  }
81 }
82 
83 #ifdef HAS_PROTO_MESSAGE_DUMP
84 std::string ProtoMessage::dump() const {
85  std::string out;
86  this->dump_to(out);
87  return out;
88 }
89 #endif
90 
91 } // namespace api
92 } // namespace esphome
virtual bool decode_32bit(uint32_t field_id, Proto32Bit value)
Definition: proto.h:287
virtual bool decode_varint(uint32_t field_id, ProtoVarInt value)
Definition: proto.h:285
static optional< ProtoVarInt > parse(const uint8_t *buffer, uint32_t len, uint32_t *consumed)
Definition: proto.h:22
std::string dump() const
Definition: proto.cpp:84
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:186
void decode(const uint8_t *buffer, size_t length)
Definition: proto.cpp:10
mopeka_std_values val[4]
virtual void dump_to(std::string &out) const =0
virtual bool decode_length(uint32_t field_id, ProtoLengthDelimited value)
Definition: proto.h:286
uint16_t length
Definition: tt21100.cpp:12
This is a workaround until we can figure out a way to get the tflite-micro idf component code availab...
Definition: a01nyub.cpp:7