This commit is contained in:
J. Nick Koston 2025-07-10 05:09:57 -10:00
parent ab4a21e84d
commit 6b0391a1f9
No known key found for this signature in database
5 changed files with 810 additions and 151 deletions

File diff suppressed because it is too large Load Diff

View File

@ -162,69 +162,69 @@ void encode_bytes_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t
} }
// Type-specific size calculation functions // Type-specific size calculation functions
void size_string_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_string_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *str = static_cast<const std::string *>(field_ptr); const auto *str = static_cast<const std::string *>(field_ptr);
ProtoSize::add_string_field(total_size, field_num, *str, force); ProtoSize::add_string_field(total_size, precalced_field_tag_size, *str, force);
} }
void size_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const uint32_t *>(field_ptr); const auto *val = static_cast<const uint32_t *>(field_ptr);
ProtoSize::add_fixed_field<4>(total_size, field_num, *val != 0 || force, force); ProtoSize::add_fixed_field<4>(total_size, precalced_field_tag_size, *val != 0 || force, force);
} }
void size_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const bool *>(field_ptr); const auto *val = static_cast<const bool *>(field_ptr);
ProtoSize::add_bool_field(total_size, field_num, *val, force); ProtoSize::add_bool_field(total_size, precalced_field_tag_size, *val, force);
} }
void size_float_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_float_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const float *>(field_ptr); const auto *val = static_cast<const float *>(field_ptr);
ProtoSize::add_fixed_field<4>(total_size, field_num, *val != 0.0f || force, force); ProtoSize::add_fixed_field<4>(total_size, precalced_field_tag_size, *val != 0.0f || force, force);
} }
void size_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const int32_t *>(field_ptr); const auto *val = static_cast<const int32_t *>(field_ptr);
ProtoSize::add_int32_field(total_size, field_num, *val, force); ProtoSize::add_int32_field(total_size, precalced_field_tag_size, *val, force);
} }
void size_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const uint32_t *>(field_ptr); const auto *val = static_cast<const uint32_t *>(field_ptr);
ProtoSize::add_uint32_field(total_size, field_num, *val, force); ProtoSize::add_uint32_field(total_size, precalced_field_tag_size, *val, force);
} }
void size_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const int64_t *>(field_ptr); const auto *val = static_cast<const int64_t *>(field_ptr);
ProtoSize::add_int64_field(total_size, field_num, *val, force); ProtoSize::add_int64_field(total_size, precalced_field_tag_size, *val, force);
} }
void size_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const uint64_t *>(field_ptr); const auto *val = static_cast<const uint64_t *>(field_ptr);
ProtoSize::add_uint64_field(total_size, field_num, *val, force); ProtoSize::add_uint64_field(total_size, precalced_field_tag_size, *val, force);
} }
void size_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const int32_t *>(field_ptr); const auto *val = static_cast<const int32_t *>(field_ptr);
ProtoSize::add_sint32_field(total_size, field_num, *val, force); ProtoSize::add_sint32_field(total_size, precalced_field_tag_size, *val, force);
} }
void size_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const int64_t *>(field_ptr); const auto *val = static_cast<const int64_t *>(field_ptr);
ProtoSize::add_sint64_field(total_size, field_num, *val, force); ProtoSize::add_sint64_field(total_size, precalced_field_tag_size, *val, force);
} }
void size_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const uint64_t *>(field_ptr); const auto *val = static_cast<const uint64_t *>(field_ptr);
ProtoSize::add_fixed_field<8>(total_size, field_num, *val != 0 || force, force); ProtoSize::add_fixed_field<8>(total_size, precalced_field_tag_size, *val != 0 || force, force);
} }
void size_double_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_double_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const double *>(field_ptr); const auto *val = static_cast<const double *>(field_ptr);
ProtoSize::add_fixed_field<8>(total_size, field_num, *val != 0.0 || force, force); ProtoSize::add_fixed_field<8>(total_size, precalced_field_tag_size, *val != 0.0 || force, force);
} }
void size_bytes_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { void size_bytes_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *str = static_cast<const std::string *>(field_ptr); const auto *str = static_cast<const std::string *>(field_ptr);
ProtoSize::add_string_field(total_size, field_num, *str, force); ProtoSize::add_string_field(total_size, precalced_field_tag_size, *str, force);
} }
// Type-specific decode functions // Type-specific decode functions
@ -401,99 +401,91 @@ void encode_repeated_double_field(ProtoWriteBuffer &buffer, const void *field_pt
// Template repeated field functions moved to header // Template repeated field functions moved to header
// Repeated field size calculation functions // Repeated field size calculation functions
void size_repeated_string_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_string_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<std::string> *>(field_ptr); const auto *vec = static_cast<const std::vector<std::string> *>(field_ptr);
for (const auto &item : *vec) { for (const auto &item : *vec) {
ProtoSize::add_string_field(total_size, field_num, item, true); ProtoSize::add_string_field(total_size, precalced_field_tag_size, item, true);
} }
} }
void size_repeated_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<bool> *>(field_ptr); const auto *vec = static_cast<const std::vector<bool> *>(field_ptr);
for (bool val : *vec) { for (bool val : *vec) {
ProtoSize::add_bool_field(total_size, field_num, val, true); ProtoSize::add_bool_field(total_size, precalced_field_tag_size, val, true);
} }
} }
void size_repeated_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<uint32_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<uint32_t> *>(field_ptr);
for (const auto &val : *vec) { for (const auto &val : *vec) {
ProtoSize::add_uint32_field(total_size, field_num, val, true); ProtoSize::add_uint32_field(total_size, precalced_field_tag_size, val, true);
} }
} }
void size_repeated_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<int32_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<int32_t> *>(field_ptr);
for (const auto &val : *vec) { for (const auto &val : *vec) {
ProtoSize::add_int32_field(total_size, field_num, val, true); ProtoSize::add_int32_field(total_size, precalced_field_tag_size, val, true);
} }
} }
void size_repeated_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<uint64_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<uint64_t> *>(field_ptr);
for (const auto &val : *vec) { for (const auto &val : *vec) {
ProtoSize::add_uint64_field(total_size, field_num, val, true); ProtoSize::add_uint64_field(total_size, precalced_field_tag_size, val, true);
} }
} }
void size_repeated_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<int64_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<int64_t> *>(field_ptr);
for (const auto &val : *vec) { for (const auto &val : *vec) {
ProtoSize::add_int64_field(total_size, field_num, val, true); ProtoSize::add_int64_field(total_size, precalced_field_tag_size, val, true);
} }
} }
void size_repeated_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<int32_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<int32_t> *>(field_ptr);
for (const auto &val : *vec) { for (const auto &val : *vec) {
ProtoSize::add_sint32_field(total_size, field_num, val, true); ProtoSize::add_sint32_field(total_size, precalced_field_tag_size, val, true);
} }
} }
void size_repeated_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<int64_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<int64_t> *>(field_ptr);
for (const auto &val : *vec) { for (const auto &val : *vec) {
ProtoSize::add_sint64_field(total_size, field_num, val, true); ProtoSize::add_sint64_field(total_size, precalced_field_tag_size, val, true);
} }
} }
void size_repeated_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<uint32_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<uint32_t> *>(field_ptr);
size_t count = vec->size(); size_t count = vec->size();
if (count > 0) { if (count > 0) {
// Calculate proper field tag size total_size += count * (precalced_field_tag_size + 4); // field tag + 4 bytes per item
uint32_t tag_size = ProtoSize::varint(static_cast<uint32_t>((field_num << 3) | 5)); // wire type 5 for fixed32
total_size += count * (tag_size + 4); // field tag + 4 bytes per item
} }
} }
void size_repeated_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<uint64_t> *>(field_ptr); const auto *vec = static_cast<const std::vector<uint64_t> *>(field_ptr);
size_t count = vec->size(); size_t count = vec->size();
if (count > 0) { if (count > 0) {
// Calculate proper field tag size total_size += count * (precalced_field_tag_size + 8); // field tag + 8 bytes per item
uint32_t tag_size = ProtoSize::varint(static_cast<uint32_t>((field_num << 3) | 1)); // wire type 1 for fixed64
total_size += count * (tag_size + 8); // field tag + 8 bytes per item
} }
} }
void size_repeated_float_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_float_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<float> *>(field_ptr); const auto *vec = static_cast<const std::vector<float> *>(field_ptr);
size_t count = vec->size(); size_t count = vec->size();
if (count > 0) { if (count > 0) {
// Calculate proper field tag size total_size += count * (precalced_field_tag_size + 4); // field tag + 4 bytes per item
uint32_t tag_size = ProtoSize::varint(static_cast<uint32_t>((field_num << 3) | 5)); // wire type 5 for float
total_size += count * (tag_size + 4); // field tag + 4 bytes per item
} }
} }
void size_repeated_double_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { void size_repeated_double_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<double> *>(field_ptr); const auto *vec = static_cast<const std::vector<double> *>(field_ptr);
size_t count = vec->size(); size_t count = vec->size();
if (count > 0) { if (count > 0) {
// Calculate proper field tag size total_size += count * (precalced_field_tag_size + 8); // field tag + 8 bytes per item
uint32_t tag_size = ProtoSize::varint(static_cast<uint32_t>((field_num << 3) | 1)); // wire type 1 for double
total_size += count * (tag_size + 8); // field tag + 8 bytes per item
} }
} }
@ -524,13 +516,13 @@ void calculate_size_from_metadata(uint32_t &total_size, const void *obj, const F
// Calculate size for regular fields // Calculate size for regular fields
for (size_t i = 0; i < field_count; i++) { for (size_t i = 0; i < field_count; i++) {
const void *field_addr = base + fields[i].offset; const void *field_addr = base + fields[i].offset;
fields[i].sizer(total_size, field_addr, fields[i].field_num, fields[i].force_encode); fields[i].sizer(total_size, field_addr, fields[i].precalced_field_tag_size, fields[i].force_encode);
} }
// Calculate size for repeated fields // Calculate size for repeated fields
for (size_t i = 0; i < repeated_count; i++) { for (size_t i = 0; i < repeated_count; i++) {
const void *field_addr = base + repeated_fields[i].offset; const void *field_addr = base + repeated_fields[i].offset;
repeated_fields[i].sizer(total_size, field_addr, repeated_fields[i].field_num); repeated_fields[i].sizer(total_size, field_addr, repeated_fields[i].precalced_field_tag_size);
} }
} }

