mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-31 15:12:06 +00:00 
			
		
		
		
	Merge branch 'integration' into memory_api
This commit is contained in:
		| @@ -22,7 +22,7 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     uint32_t tag = res->as_uint32(); |     uint32_t tag = res->as_uint32(); | ||||||
|     uint32_t field_type = tag & 0b111; |     uint32_t field_type = tag & WIRE_TYPE_MASK; | ||||||
|     uint32_t field_id = tag >> 3; |     uint32_t field_id = tag >> 3; | ||||||
|     ptr += consumed; |     ptr += consumed; | ||||||
|  |  | ||||||
| @@ -33,7 +33,7 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size | |||||||
|  |  | ||||||
|     // Skip field data based on wire type |     // Skip field data based on wire type | ||||||
|     switch (field_type) { |     switch (field_type) { | ||||||
|       case 0: {  // VarInt - parse and skip |       case WIRE_TYPE_VARINT: {  // VarInt - parse and skip | ||||||
|         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); |         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); | ||||||
|         if (!res.has_value()) { |         if (!res.has_value()) { | ||||||
|           return count;  // Invalid data, return what we have |           return count;  // Invalid data, return what we have | ||||||
| @@ -41,7 +41,7 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size | |||||||
|         ptr += consumed; |         ptr += consumed; | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       case 2: {  // Length-delimited - parse length and skip data |       case WIRE_TYPE_LENGTH_DELIMITED: {  // Length-delimited - parse length and skip data | ||||||
|         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); |         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); | ||||||
|         if (!res.has_value()) { |         if (!res.has_value()) { | ||||||
|           return count; |           return count; | ||||||
| @@ -54,7 +54,7 @@ uint32_t ProtoDecodableMessage::count_repeated_field(const uint8_t *buffer, size | |||||||
|         ptr += field_length; |         ptr += field_length; | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       case 5: {  // 32-bit - skip 4 bytes |       case WIRE_TYPE_FIXED32: {  // 32-bit - skip 4 bytes | ||||||
|         if (ptr + 4 > end) { |         if (ptr + 4 > end) { | ||||||
|           return count; |           return count; | ||||||
|         } |         } | ||||||
| @@ -85,12 +85,12 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     uint32_t tag = res->as_uint32(); |     uint32_t tag = res->as_uint32(); | ||||||
|     uint32_t field_type = tag & 0b111; |     uint32_t field_type = tag & WIRE_TYPE_MASK; | ||||||
|     uint32_t field_id = tag >> 3; |     uint32_t field_id = tag >> 3; | ||||||
|     ptr += consumed; |     ptr += consumed; | ||||||
|  |  | ||||||
|     switch (field_type) { |     switch (field_type) { | ||||||
|       case 0: {  // VarInt |       case WIRE_TYPE_VARINT: {  // VarInt | ||||||
|         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); |         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); | ||||||
|         if (!res.has_value()) { |         if (!res.has_value()) { | ||||||
|           ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer)); |           ESP_LOGV(TAG, "Invalid VarInt at offset %ld", (long) (ptr - buffer)); | ||||||
| @@ -102,7 +102,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { | |||||||
|         ptr += consumed; |         ptr += consumed; | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       case 2: {  // Length-delimited |       case WIRE_TYPE_LENGTH_DELIMITED: {  // Length-delimited | ||||||
|         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); |         res = ProtoVarInt::parse(ptr, end - ptr, &consumed); | ||||||
|         if (!res.has_value()) { |         if (!res.has_value()) { | ||||||
|           ESP_LOGV(TAG, "Invalid Length Delimited at offset %ld", (long) (ptr - buffer)); |           ESP_LOGV(TAG, "Invalid Length Delimited at offset %ld", (long) (ptr - buffer)); | ||||||
| @@ -120,7 +120,7 @@ void ProtoDecodableMessage::decode(const uint8_t *buffer, size_t length) { | |||||||
|         ptr += field_length; |         ptr += field_length; | ||||||
|         break; |         break; | ||||||
|       } |       } | ||||||
|       case 5: {  // 32-bit |       case WIRE_TYPE_FIXED32: {  // 32-bit | ||||||
|         if (ptr + 4 > end) { |         if (ptr + 4 > end) { | ||||||
|           ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer)); |           ESP_LOGV(TAG, "Out-of-bounds Fixed32-bit at offset %ld", (long) (ptr - buffer)); | ||||||
|           return; |           return; | ||||||
|   | |||||||
| @@ -15,6 +15,13 @@ | |||||||
|  |  | ||||||
| namespace esphome::api { | namespace esphome::api { | ||||||
|  |  | ||||||
|  | // Protocol Buffer wire type constants | ||||||
|  | // See https://protobuf.dev/programming-guides/encoding/#structure | ||||||
|  | constexpr uint8_t WIRE_TYPE_VARINT = 0;            // int32, int64, uint32, uint64, sint32, sint64, bool, enum | ||||||
|  | constexpr uint8_t WIRE_TYPE_LENGTH_DELIMITED = 2;  // string, bytes, embedded messages, packed repeated fields | ||||||
|  | constexpr uint8_t WIRE_TYPE_FIXED32 = 5;           // fixed32, sfixed32, float | ||||||
|  | constexpr uint8_t WIRE_TYPE_MASK = 0b111;          // Mask to extract wire type from tag | ||||||
|  |  | ||||||
| // Helper functions for ZigZag encoding/decoding | // Helper functions for ZigZag encoding/decoding | ||||||
| inline constexpr uint32_t encode_zigzag32(int32_t value) { | inline constexpr uint32_t encode_zigzag32(int32_t value) { | ||||||
|   return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31)); |   return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31)); | ||||||
| @@ -241,7 +248,7 @@ class ProtoWriteBuffer { | |||||||
|    * Following https://protobuf.dev/programming-guides/encoding/#structure |    * Following https://protobuf.dev/programming-guides/encoding/#structure | ||||||
|    */ |    */ | ||||||
|   void encode_field_raw(uint32_t field_id, uint32_t type) { |   void encode_field_raw(uint32_t field_id, uint32_t type) { | ||||||
|     uint32_t val = (field_id << 3) | (type & 0b111); |     uint32_t val = (field_id << 3) | (type & WIRE_TYPE_MASK); | ||||||
|     this->encode_varint_raw(val); |     this->encode_varint_raw(val); | ||||||
|   } |   } | ||||||
|   void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) { |   void encode_string(uint32_t field_id, const char *string, size_t len, bool force = false) { | ||||||
| @@ -493,7 +500,7 @@ class ProtoSize { | |||||||
|    * @return The number of bytes needed to encode the field ID and wire type |    * @return The number of bytes needed to encode the field ID and wire type | ||||||
|    */ |    */ | ||||||
|   static constexpr uint32_t field(uint32_t field_id, uint32_t type) { |   static constexpr uint32_t field(uint32_t field_id, uint32_t type) { | ||||||
|     uint32_t tag = (field_id << 3) | (type & 0b111); |     uint32_t tag = (field_id << 3) | (type & WIRE_TYPE_MASK); | ||||||
|     return varint(tag); |     return varint(tag); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,6 +11,7 @@ from typing import Any | |||||||
|  |  | ||||||
| import aioesphomeapi.api_options_pb2 as pb | import aioesphomeapi.api_options_pb2 as pb | ||||||
| import google.protobuf.descriptor_pb2 as descriptor | import google.protobuf.descriptor_pb2 as descriptor | ||||||
|  | from google.protobuf.descriptor_pb2 import FieldDescriptorProto | ||||||
|  |  | ||||||
|  |  | ||||||
| class WireType(IntEnum): | class WireType(IntEnum): | ||||||
| @@ -148,7 +149,7 @@ class TypeInfo(ABC): | |||||||
|     @property |     @property | ||||||
|     def repeated(self) -> bool: |     def repeated(self) -> bool: | ||||||
|         """Check if the field is repeated.""" |         """Check if the field is repeated.""" | ||||||
|         return self._field.label == 3 |         return self._field.label == FieldDescriptorProto.LABEL_REPEATED | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def wire_type(self) -> WireType: |     def wire_type(self) -> WireType: | ||||||
| @@ -337,7 +338,7 @@ def create_field_type_info( | |||||||
|     needs_encode: bool = True, |     needs_encode: bool = True, | ||||||
| ) -> TypeInfo: | ) -> TypeInfo: | ||||||
|     """Create the appropriate TypeInfo instance for a field, handling repeated fields and custom options.""" |     """Create the appropriate TypeInfo instance for a field, handling repeated fields and custom options.""" | ||||||
|     if field.label == 3:  # repeated |     if field.label == FieldDescriptorProto.LABEL_REPEATED: | ||||||
|         # Check if this repeated field has fixed_array_with_length_define option |         # Check if this repeated field has fixed_array_with_length_define option | ||||||
|         if ( |         if ( | ||||||
|             fixed_size := get_field_opt(field, pb.fixed_array_with_length_define) |             fixed_size := get_field_opt(field, pb.fixed_array_with_length_define) | ||||||
| @@ -1890,7 +1891,7 @@ def build_message_type( | |||||||
|         # Validate that fixed_array_size is only used in encode-only messages |         # Validate that fixed_array_size is only used in encode-only messages | ||||||
|         if ( |         if ( | ||||||
|             needs_decode |             needs_decode | ||||||
|             and field.label == 3 |             and field.label == FieldDescriptorProto.LABEL_REPEATED | ||||||
|             and get_field_opt(field, pb.fixed_array_size) is not None |             and get_field_opt(field, pb.fixed_array_size) is not None | ||||||
|         ): |         ): | ||||||
|             raise ValueError( |             raise ValueError( | ||||||
| @@ -1903,7 +1904,7 @@ def build_message_type( | |||||||
|         # Validate that fixed_array_with_length_define is only used in encode-only messages |         # Validate that fixed_array_with_length_define is only used in encode-only messages | ||||||
|         if ( |         if ( | ||||||
|             needs_decode |             needs_decode | ||||||
|             and field.label == 3 |             and field.label == FieldDescriptorProto.LABEL_REPEATED | ||||||
|             and get_field_opt(field, pb.fixed_array_with_length_define) is not None |             and get_field_opt(field, pb.fixed_array_with_length_define) is not None | ||||||
|         ): |         ): | ||||||
|             raise ValueError( |             raise ValueError( | ||||||
| @@ -1916,7 +1917,7 @@ def build_message_type( | |||||||
|         # Collect fixed_vector repeated fields for custom decode generation |         # Collect fixed_vector repeated fields for custom decode generation | ||||||
|         if ( |         if ( | ||||||
|             needs_decode |             needs_decode | ||||||
|             and field.label == 3 |             and field.label == FieldDescriptorProto.LABEL_REPEATED | ||||||
|             and get_field_opt(field, pb.fixed_vector, False) |             and get_field_opt(field, pb.fixed_vector, False) | ||||||
|         ): |         ): | ||||||
|             fixed_vector_fields.append((field.name, field.number)) |             fixed_vector_fields.append((field.name, field.number)) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user