[api] Add force proto field option to skip zero checks on hot path (#14610)

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
J. Nick Koston
2026-03-07 18:59:13 -10:00
committed by GitHub
parent 9fea8fe01b
commit be6c3c52ac
4 changed files with 52 additions and 12 deletions

View File

@@ -1604,11 +1604,11 @@ message BluetoothLEAdvertisementResponse {
}
message BluetoothLERawAdvertisement {
uint64 address = 1;
sint32 rssi = 2;
uint64 address = 1 [(force) = true];
sint32 rssi = 2 [(force) = true];
uint32 address_type = 3;
bytes data = 4 [(fixed_array_size) = 62];
bytes data = 4 [(fixed_array_size) = 62, (force) = true];
}
message BluetoothLERawAdvertisementsResponse {

View File

@@ -90,4 +90,10 @@ extend google.protobuf.FieldOptions {
// - uint16_t <field>_length_{0};
// - uint16_t <field>_count_{0};
optional bool packed_buffer = 50015 [default=false];
// force: Always encode this field, even when its value equals the proto3 default.
// Skips the zero/empty check in calculate_size() and encode(), using the _force
// variant of the calc_ method. Use on fields that are almost always non-default
// to eliminate dead branches on hot paths.
optional bool force = 50016 [default=false];
}

View File

@@ -139,7 +139,7 @@ void DeviceInfoResponse::encode(ProtoWriteBuffer &buffer) const {
#endif
#ifdef USE_SERIAL_PROXY
for (const auto &it : this->serial_proxies) {
buffer.encode_message(25, it);
buffer.encode_sub_message(25, it);
}
#endif
}
@@ -2249,17 +2249,17 @@ bool SubscribeBluetoothLEAdvertisementsRequest::decode_varint(uint32_t field_id,
return true;
}
void BluetoothLERawAdvertisement::encode(ProtoWriteBuffer &buffer) const {
buffer.encode_uint64(1, this->address);
buffer.encode_sint32(2, this->rssi);
buffer.encode_uint64(1, this->address, true);
buffer.encode_sint32(2, this->rssi, true);
buffer.encode_uint32(3, this->address_type);
buffer.encode_bytes(4, this->data, this->data_len);
buffer.encode_bytes(4, this->data, this->data_len, true);
}
uint32_t BluetoothLERawAdvertisement::calculate_size() const {
uint32_t size = 0;
size += ProtoSize::calc_uint64(1, this->address);
size += ProtoSize::calc_sint32(1, this->rssi);
size += ProtoSize::calc_uint64_force(1, this->address);
size += ProtoSize::calc_sint32_force(1, this->rssi);
size += ProtoSize::calc_uint32(1, this->address_type);
size += ProtoSize::calc_length(1, this->data_len);
size += ProtoSize::calc_length_force(1, this->data_len);
return size;
}
void BluetoothLERawAdvertisementsResponse::encode(ProtoWriteBuffer &buffer) const {

View File

@@ -151,6 +151,11 @@ class TypeInfo(ABC):
"""Check if the field is repeated."""
return self._field.label == FieldDescriptorProto.LABEL_REPEATED
@property
def force(self) -> bool:
"""Check if this field should always be encoded (skip zero/empty check)."""
return get_field_opt(self._field, pb.force, False)
@property
def wire_type(self) -> WireType:
"""Get the wire type for the field."""
@@ -218,6 +223,8 @@ class TypeInfo(ABC):
@property
def encode_content(self) -> str:
if self.force:
return f"buffer.{self.encode_func}({self.number}, this->{self.field_name}, true);"
return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});"
encode_func = None
@@ -413,6 +420,8 @@ class DoubleType(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
if force:
return f"size += {field_id_size + self.get_fixed_size_bytes()};"
return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
@@ -437,6 +446,8 @@ class FloatType(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
if force:
return f"size += {field_id_size + self.get_fixed_size_bytes()};"
return f"size += ProtoSize::calc_float({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
@@ -521,6 +532,8 @@ class Fixed64Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
if force:
return f"size += {field_id_size + self.get_fixed_size_bytes()};"
return f"size += ProtoSize::calc_fixed64({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
@@ -545,6 +558,8 @@ class Fixed32Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
if force:
return f"size += {field_id_size + self.get_fixed_size_bytes()};"
return f"size += ProtoSize::calc_fixed32({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
@@ -607,6 +622,8 @@ class StringType(TypeInfo):
@property
def encode_content(self) -> str:
# Use the StringRef
if self.force:
return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_, true);"
return f"buffer.encode_string({self.number}, this->{self.field_name}_ref_);"
def dump(self, name):
@@ -694,7 +711,7 @@ class MessageType(TypeInfo):
@property
def encode_content(self) -> str:
# Singular message fields skip encoding when empty
# encode_sub_message always encodes (uses backpatch), no force needed
return f"buffer.{self.encode_func}({self.number}, this->{self.field_name});"
@property
@@ -771,6 +788,8 @@ class BytesType(TypeInfo):
@property
def encode_content(self) -> str:
if self.force:
return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_, true);"
return f"buffer.encode_bytes({self.number}, this->{self.field_name}_ptr_, this->{self.field_name}_len_);"
def dump(self, name: str) -> str:
@@ -876,6 +895,8 @@ class PointerToBytesBufferType(PointerToBufferTypeBase):
@property
def encode_content(self) -> str:
if self.force:
return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);"
return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);"
@property
@@ -923,6 +944,10 @@ class PointerToStringBufferType(PointerToBufferTypeBase):
@property
def encode_content(self) -> str:
if self.force:
return (
f"buffer.encode_string({self.number}, this->{self.field_name}, true);"
)
return f"buffer.encode_string({self.number}, this->{self.field_name});"
@property
@@ -1086,6 +1111,8 @@ class FixedArrayBytesType(TypeInfo):
@property
def encode_content(self) -> str:
if self.force:
return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len, true);"
return f"buffer.encode_bytes({self.number}, this->{self.field_name}, this->{self.field_name}_len);"
def dump(self, name: str) -> str:
@@ -1159,6 +1186,8 @@ class EnumType(TypeInfo):
@property
def encode_content(self) -> str:
if self.force:
return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}), true);"
return f"buffer.{self.encode_func}({self.number}, static_cast<uint32_t>(this->{self.field_name}));"
def dump(self, name: str) -> str:
@@ -1192,6 +1221,8 @@ class SFixed32Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
if force:
return f"size += {field_id_size + self.get_fixed_size_bytes()};"
return f"size += ProtoSize::calc_sfixed32({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
@@ -1216,6 +1247,8 @@ class SFixed64Type(TypeInfo):
def get_size_calculation(self, name: str, force: bool = False) -> str:
field_id_size = self.calculate_field_id_size()
if force:
return f"size += {field_id_size + self.get_fixed_size_bytes()};"
return f"size += ProtoSize::calc_sfixed64({field_id_size}, {name});"
def get_fixed_size_bytes(self) -> int:
@@ -2134,7 +2167,8 @@ def build_message_type(
encode.extend(wrap_with_ifdef(ti.encode_content, field_ifdef))
size_calc.extend(
wrap_with_ifdef(
ti.get_size_calculation(f"this->{ti.field_name}"), field_ifdef
ti.get_size_calculation(f"this->{ti.field_name}", ti.force),
field_ifdef,
)
)