mirror of
https://github.com/esphome/esphome.git
synced 2026-09-21 12:08:38 +00:00
[api] Add 48-bit MAC address varint fast path for BLE advertisements
Adds a (mac_address) field option that switches uint64 fields holding 48-bit MAC addresses to a specialized varint encoder. The fast path emits exactly 7 bytes when bits [42..47] are non-zero (the common case for real MACs, since OUIs occupy the top 24 bits) -- one bounds check and 7 independent stores instead of the 7-iteration shift+branch loop. calc_uint64_48bit_force mirrors the same fast path in size calculation. Applied to BluetoothLERawAdvertisement.address, the per-advertisement address encode in BluetoothLERawAdvertisementsResponse drops from a serialized per-byte loop to straight-line code.
This commit is contained in:
@@ -184,6 +184,11 @@ class TypeInfo(ABC):
|
||||
"""Check if this field should always be encoded (skip zero/empty check)."""
|
||||
return get_field_opt(self._field, pb.force, False)
|
||||
|
||||
@property
|
||||
def mac_address(self) -> bool:
|
||||
"""Check if this uint64 field is a 48-bit MAC address (use 7-byte fast path)."""
|
||||
return get_field_opt(self._field, pb.mac_address, False)
|
||||
|
||||
@property
|
||||
def max_value(self) -> int | None:
|
||||
"""Get the max_value option for this field, or None if not set."""
|
||||
@@ -665,8 +670,22 @@ class UInt64Type(VarintTypeMixin, TypeInfo):
|
||||
return o
|
||||
|
||||
def get_size_calculation(self, name: str, force: bool = False) -> str:
|
||||
if self.mac_address and force:
|
||||
field_id_size = self.calculate_field_id_size()
|
||||
return (
|
||||
f"size += ProtoSize::calc_uint64_48bit_force({field_id_size}, {name});"
|
||||
)
|
||||
return self._get_simple_size_calculation(name, force, "uint64")
|
||||
|
||||
@property
|
||||
def RAW_ENCODE_MAP(self) -> dict[str, str]: # noqa: N802
|
||||
if self.mac_address:
|
||||
return {
|
||||
**TypeInfo.RAW_ENCODE_MAP,
|
||||
"encode_uint64": "ProtoEncode::encode_varint_raw_48bit(pos, {value});",
|
||||
}
|
||||
return TypeInfo.RAW_ENCODE_MAP
|
||||
|
||||
def get_estimated_size(self) -> int:
|
||||
return self.calculate_field_id_size() + 3 # field ID + 3 bytes typical varint
|
||||
|
||||
|
||||
Reference in New Issue
Block a user