mirror of
https://github.com/esphome/esphome.git
synced 2025-09-06 13:22:19 +01:00
[bluetooth_proxy] Send native 16/32-bit UUIDs instead of always converting to 128-bit
This commit is contained in:
@@ -1482,21 +1482,42 @@ message BluetoothGATTGetServicesRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
message BluetoothGATTDescriptor {
|
message BluetoothGATTDescriptor {
|
||||||
repeated uint64 uuid = 1 [(fixed_array_size) = 2];
|
repeated uint64 uuid = 1 [(fixed_array_size) = 2, (fixed_array_skip_zero) = true];
|
||||||
uint32 handle = 2;
|
uint32 handle = 2;
|
||||||
|
|
||||||
|
// New fields for efficient UUID (v1.12+)
|
||||||
|
// Only one of uuid, uuid16, or uuid32 will be set.
|
||||||
|
// uuid16/uuid32 are only used for 16/32-bit UUIDs with v1.12+ clients.
|
||||||
|
// 128-bit UUIDs always use the uuid field for backwards compatibility.
|
||||||
|
uint32 uuid16 = 3; // 16-bit UUID
|
||||||
|
uint32 uuid32 = 4; // 32-bit UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
message BluetoothGATTCharacteristic {
|
message BluetoothGATTCharacteristic {
|
||||||
repeated uint64 uuid = 1 [(fixed_array_size) = 2];
|
repeated uint64 uuid = 1 [(fixed_array_size) = 2, (fixed_array_skip_zero) = true];
|
||||||
uint32 handle = 2;
|
uint32 handle = 2;
|
||||||
uint32 properties = 3;
|
uint32 properties = 3;
|
||||||
repeated BluetoothGATTDescriptor descriptors = 4;
|
repeated BluetoothGATTDescriptor descriptors = 4;
|
||||||
|
|
||||||
|
// New fields for efficient UUID (v1.12+)
|
||||||
|
// Only one of uuid, uuid16, or uuid32 will be set.
|
||||||
|
// uuid16/uuid32 are only used for 16/32-bit UUIDs with v1.12+ clients.
|
||||||
|
// 128-bit UUIDs always use the uuid field for backwards compatibility.
|
||||||
|
uint32 uuid16 = 5; // 16-bit UUID
|
||||||
|
uint32 uuid32 = 6; // 32-bit UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
message BluetoothGATTService {
|
message BluetoothGATTService {
|
||||||
repeated uint64 uuid = 1 [(fixed_array_size) = 2];
|
repeated uint64 uuid = 1 [(fixed_array_size) = 2, (fixed_array_skip_zero) = true];
|
||||||
uint32 handle = 2;
|
uint32 handle = 2;
|
||||||
repeated BluetoothGATTCharacteristic characteristics = 3;
|
repeated BluetoothGATTCharacteristic characteristics = 3;
|
||||||
|
|
||||||
|
// New fields for efficient UUID (v1.12+)
|
||||||
|
// Only one of uuid, uuid16, or uuid32 will be set.
|
||||||
|
// uuid16/uuid32 are only used for 16/32-bit UUIDs with v1.12+ clients.
|
||||||
|
// 128-bit UUIDs always use the uuid field for backwards compatibility.
|
||||||
|
uint32 uuid16 = 4; // 16-bit UUID
|
||||||
|
uint32 uuid32 = 5; // 32-bit UUID
|
||||||
}
|
}
|
||||||
|
|
||||||
message BluetoothGATTGetServicesResponse {
|
message BluetoothGATTGetServicesResponse {
|
||||||
|
@@ -1363,7 +1363,7 @@ bool APIConnection::send_hello_response(const HelloRequest &msg) {
|
|||||||
|
|
||||||
HelloResponse resp;
|
HelloResponse resp;
|
||||||
resp.api_version_major = 1;
|
resp.api_version_major = 1;
|
||||||
resp.api_version_minor = 11;
|
resp.api_version_minor = 12;
|
||||||
// Temporary string for concatenation - will be valid during send_message call
|
// Temporary string for concatenation - will be valid during send_message call
|
||||||
std::string server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
|
std::string server_info = App.get_name() + " (esphome v" ESPHOME_VERSION ")";
|
||||||
resp.set_server_info(StringRef(server_info));
|
resp.set_server_info(StringRef(server_info));
|
||||||
|
@@ -28,6 +28,7 @@ extend google.protobuf.FieldOptions {
|
|||||||
optional string field_ifdef = 1042;
|
optional string field_ifdef = 1042;
|
||||||
optional uint32 fixed_array_size = 50007;
|
optional uint32 fixed_array_size = 50007;
|
||||||
optional bool no_zero_copy = 50008 [default=false];
|
optional bool no_zero_copy = 50008 [default=false];
|
||||||
|
optional bool fixed_array_skip_zero = 50009 [default=false];
|
||||||
|
|
||||||
// container_pointer: Zero-copy optimization for repeated fields.
|
// container_pointer: Zero-copy optimization for repeated fields.
|
||||||
//
|
//
|
||||||
|
@@ -1888,44 +1888,68 @@ bool BluetoothGATTGetServicesRequest::decode_varint(uint32_t field_id, ProtoVarI
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
void BluetoothGATTDescriptor::encode(ProtoWriteBuffer buffer) const {
|
void BluetoothGATTDescriptor::encode(ProtoWriteBuffer buffer) const {
|
||||||
|
if (!(this->uuid[0] == 0 && this->uuid[1] == 0)) {
|
||||||
buffer.encode_uint64(1, this->uuid[0], true);
|
buffer.encode_uint64(1, this->uuid[0], true);
|
||||||
buffer.encode_uint64(1, this->uuid[1], true);
|
buffer.encode_uint64(1, this->uuid[1], true);
|
||||||
|
}
|
||||||
buffer.encode_uint32(2, this->handle);
|
buffer.encode_uint32(2, this->handle);
|
||||||
|
buffer.encode_uint32(3, this->uuid16);
|
||||||
|
buffer.encode_uint32(4, this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTDescriptor::calculate_size(ProtoSize &size) const {
|
void BluetoothGATTDescriptor::calculate_size(ProtoSize &size) const {
|
||||||
|
if (!(this->uuid[0] == 0 && this->uuid[1] == 0)) {
|
||||||
size.add_uint64_force(1, this->uuid[0]);
|
size.add_uint64_force(1, this->uuid[0]);
|
||||||
size.add_uint64_force(1, this->uuid[1]);
|
size.add_uint64_force(1, this->uuid[1]);
|
||||||
|
}
|
||||||
size.add_uint32(1, this->handle);
|
size.add_uint32(1, this->handle);
|
||||||
|
size.add_uint32(1, this->uuid16);
|
||||||
|
size.add_uint32(1, this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer buffer) const {
|
void BluetoothGATTCharacteristic::encode(ProtoWriteBuffer buffer) const {
|
||||||
|
if (!(this->uuid[0] == 0 && this->uuid[1] == 0)) {
|
||||||
buffer.encode_uint64(1, this->uuid[0], true);
|
buffer.encode_uint64(1, this->uuid[0], true);
|
||||||
buffer.encode_uint64(1, this->uuid[1], true);
|
buffer.encode_uint64(1, this->uuid[1], true);
|
||||||
|
}
|
||||||
buffer.encode_uint32(2, this->handle);
|
buffer.encode_uint32(2, this->handle);
|
||||||
buffer.encode_uint32(3, this->properties);
|
buffer.encode_uint32(3, this->properties);
|
||||||
for (auto &it : this->descriptors) {
|
for (auto &it : this->descriptors) {
|
||||||
buffer.encode_message(4, it, true);
|
buffer.encode_message(4, it, true);
|
||||||
}
|
}
|
||||||
|
buffer.encode_uint32(5, this->uuid16);
|
||||||
|
buffer.encode_uint32(6, this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTCharacteristic::calculate_size(ProtoSize &size) const {
|
void BluetoothGATTCharacteristic::calculate_size(ProtoSize &size) const {
|
||||||
|
if (!(this->uuid[0] == 0 && this->uuid[1] == 0)) {
|
||||||
size.add_uint64_force(1, this->uuid[0]);
|
size.add_uint64_force(1, this->uuid[0]);
|
||||||
size.add_uint64_force(1, this->uuid[1]);
|
size.add_uint64_force(1, this->uuid[1]);
|
||||||
|
}
|
||||||
size.add_uint32(1, this->handle);
|
size.add_uint32(1, this->handle);
|
||||||
size.add_uint32(1, this->properties);
|
size.add_uint32(1, this->properties);
|
||||||
size.add_repeated_message(1, this->descriptors);
|
size.add_repeated_message(1, this->descriptors);
|
||||||
|
size.add_uint32(1, this->uuid16);
|
||||||
|
size.add_uint32(1, this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTService::encode(ProtoWriteBuffer buffer) const {
|
void BluetoothGATTService::encode(ProtoWriteBuffer buffer) const {
|
||||||
|
if (!(this->uuid[0] == 0 && this->uuid[1] == 0)) {
|
||||||
buffer.encode_uint64(1, this->uuid[0], true);
|
buffer.encode_uint64(1, this->uuid[0], true);
|
||||||
buffer.encode_uint64(1, this->uuid[1], true);
|
buffer.encode_uint64(1, this->uuid[1], true);
|
||||||
|
}
|
||||||
buffer.encode_uint32(2, this->handle);
|
buffer.encode_uint32(2, this->handle);
|
||||||
for (auto &it : this->characteristics) {
|
for (auto &it : this->characteristics) {
|
||||||
buffer.encode_message(3, it, true);
|
buffer.encode_message(3, it, true);
|
||||||
}
|
}
|
||||||
|
buffer.encode_uint32(4, this->uuid16);
|
||||||
|
buffer.encode_uint32(5, this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTService::calculate_size(ProtoSize &size) const {
|
void BluetoothGATTService::calculate_size(ProtoSize &size) const {
|
||||||
|
if (!(this->uuid[0] == 0 && this->uuid[1] == 0)) {
|
||||||
size.add_uint64_force(1, this->uuid[0]);
|
size.add_uint64_force(1, this->uuid[0]);
|
||||||
size.add_uint64_force(1, this->uuid[1]);
|
size.add_uint64_force(1, this->uuid[1]);
|
||||||
|
}
|
||||||
size.add_uint32(1, this->handle);
|
size.add_uint32(1, this->handle);
|
||||||
size.add_repeated_message(1, this->characteristics);
|
size.add_repeated_message(1, this->characteristics);
|
||||||
|
size.add_uint32(1, this->uuid16);
|
||||||
|
size.add_uint32(1, this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer buffer) const {
|
void BluetoothGATTGetServicesResponse::encode(ProtoWriteBuffer buffer) const {
|
||||||
buffer.encode_uint64(1, this->address);
|
buffer.encode_uint64(1, this->address);
|
||||||
|
@@ -1857,6 +1857,8 @@ class BluetoothGATTDescriptor : public ProtoMessage {
|
|||||||
public:
|
public:
|
||||||
std::array<uint64_t, 2> uuid{};
|
std::array<uint64_t, 2> uuid{};
|
||||||
uint32_t handle{0};
|
uint32_t handle{0};
|
||||||
|
uint32_t uuid16{0};
|
||||||
|
uint32_t uuid32{0};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
void calculate_size(ProtoSize &size) const override;
|
void calculate_size(ProtoSize &size) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
@@ -1871,6 +1873,8 @@ class BluetoothGATTCharacteristic : public ProtoMessage {
|
|||||||
uint32_t handle{0};
|
uint32_t handle{0};
|
||||||
uint32_t properties{0};
|
uint32_t properties{0};
|
||||||
std::vector<BluetoothGATTDescriptor> descriptors{};
|
std::vector<BluetoothGATTDescriptor> descriptors{};
|
||||||
|
uint32_t uuid16{0};
|
||||||
|
uint32_t uuid32{0};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
void calculate_size(ProtoSize &size) const override;
|
void calculate_size(ProtoSize &size) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
@@ -1884,6 +1888,8 @@ class BluetoothGATTService : public ProtoMessage {
|
|||||||
std::array<uint64_t, 2> uuid{};
|
std::array<uint64_t, 2> uuid{};
|
||||||
uint32_t handle{0};
|
uint32_t handle{0};
|
||||||
std::vector<BluetoothGATTCharacteristic> characteristics{};
|
std::vector<BluetoothGATTCharacteristic> characteristics{};
|
||||||
|
uint32_t uuid16{0};
|
||||||
|
uint32_t uuid32{0};
|
||||||
void encode(ProtoWriteBuffer buffer) const override;
|
void encode(ProtoWriteBuffer buffer) const override;
|
||||||
void calculate_size(ProtoSize &size) const override;
|
void calculate_size(ProtoSize &size) const override;
|
||||||
#ifdef HAS_PROTO_MESSAGE_DUMP
|
#ifdef HAS_PROTO_MESSAGE_DUMP
|
||||||
|
@@ -1561,6 +1561,8 @@ void BluetoothGATTDescriptor::dump_to(std::string &out) const {
|
|||||||
dump_field(out, "uuid", it, 4);
|
dump_field(out, "uuid", it, 4);
|
||||||
}
|
}
|
||||||
dump_field(out, "handle", this->handle);
|
dump_field(out, "handle", this->handle);
|
||||||
|
dump_field(out, "uuid16", this->uuid16);
|
||||||
|
dump_field(out, "uuid32", this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTCharacteristic::dump_to(std::string &out) const {
|
void BluetoothGATTCharacteristic::dump_to(std::string &out) const {
|
||||||
MessageDumpHelper helper(out, "BluetoothGATTCharacteristic");
|
MessageDumpHelper helper(out, "BluetoothGATTCharacteristic");
|
||||||
@@ -1574,6 +1576,8 @@ void BluetoothGATTCharacteristic::dump_to(std::string &out) const {
|
|||||||
it.dump_to(out);
|
it.dump_to(out);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
}
|
}
|
||||||
|
dump_field(out, "uuid16", this->uuid16);
|
||||||
|
dump_field(out, "uuid32", this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTService::dump_to(std::string &out) const {
|
void BluetoothGATTService::dump_to(std::string &out) const {
|
||||||
MessageDumpHelper helper(out, "BluetoothGATTService");
|
MessageDumpHelper helper(out, "BluetoothGATTService");
|
||||||
@@ -1586,6 +1590,8 @@ void BluetoothGATTService::dump_to(std::string &out) const {
|
|||||||
it.dump_to(out);
|
it.dump_to(out);
|
||||||
out.append("\n");
|
out.append("\n");
|
||||||
}
|
}
|
||||||
|
dump_field(out, "uuid16", this->uuid16);
|
||||||
|
dump_field(out, "uuid32", this->uuid32);
|
||||||
}
|
}
|
||||||
void BluetoothGATTGetServicesResponse::dump_to(std::string &out) const {
|
void BluetoothGATTGetServicesResponse::dump_to(std::string &out) const {
|
||||||
MessageDumpHelper helper(out, "BluetoothGATTGetServicesResponse");
|
MessageDumpHelper helper(out, "BluetoothGATTGetServicesResponse");
|
||||||
|
@@ -24,6 +24,13 @@ static void fill_128bit_uuid_array(std::array<uint64_t, 2> &out, esp_bt_uuid_t u
|
|||||||
((uint64_t) uuid.uuid.uuid128[1] << 8) | ((uint64_t) uuid.uuid.uuid128[0]);
|
((uint64_t) uuid.uuid.uuid128[1] << 8) | ((uint64_t) uuid.uuid.uuid128[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool supports_efficient_uuids(api::APIConnection *api_conn) {
|
||||||
|
if (!api_conn)
|
||||||
|
return false;
|
||||||
|
return api_conn->get_client_api_version_major() > 1 ||
|
||||||
|
(api_conn->get_client_api_version_major() == 1 && api_conn->get_client_api_version_minor() >= 12);
|
||||||
|
}
|
||||||
|
|
||||||
void BluetoothConnection::dump_config() {
|
void BluetoothConnection::dump_config() {
|
||||||
ESP_LOGCONFIG(TAG, "BLE Connection:");
|
ESP_LOGCONFIG(TAG, "BLE Connection:");
|
||||||
BLEClientBase::dump_config();
|
BLEClientBase::dump_config();
|
||||||
@@ -74,6 +81,9 @@ void BluetoothConnection::send_service_for_discovery_() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check if client supports efficient UUIDs
|
||||||
|
bool use_efficient_uuids = supports_efficient_uuids(api_conn);
|
||||||
|
|
||||||
// Prepare response for up to 3 services
|
// Prepare response for up to 3 services
|
||||||
api::BluetoothGATTGetServicesResponse resp;
|
api::BluetoothGATTGetServicesResponse resp;
|
||||||
resp.address = this->address_;
|
resp.address = this->address_;
|
||||||
@@ -100,7 +110,16 @@ void BluetoothConnection::send_service_for_discovery_() {
|
|||||||
this->send_service_++;
|
this->send_service_++;
|
||||||
resp.services.emplace_back();
|
resp.services.emplace_back();
|
||||||
auto &service_resp = resp.services.back();
|
auto &service_resp = resp.services.back();
|
||||||
|
|
||||||
|
if (!use_efficient_uuids || service_result.uuid.len == ESP_UUID_LEN_128) {
|
||||||
|
// Use 128-bit format for old clients or when UUID is already 128-bit
|
||||||
fill_128bit_uuid_array(service_resp.uuid, service_result.uuid);
|
fill_128bit_uuid_array(service_resp.uuid, service_result.uuid);
|
||||||
|
} else if (service_result.uuid.len == ESP_UUID_LEN_16) {
|
||||||
|
service_resp.uuid16 = service_result.uuid.uuid.uuid16;
|
||||||
|
} else if (service_result.uuid.len == ESP_UUID_LEN_32) {
|
||||||
|
service_resp.uuid32 = service_result.uuid.uuid.uuid32;
|
||||||
|
}
|
||||||
|
|
||||||
service_resp.handle = service_result.start_handle;
|
service_resp.handle = service_result.start_handle;
|
||||||
|
|
||||||
// Get the number of characteristics directly with one call
|
// Get the number of characteristics directly with one call
|
||||||
@@ -145,7 +164,16 @@ void BluetoothConnection::send_service_for_discovery_() {
|
|||||||
|
|
||||||
service_resp.characteristics.emplace_back();
|
service_resp.characteristics.emplace_back();
|
||||||
auto &characteristic_resp = service_resp.characteristics.back();
|
auto &characteristic_resp = service_resp.characteristics.back();
|
||||||
|
|
||||||
|
if (!use_efficient_uuids || char_result.uuid.len == ESP_UUID_LEN_128) {
|
||||||
|
// Use 128-bit format for old clients or when UUID is already 128-bit
|
||||||
fill_128bit_uuid_array(characteristic_resp.uuid, char_result.uuid);
|
fill_128bit_uuid_array(characteristic_resp.uuid, char_result.uuid);
|
||||||
|
} else if (char_result.uuid.len == ESP_UUID_LEN_16) {
|
||||||
|
characteristic_resp.uuid16 = char_result.uuid.uuid.uuid16;
|
||||||
|
} else if (char_result.uuid.len == ESP_UUID_LEN_32) {
|
||||||
|
characteristic_resp.uuid32 = char_result.uuid.uuid.uuid32;
|
||||||
|
}
|
||||||
|
|
||||||
characteristic_resp.handle = char_result.char_handle;
|
characteristic_resp.handle = char_result.char_handle;
|
||||||
characteristic_resp.properties = char_result.properties;
|
characteristic_resp.properties = char_result.properties;
|
||||||
char_offset++;
|
char_offset++;
|
||||||
@@ -189,7 +217,16 @@ void BluetoothConnection::send_service_for_discovery_() {
|
|||||||
|
|
||||||
characteristic_resp.descriptors.emplace_back();
|
characteristic_resp.descriptors.emplace_back();
|
||||||
auto &descriptor_resp = characteristic_resp.descriptors.back();
|
auto &descriptor_resp = characteristic_resp.descriptors.back();
|
||||||
|
|
||||||
|
if (!use_efficient_uuids || desc_result.uuid.len == ESP_UUID_LEN_128) {
|
||||||
|
// Use 128-bit format for old clients or when UUID is already 128-bit
|
||||||
fill_128bit_uuid_array(descriptor_resp.uuid, desc_result.uuid);
|
fill_128bit_uuid_array(descriptor_resp.uuid, desc_result.uuid);
|
||||||
|
} else if (desc_result.uuid.len == ESP_UUID_LEN_16) {
|
||||||
|
descriptor_resp.uuid16 = desc_result.uuid.uuid.uuid16;
|
||||||
|
} else if (desc_result.uuid.len == ESP_UUID_LEN_32) {
|
||||||
|
descriptor_resp.uuid32 = desc_result.uuid.uuid.uuid32;
|
||||||
|
}
|
||||||
|
|
||||||
descriptor_resp.handle = desc_result.handle;
|
descriptor_resp.handle = desc_result.handle;
|
||||||
desc_offset++;
|
desc_offset++;
|
||||||
}
|
}
|
||||||
|
@@ -1075,6 +1075,11 @@ class FixedArrayRepeatedType(TypeInfo):
|
|||||||
def __init__(self, field: descriptor.FieldDescriptorProto, size: int) -> None:
|
def __init__(self, field: descriptor.FieldDescriptorProto, size: int) -> None:
|
||||||
super().__init__(field)
|
super().__init__(field)
|
||||||
self.array_size = size
|
self.array_size = size
|
||||||
|
# Check if we should skip encoding when all elements are zero
|
||||||
|
# Use getattr to handle older versions of api_options_pb2
|
||||||
|
self.skip_zero = get_field_opt(
|
||||||
|
field, getattr(pb, "fixed_array_skip_zero", None), False
|
||||||
|
)
|
||||||
# Create the element type info
|
# Create the element type info
|
||||||
validate_field_type(field.type, field.name)
|
validate_field_type(field.type, field.name)
|
||||||
self._ti: TypeInfo = TYPE_INFO[field.type](field)
|
self._ti: TypeInfo = TYPE_INFO[field.type](field)
|
||||||
@@ -1113,6 +1118,18 @@ class FixedArrayRepeatedType(TypeInfo):
|
|||||||
else:
|
else:
|
||||||
return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);"
|
return f"buffer.{self._ti.encode_func}({self.number}, {element}, true);"
|
||||||
|
|
||||||
|
# If skip_zero is enabled, wrap encoding in a zero check
|
||||||
|
if self.skip_zero:
|
||||||
|
# Build the condition to check if all elements are zero
|
||||||
|
zero_checks = " && ".join(
|
||||||
|
[f"this->{self.field_name}[{i}] == 0" for i in range(self.array_size)]
|
||||||
|
)
|
||||||
|
encode_lines = [
|
||||||
|
f" {encode_element(f'this->{self.field_name}[{i}]')}"
|
||||||
|
for i in range(self.array_size)
|
||||||
|
]
|
||||||
|
return f"if (!({zero_checks})) {{\n" + "\n".join(encode_lines) + "\n}"
|
||||||
|
|
||||||
# Unroll small arrays for efficiency
|
# Unroll small arrays for efficiency
|
||||||
if self.array_size == 1:
|
if self.array_size == 1:
|
||||||
return encode_element(f"this->{self.field_name}[0]")
|
return encode_element(f"this->{self.field_name}[0]")
|
||||||
@@ -1141,6 +1158,18 @@ class FixedArrayRepeatedType(TypeInfo):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
def get_size_calculation(self, name: str, force: bool = False) -> str:
|
def get_size_calculation(self, name: str, force: bool = False) -> str:
|
||||||
|
# If skip_zero is enabled, wrap size calculation in a zero check
|
||||||
|
if self.skip_zero:
|
||||||
|
# Build the condition to check if all elements are zero
|
||||||
|
zero_checks = " && ".join(
|
||||||
|
[f"{name}[{i}] == 0" for i in range(self.array_size)]
|
||||||
|
)
|
||||||
|
size_lines = [
|
||||||
|
f" {self._ti.get_size_calculation(f'{name}[{i}]', True)}"
|
||||||
|
for i in range(self.array_size)
|
||||||
|
]
|
||||||
|
return f"if (!({zero_checks})) {{\n" + "\n".join(size_lines) + "\n}"
|
||||||
|
|
||||||
# For fixed arrays, we always encode all elements
|
# For fixed arrays, we always encode all elements
|
||||||
|
|
||||||
# Special case for single-element arrays - no loop needed
|
# Special case for single-element arrays - no loop needed
|
||||||
|
Reference in New Issue
Block a user