diff --git a/esphome/components/api/api_pb2.h b/esphome/components/api/api_pb2.h index a4ee0adb8b..86289a28d6 100644 --- a/esphome/components/api/api_pb2.h +++ b/esphome/components/api/api_pb2.h @@ -1253,7 +1253,7 @@ class ExecuteServiceArgument final : public ProtoDecodableMessage { FixedVector int_array{}; FixedVector float_array{}; FixedVector string_array{}; - void decode(const uint8_t *buffer, size_t length) override; + void decode(const uint8_t *buffer, size_t length); #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif @@ -1278,7 +1278,7 @@ class ExecuteServiceRequest final : public ProtoDecodableMessage { #ifdef USE_API_USER_DEFINED_ACTION_RESPONSES bool return_response{false}; #endif - void decode(const uint8_t *buffer, size_t length) override; + void decode(const uint8_t *buffer, size_t length); #ifdef HAS_PROTO_MESSAGE_DUMP const char *dump_to(DumpBuffer &out) const override; #endif diff --git a/esphome/components/api/proto.h b/esphome/components/api/proto.h index cc1d1f1549..a63f53adb4 100644 --- a/esphome/components/api/proto.h +++ b/esphome/components/api/proto.h @@ -152,8 +152,7 @@ class ProtoVarInt { #endif }; -// Forward declarations for decode_to_message and related encoding helpers -class ProtoDecodableMessage; +// Forward declarations for encoding helpers class ProtoMessage; class ProtoSize; @@ -166,16 +165,9 @@ class ProtoLengthDelimited { const uint8_t *data() const { return this->value_; } size_t size() const { return this->length_; } - /** - * Decode the length-delimited data into an existing ProtoDecodableMessage instance. - * - * This method allows decoding without templates, enabling use in contexts - * where the message type is not known at compile time. The ProtoDecodableMessage's - * decode() method will be called with the raw data and length. - * - * @param msg The ProtoDecodableMessage instance to decode into - */ - void decode_to_message(ProtoDecodableMessage &msg) const; + /// Decode the length-delimited data into a message instance. + /// Template preserves concrete type so decode() resolves statically. + template void decode_to_message(T &msg) const; protected: const uint8_t *const value_; @@ -454,7 +446,7 @@ class ProtoMessage { // Base class for messages that support decoding class ProtoDecodableMessage : public ProtoMessage { public: - virtual void decode(const uint8_t *buffer, size_t length); + void decode(const uint8_t *buffer, size_t length); /** * Count occurrences of a repeated field in a protobuf buffer. @@ -690,8 +682,8 @@ template inline void ProtoWriteBuffer::encode_optional_sub_message(u this->encode_optional_sub_message(field_id, value.calculate_size(), &value, &proto_encode_msg); } -// Implementation of decode_to_message - must be after ProtoDecodableMessage is defined -inline void ProtoLengthDelimited::decode_to_message(ProtoDecodableMessage &msg) const { +// Template decode_to_message - preserves concrete type so decode() resolves statically +template void ProtoLengthDelimited::decode_to_message(T &msg) const { msg.decode(this->value_, this->length_); } diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index e4e0632542..1e0e872270 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -2262,7 +2262,7 @@ def build_message_type( o += "}\n" cpp += o # Generate the decode() declaration in header (public method) - prot = "void decode(const uint8_t *buffer, size_t length) override;" + prot = "void decode(const uint8_t *buffer, size_t length);" public_content.append(prot) # Only generate encode method if this message needs encoding and has fields