diff --git a/esphome/components/api/api_pb2.cpp b/esphome/components/api/api_pb2.cpp index e2b9dd7b70..66623c0ab0 100644 --- a/esphome/components/api/api_pb2.cpp +++ b/esphome/components/api/api_pb2.cpp @@ -512,9 +512,7 @@ uint32_t ListEntitiesLightResponse::calculate_size() const { size += 5; size += ProtoSize::calc_length(1, this->name.size()); if (!this->supported_color_modes->empty()) { - for (const auto &it : *this->supported_color_modes) { - size += 2; - } + size += this->supported_color_modes->size() * 2; } size += ProtoSize::calc_float(1, this->min_mireds); size += ProtoSize::calc_float(1, this->max_mireds); @@ -1379,23 +1377,17 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { size += ProtoSize::calc_bool(1, this->supports_current_temperature); size += ProtoSize::calc_bool(1, this->supports_two_point_target_temperature); if (!this->supported_modes->empty()) { - for (const auto &it : *this->supported_modes) { - size += 2; - } + size += this->supported_modes->size() * 2; } size += ProtoSize::calc_float(1, this->visual_min_temperature); size += ProtoSize::calc_float(1, this->visual_max_temperature); size += ProtoSize::calc_float(1, this->visual_target_temperature_step); size += ProtoSize::calc_bool(1, this->supports_action); if (!this->supported_fan_modes->empty()) { - for (const auto &it : *this->supported_fan_modes) { - size += 2; - } + size += this->supported_fan_modes->size() * 2; } if (!this->supported_swing_modes->empty()) { - for (const auto &it : *this->supported_swing_modes) { - size += 2; - } + size += this->supported_swing_modes->size() * 2; } if (!this->supported_custom_fan_modes->empty()) { for (const char *it : *this->supported_custom_fan_modes) { @@ -1403,9 +1395,7 @@ uint32_t ListEntitiesClimateResponse::calculate_size() const { } } if (!this->supported_presets->empty()) { - for (const auto &it : *this->supported_presets) { - size += 3; - } + size += this->supported_presets->size() * 3; } if (!this->supported_custom_presets->empty()) { for (const char *it : *this->supported_custom_presets) { @@ -1598,9 +1588,7 @@ uint32_t ListEntitiesWaterHeaterResponse::calculate_size() const { size += ProtoSize::calc_float(1, this->max_temperature); size += ProtoSize::calc_float(1, this->target_temperature_step); if (!this->supported_modes->empty()) { - for (const auto &it : *this->supported_modes) { - size += 2; - } + size += this->supported_modes->size() * 2; } size += ProtoSize::calc_uint32(1, this->supported_features); return size; diff --git a/script/api_protobuf/api_protobuf.py b/script/api_protobuf/api_protobuf.py index 2f2b5f4baa..ac8845ae5f 100755 --- a/script/api_protobuf/api_protobuf.py +++ b/script/api_protobuf/api_protobuf.py @@ -1907,17 +1907,27 @@ class RepeatedTypeInfo(TypeInfo): size_expr = f"{name}->size()" if self._use_pointer else f"{name}.size()" o += f" size += {size_expr} * {bytes_per_element};\n" else: - # Other types need the actual value + # Check if inner type produces a constant size (doesn't depend on value) + inner_size = self._ti.get_size_calculation("it", True) + if "it" not in inner_size: + # Constant size per element — use multiply instead of loop + # Extract the constant from "size += N;" + const_val = ( + inner_size.strip().removeprefix("size += ").removesuffix(";") + ) + size_expr = f"{name}->size()" if self._use_pointer else f"{name}.size()" + o += f" size += {size_expr} * {const_val};\n" # Special handling for const char* elements - if self._use_pointer and "const char" in self._container_no_template: + elif self._use_pointer and "const char" in self._container_no_template: field_id_size = self.calculate_field_id_size() o += f" for (const char *it : {container_ref}) {{\n" o += f" size += ProtoSize::calc_length_force({field_id_size}, strlen(it));\n" + o += " }\n" else: auto_ref = "" if self._ti_is_bool else "&" o += f" for (const auto {auto_ref}it : {container_ref}) {{\n" - o += f" {self._ti.get_size_calculation('it', True)}\n" - o += " }\n" + o += f" {inner_size}\n" + o += " }\n" o += "}" return o