[api] Use multiply instead of loop for constant-size repeated enums

When a repeated enum field has a constant size per element (max < 128),
emit size * constant instead of iterating. This fixes unused variable
warnings from clang-tidy and generates more efficient code.
This commit is contained in:
J. Nick Koston
2026-04-05 18:29:01 -10:00
parent 0fc3664441
commit acd2fc3711
2 changed files with 20 additions and 22 deletions
+6 -18
View File
@@ -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;
+14 -4
View File
@@ -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