Merge remote-tracking branch 'upstream/api-enum-auto-max-value' into integration

This commit is contained in:
J. Nick Koston
2026-04-05 18:40:32 -10:00
2 changed files with 92 additions and 74 deletions
+34 -4
View File
@@ -56,6 +56,10 @@ FILE_HEADER = """// This file was automatically generated with a tool.
// See script/api_protobuf/api_protobuf.py
"""
# Populated by main() before any TypeInfo creation.
# Maps enum type name (e.g. ".BluetoothDeviceRequestType") to max enum value.
_enum_max_values: dict[str, int] = {}
def indent_list(text: str, padding: str = " ") -> list[str]:
"""Indent each line of the given text with the specified padding."""
@@ -1338,6 +1342,14 @@ class EnumType(TypeInfo):
default_value = ""
wire_type = WireType.VARINT # Uses wire type 0
@property
def max_value(self) -> int | None:
"""Get max_value from explicit annotation or auto-derive from enum definition."""
explicit = super().max_value
if explicit is not None:
return explicit
return _enum_max_values.get(self._field.type_name)
@property
def encode_func(self) -> str:
return "encode_uint32"
@@ -1360,6 +1372,9 @@ class EnumType(TypeInfo):
return f"static_cast<{self.cpp_type}>({value})"
def get_size_calculation(self, name: str, force: bool = False) -> str:
max_val = self.max_value
if max_val is not None and max_val < 128:
return self._get_single_byte_varint_size(name, force)
return self._get_simple_size_calculation(
name, force, "uint32", f"static_cast<uint32_t>({name})"
)
@@ -1918,17 +1933,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
@@ -2797,6 +2822,11 @@ def main() -> None:
file = d.file[0]
# Build enum max value map so EnumType can auto-derive max_value
for enum in file.enum_type:
if not enum.options.deprecated and enum.value:
_enum_max_values[f".{enum.name}"] = max(v.number for v in enum.value)
# Build dynamic ifdef mappings early so we can emit USE_API_VARINT64 before includes
enum_ifdef_map, message_ifdef_map, message_source_map, used_messages = (
build_type_usage_map(file)