mirror of
https://github.com/esphome/esphome.git
synced 2026-09-30 00:10:22 +00:00
[api] Auto-derive max_value for enum fields in protobuf codegen
The protobuf code generator already parses all enum definitions and knows every enum's maximum value. Use this to automatically apply the max_value < 128 optimization to all enum fields, eliminating the need for manual annotation. Since every enum in api.proto has max < 128, all 58 enum field size calculations now use constant arithmetic instead of calling varint size functions. Builds on #15424 which introduced the max_value optimization.
This commit is contained in:
@@ -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."""
|
||||
@@ -1312,6 +1316,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"
|
||||
@@ -1334,6 +1346,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})"
|
||||
)
|
||||
@@ -2771,6 +2786,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)
|
||||
|
||||
Reference in New Issue
Block a user