View File

@ -18,7 +18,7 @@ class ProtoWriteBuffer;
// Function pointer types for encoding and size calculation // Function pointer types for encoding and size calculation
using EncodeFunc = void (*)(ProtoWriteBuffer &, const void *field_ptr, uint8_t field_num); using EncodeFunc = void (*)(ProtoWriteBuffer &, const void *field_ptr, uint8_t field_num);
using SizeFunc = void (*)(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); using SizeFunc = void (*)(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
// Macro to calculate field offset without triggering -Winvalid-offsetof // Macro to calculate field offset without triggering -Winvalid-offsetof
// This uses the same approach as offsetof but with explicit reinterpret_cast // This uses the same approach as offsetof but with explicit reinterpret_cast
@ -27,14 +27,15 @@ using SizeFunc = void (*)(uint32_t &total_size, const void *field_ptr, uint8_t f
// Function pointer types for repeated fields // Function pointer types for repeated fields
using RepeatedEncodeFunc = void (*)(ProtoWriteBuffer &, const void *field_ptr, uint8_t field_num); using RepeatedEncodeFunc = void (*)(ProtoWriteBuffer &, const void *field_ptr, uint8_t field_num);
using RepeatedSizeFunc = void (*)(uint32_t &total_size, const void *field_ptr, uint8_t field_num); using RepeatedSizeFunc = void (*)(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
// Special metadata for repeated fields // Special metadata for repeated fields
struct RepeatedFieldMeta { struct RepeatedFieldMeta {
uint8_t field_num; uint8_t field_num;
uint16_t offset; uint16_t offset;
RepeatedEncodeFunc encoder; // Encoder for the entire vector RepeatedEncodeFunc encoder; // Encoder for the entire vector
RepeatedSizeFunc sizer; // Sizer for the entire vector RepeatedSizeFunc sizer; // Sizer for the entire vector
uint8_t precalced_field_tag_size; // Pre-calculated size of field tag in bytes
}; };
/// Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit /// Representation of a VarInt - in ProtoBuf should be 64bit but we only use 32bit
@ -216,12 +217,13 @@ using Decode64BitFunc = bool (*)(void *field_ptr, Proto64Bit value);
// Metadata structure describing each field // Metadata structure describing each field
struct FieldMeta { struct FieldMeta {
uint8_t field_num; // Protobuf field number (1-255) uint8_t field_num; // Protobuf field number (1-255)
uint16_t offset; // offset of field in class uint16_t offset; // offset of field in class
EncodeFunc encoder; // Function to encode this field type EncodeFunc encoder; // Function to encode this field type
SizeFunc sizer; // Function to calculate size for this field type SizeFunc sizer; // Function to calculate size for this field type
bool force_encode; // If true, encode even if value is default/empty bool force_encode; // If true, encode even if value is default/empty
uint8_t wire_type; // Wire type (0=varint, 2=length, 5=32bit, 1=64bit) uint8_t wire_type; // Wire type (0=varint, 2=length, 5=32bit, 1=64bit)
uint8_t precalced_field_tag_size; // Pre-calculated size of field tag in bytes
union { union {
DecodeVarintFunc decode_varint; DecodeVarintFunc decode_varint;
DecodeLengthFunc decode_length; DecodeLengthFunc decode_length;
@ -510,25 +512,25 @@ bool decode_bytes_field(void *field_ptr, ProtoLengthDelimited value);
template<typename EnumType> bool decode_enum_field(void *field_ptr, ProtoVarInt value); template<typename EnumType> bool decode_enum_field(void *field_ptr, ProtoVarInt value);
// Type-specific size calculation functions // Type-specific size calculation functions
void size_string_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_string_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_float_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_float_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_double_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_double_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
void size_bytes_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_bytes_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
// Template enum field functions // Template enum field functions
template<typename EnumType> void encode_enum_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num); template<typename EnumType> void encode_enum_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num);
template<typename EnumType> template<typename EnumType>
void size_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force); void size_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force);
// Repeated field handling functions // Repeated field handling functions
void encode_repeated_string_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num); void encode_repeated_string_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num);
@ -551,24 +553,24 @@ template<typename MessageType>
void encode_repeated_message_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num); void encode_repeated_message_field(ProtoWriteBuffer &buffer, const void *field_ptr, uint8_t field_num);
// Size calculation for repeated fields // Size calculation for repeated fields
void size_repeated_string_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_string_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_bool_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_uint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_int32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_uint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_int64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_sint32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_sint64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_fixed32_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_fixed64_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_float_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_float_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
void size_repeated_double_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_double_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
template<typename EnumType> template<typename EnumType>
void size_repeated_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
template<typename MessageType> template<typename MessageType>
void size_repeated_message_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num); void size_repeated_message_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size);
// Core shared functions // Core shared functions
void encode_from_metadata(ProtoWriteBuffer buffer, const void *obj, const FieldMeta *fields, size_t field_count, void encode_from_metadata(ProtoWriteBuffer buffer, const void *obj, const FieldMeta *fields, size_t field_count,

View File

@ -14,9 +14,9 @@ inline void encode_enum_field(ProtoWriteBuffer &buffer, const void *field_ptr, u
} }
template<typename EnumType> template<typename EnumType>
inline void size_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num, bool force) { inline void size_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size, bool force) {
const auto *val = static_cast<const EnumType *>(field_ptr); const auto *val = static_cast<const EnumType *>(field_ptr);
ProtoSize::add_enum_field(total_size, field_num, static_cast<uint32_t>(*val), force); ProtoSize::add_enum_field(total_size, precalced_field_tag_size, static_cast<uint32_t>(*val), force);
} }
template<typename EnumType> inline bool decode_enum_field(void *field_ptr, ProtoVarInt value) { template<typename EnumType> inline bool decode_enum_field(void *field_ptr, ProtoVarInt value) {
@ -44,17 +44,17 @@ inline void encode_repeated_message_field(ProtoWriteBuffer &buffer, const void *
// Template size functions for repeated fields (must be in header for instantiation) // Template size functions for repeated fields (must be in header for instantiation)
template<typename EnumType> template<typename EnumType>
inline void size_repeated_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { inline void size_repeated_enum_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<EnumType> *>(field_ptr); const auto *vec = static_cast<const std::vector<EnumType> *>(field_ptr);
for (const auto &val : *vec) { for (const auto &val : *vec) {
ProtoSize::add_enum_field(total_size, field_num, static_cast<uint32_t>(val), true); ProtoSize::add_enum_field(total_size, precalced_field_tag_size, static_cast<uint32_t>(val), true);
} }
} }
template<typename MessageType> template<typename MessageType>
inline void size_repeated_message_field(uint32_t &total_size, const void *field_ptr, uint8_t field_num) { inline void size_repeated_message_field(uint32_t &total_size, const void *field_ptr, uint8_t precalced_field_tag_size) {
const auto *vec = static_cast<const std::vector<MessageType> *>(field_ptr); const auto *vec = static_cast<const std::vector<MessageType> *>(field_ptr);
ProtoSize::add_repeated_message<MessageType>(total_size, field_num, *vec); ProtoSize::add_repeated_message<MessageType>(total_size, precalced_field_tag_size, *vec);
} }
} // namespace api } // namespace api

View File

@ -1211,24 +1211,25 @@ def build_message_type(
ti = RepeatedTypeInfo(field) ti = RepeatedTypeInfo(field)
encoder = get_repeated_encoder_function(ti) encoder = get_repeated_encoder_function(ti)
sizer = get_repeated_sizer_function(ti) sizer = get_repeated_sizer_function(ti)
field_tag_size = ti.calculate_field_id_size()
if encoder and sizer: if encoder and sizer:
repeated_fields.append( repeated_fields.append(
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), {encoder}, {sizer}}}" f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), {encoder}, {sizer}, {field_tag_size}}}"
) )
elif isinstance(ti._ti, EnumType): elif isinstance(ti._ti, EnumType):
# Handle enum repeated fields with template # Handle enum repeated fields with template
enum_type = ti._ti.cpp_type enum_type = ti._ti.cpp_type
repeated_fields.append( repeated_fields.append(
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), " f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
f"&encode_repeated_enum_field<{enum_type}>, &size_repeated_enum_field<{enum_type}>}}" f"&encode_repeated_enum_field<{enum_type}>, &size_repeated_enum_field<{enum_type}>, {field_tag_size}}}"
) )
elif isinstance(ti._ti, MessageType): elif isinstance(ti._ti, MessageType):
# Handle message repeated fields with template # Handle message repeated fields with template
msg_type = ti._ti.cpp_type msg_type = ti._ti.cpp_type
repeated_fields.append( repeated_fields.append(
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), " f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
f"&encode_repeated_message_field<{msg_type}>, &size_repeated_message_field<{msg_type}>}}" f"&encode_repeated_message_field<{msg_type}>, &size_repeated_message_field<{msg_type}>, {field_tag_size}}}"
) )
else: else:
ti = TYPE_INFO[field.type](field) ti = TYPE_INFO[field.type](field)
@ -1239,7 +1240,9 @@ def build_message_type(
force = "true" if field.label == 2 else "false" # Required fields force = "true" if field.label == 2 else "false" # Required fields
if encoder and sizer and decoder: if encoder and sizer and decoder:
# Format: {field_num, offset, encoder, sizer, force_encode, wire_type, {decoder}} # Calculate pre-calculated field tag size
field_tag_size = ti.calculate_field_id_size()
# Format: {field_num, offset, encoder, sizer, force_encode, wire_type, precalced_field_tag_size, {decoder}}
decoder_field = ( decoder_field = (
f".decode_varint = {decoder}" f".decode_varint = {decoder}"
if wire_type == 0 if wire_type == 0
@ -1250,14 +1253,15 @@ def build_message_type(
else f".decode_64bit = {decoder}" else f".decode_64bit = {decoder}"
) )
regular_fields.append( regular_fields.append(
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), {encoder}, {sizer}, {force}, {wire_type}, {{{decoder_field}}}}}" f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), {encoder}, {sizer}, {force}, {wire_type}, {field_tag_size}, {{{decoder_field}}}}}"
) )
elif isinstance(ti, EnumType): elif isinstance(ti, EnumType):
# Handle enum fields with template # Handle enum fields with template
enum_type = ti.cpp_type enum_type = ti.cpp_type
field_tag_size = ti.calculate_field_id_size()
regular_fields.append( regular_fields.append(
f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), " f"{{{field.number}, PROTO_FIELD_OFFSET({desc.name}, {ti.field_name}), "
f"&encode_enum_field<{enum_type}>, &size_enum_field<{enum_type}>, {force}, 0, {{.decode_varint = &decode_enum_field<{enum_type}>}}}}" f"&encode_enum_field<{enum_type}>, &size_enum_field<{enum_type}>, {force}, 0, {field_tag_size}, {{.decode_varint = &decode_enum_field<{enum_type}>}}}}"
) )
elif isinstance(ti, MessageType): elif isinstance(ti, MessageType):
# Skip nested messages for now - they need special handling # Skip nested messages for now - they need special handling