File indexing completed on 2026-09-14 09:10:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
0013 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
0014
0015 #include <array>
0016 #include <atomic>
0017 #include <cstddef>
0018 #include <cstdint>
0019 #include <type_traits>
0020
0021 #include "absl/log/absl_check.h"
0022 #include "absl/types/span.h"
0023 #include "google/protobuf/arena.h"
0024 #include "google/protobuf/message_lite.h"
0025 #include "google/protobuf/parse_context.h"
0026 #include "google/protobuf/port.h"
0027 #include "google/protobuf/wire_format_lite.h"
0028
0029
0030 #include "google/protobuf/port_def.inc"
0031
0032 namespace google {
0033 namespace protobuf {
0034 namespace internal {
0035
0036
0037 struct TcFieldData {
0038 constexpr TcFieldData() : data(0) {}
0039 explicit constexpr TcFieldData(uint64_t data) : data(data) {}
0040
0041
0042 constexpr TcFieldData(uint16_t coded_tag, uint8_t hasbit_idx, uint8_t aux_idx,
0043 uint16_t offset)
0044 : data(uint64_t{offset} << 48 |
0045 uint64_t{aux_idx} << 24 |
0046 uint64_t{hasbit_idx} << 16 |
0047 uint64_t{coded_tag}) {}
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 struct DefaultInit {};
0065 TcFieldData(DefaultInit) {}
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 template <typename TagType = uint16_t>
0083 TagType coded_tag() const {
0084 return static_cast<TagType>(data);
0085 }
0086 uint8_t hasbit_idx() const { return static_cast<uint8_t>(data >> 16); }
0087 uint8_t aux_idx() const { return static_cast<uint8_t>(data >> 24); }
0088 uint16_t offset() const { return static_cast<uint16_t>(data >> 48); }
0089
0090
0091
0092 constexpr TcFieldData(uint16_t coded_tag, uint16_t nonfield_info)
0093 : data(uint64_t{nonfield_info} << 16 |
0094 uint64_t{coded_tag}) {}
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 uint16_t decoded_tag() const { return static_cast<uint16_t>(data >> 16); }
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123 uint32_t tag() const { return static_cast<uint32_t>(data); }
0124 uint32_t entry_offset() const { return static_cast<uint32_t>(data >> 32); }
0125
0126 union {
0127 uint64_t data;
0128 };
0129 };
0130
0131 struct TcParseTableBase;
0132
0133
0134 using TailCallParseFunc = PROTOBUF_CC const char* (*)(PROTOBUF_TC_PARAM_DECL);
0135
0136 namespace field_layout {
0137 struct Offset {
0138 uint32_t off;
0139 };
0140 }
0141
0142 #if defined(_MSC_VER) && !defined(_WIN64)
0143 #pragma warning(push)
0144
0145 #pragma warning(disable : 4324)
0146 #endif
0147
0148 struct FieldAuxDefaultMessage {};
0149 struct FieldAuxEnumData {};
0150
0151
0152
0153
0154 class MapTypeCard {
0155 public:
0156 MapTypeCard() = default;
0157 constexpr MapTypeCard(int number, WireFormatLite::WireType wiretype,
0158 bool is_signed, bool is_zigzag, bool is_utf8)
0159 : tag_(static_cast<uint8_t>(WireFormatLite::MakeTag(number, wiretype))),
0160 is_signed_(is_signed),
0161 is_zigzag_(is_zigzag),
0162 is_utf8_(is_utf8) {}
0163
0164 uint8_t tag() const { return tag_; }
0165
0166 WireFormatLite::WireType wiretype() const {
0167 return static_cast<WireFormatLite::WireType>(tag_ & 7);
0168 }
0169
0170 bool is_signed() const { return is_signed_; }
0171
0172 bool is_zigzag() const {
0173 ABSL_DCHECK(wiretype() == WireFormatLite::WIRETYPE_VARINT);
0174 return is_zigzag_;
0175 }
0176 bool is_utf8() const {
0177 ABSL_DCHECK(wiretype() == WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
0178 return is_utf8_;
0179 }
0180
0181 private:
0182 uint8_t tag_;
0183 bool is_signed_ : 1;
0184 bool is_zigzag_ : 1;
0185 bool is_utf8_ : 1;
0186 };
0187
0188
0189 constexpr MapTypeCard MakeMapTypeCard(int number,
0190 WireFormatLite::FieldType type) {
0191 switch (type) {
0192 case WireFormatLite::TYPE_FLOAT:
0193 return {number, WireFormatLite::WIRETYPE_FIXED32, true, false, false};
0194 case WireFormatLite::TYPE_FIXED32:
0195 return {number, WireFormatLite::WIRETYPE_FIXED32, false, false, false};
0196 case WireFormatLite::TYPE_SFIXED32:
0197 return {number, WireFormatLite::WIRETYPE_FIXED32, true, false, false};
0198
0199 case WireFormatLite::TYPE_DOUBLE:
0200 return {number, WireFormatLite::WIRETYPE_FIXED64, true, false, false};
0201 case WireFormatLite::TYPE_FIXED64:
0202 return {number, WireFormatLite::WIRETYPE_FIXED64, false, false, false};
0203 case WireFormatLite::TYPE_SFIXED64:
0204 return {number, WireFormatLite::WIRETYPE_FIXED64, true, false, false};
0205
0206 case WireFormatLite::TYPE_BOOL:
0207 return {number, WireFormatLite::WIRETYPE_VARINT, false, false, false};
0208
0209 case WireFormatLite::TYPE_ENUM:
0210
0211 return {number, WireFormatLite::WIRETYPE_VARINT, true, false, false};
0212 case WireFormatLite::TYPE_INT32:
0213 return {number, WireFormatLite::WIRETYPE_VARINT, true, false, false};
0214 case WireFormatLite::TYPE_UINT32:
0215 return {number, WireFormatLite::WIRETYPE_VARINT, false, false, false};
0216
0217 case WireFormatLite::TYPE_INT64:
0218 return {number, WireFormatLite::WIRETYPE_VARINT, true, false, false};
0219 case WireFormatLite::TYPE_UINT64:
0220 return {number, WireFormatLite::WIRETYPE_VARINT, false, false, false};
0221
0222 case WireFormatLite::TYPE_SINT32:
0223 return {number, WireFormatLite::WIRETYPE_VARINT, true, true, false};
0224 case WireFormatLite::TYPE_SINT64:
0225 return {number, WireFormatLite::WIRETYPE_VARINT, true, true, false};
0226
0227 case WireFormatLite::TYPE_STRING:
0228 return {number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, false, false,
0229 true};
0230 case WireFormatLite::TYPE_BYTES:
0231 return {number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, false, false,
0232 false};
0233
0234 case WireFormatLite::TYPE_MESSAGE:
0235 return {number, WireFormatLite::WIRETYPE_LENGTH_DELIMITED, false, false,
0236 false};
0237
0238 case WireFormatLite::TYPE_GROUP:
0239 default:
0240 Unreachable();
0241 }
0242 }
0243
0244
0245 struct MapAuxInfo {
0246 MapTypeCard key_type_card;
0247 MapTypeCard value_type_card;
0248
0249
0250 uint8_t is_supported : 1;
0251
0252
0253 uint8_t use_lite : 1;
0254
0255 uint8_t fail_on_utf8_failure : 1;
0256
0257 uint8_t log_debug_utf8_failure : 1;
0258
0259 uint8_t value_is_validated_enum : 1;
0260 };
0261 static_assert(sizeof(MapAuxInfo) <= 8, "");
0262
0263
0264 struct alignas(uint64_t) TcParseTableBase {
0265
0266 uint16_t has_bits_offset;
0267 uint16_t extension_offset;
0268 uint32_t max_field_number;
0269 uint8_t fast_idx_mask;
0270
0271
0272
0273 uint8_t has_post_loop_handler : 1;
0274 uint16_t lookup_table_offset;
0275 uint32_t skipmap32;
0276 uint32_t field_entries_offset;
0277 uint16_t num_field_entries;
0278
0279 uint16_t num_aux_entries;
0280 uint32_t aux_offset;
0281
0282 const ClassData* class_data;
0283 using PostLoopHandler = const char* (*)(MessageLite* msg, const char* ptr,
0284 ParseContext* ctx);
0285 PostLoopHandler post_loop_handler;
0286
0287
0288 TailCallParseFunc fallback;
0289
0290
0291 #ifdef PROTOBUF_PREFETCH_PARSE_TABLE
0292 const TcParseTableBase* to_prefetch;
0293 #endif
0294
0295
0296
0297
0298
0299
0300 constexpr TcParseTableBase(uint16_t has_bits_offset,
0301 uint16_t extension_offset,
0302 uint32_t max_field_number, uint8_t fast_idx_mask,
0303 uint16_t lookup_table_offset, uint32_t skipmap32,
0304 uint32_t field_entries_offset,
0305 uint16_t num_field_entries,
0306 uint16_t num_aux_entries, uint32_t aux_offset,
0307 const ClassData* class_data,
0308 PostLoopHandler post_loop_handler,
0309 TailCallParseFunc fallback
0310 #ifdef PROTOBUF_PREFETCH_PARSE_TABLE
0311 ,
0312 const TcParseTableBase* to_prefetch
0313 #endif
0314 )
0315 : has_bits_offset(has_bits_offset),
0316 extension_offset(extension_offset),
0317 max_field_number(max_field_number),
0318 fast_idx_mask(fast_idx_mask),
0319 has_post_loop_handler(post_loop_handler != nullptr),
0320 lookup_table_offset(lookup_table_offset),
0321 skipmap32(skipmap32),
0322 field_entries_offset(field_entries_offset),
0323 num_field_entries(num_field_entries),
0324 num_aux_entries(num_aux_entries),
0325 aux_offset(aux_offset),
0326 class_data(class_data),
0327 post_loop_handler(post_loop_handler),
0328 fallback(fallback)
0329 #ifdef PROTOBUF_PREFETCH_PARSE_TABLE
0330 ,
0331 to_prefetch(to_prefetch)
0332 #endif
0333 {
0334 }
0335
0336
0337 struct FastFieldEntry {
0338
0339 mutable std::atomic<TailCallParseFunc> target_atomic;
0340
0341
0342 TcFieldData bits;
0343
0344
0345 FastFieldEntry() = default;
0346
0347
0348 constexpr FastFieldEntry(TailCallParseFunc func, TcFieldData bits)
0349 : target_atomic(func), bits(bits) {}
0350
0351
0352
0353 FastFieldEntry(const FastFieldEntry& rhs) noexcept
0354 : FastFieldEntry(rhs.target(), rhs.bits) {}
0355 FastFieldEntry& operator=(const FastFieldEntry& rhs) noexcept {
0356 SetTarget(rhs.target());
0357 bits = rhs.bits;
0358 return *this;
0359 }
0360
0361
0362 TailCallParseFunc target() const {
0363 return target_atomic.load(std::memory_order_relaxed);
0364 }
0365 void SetTarget(TailCallParseFunc func) const {
0366 return target_atomic.store(func, std::memory_order_relaxed);
0367 }
0368 };
0369
0370 const FastFieldEntry* fast_entry(size_t idx) const {
0371 return reinterpret_cast<const FastFieldEntry*>(this + 1) + idx;
0372 }
0373 FastFieldEntry* fast_entry(size_t idx) {
0374 return reinterpret_cast<FastFieldEntry*>(this + 1) + idx;
0375 }
0376
0377 static uint32_t RecodeTagForFastParsing(uint32_t tag) {
0378 ABSL_DCHECK_LE(tag, 0x3FFFu);
0379
0380
0381 uint32_t hibits = tag & 0xFFFFFF80;
0382 if (hibits != 0) {
0383
0384
0385
0386
0387 tag = tag + hibits + 0x80;
0388 }
0389 return tag;
0390 }
0391
0392 static constexpr size_t kMaxFastFields = 32;
0393 static uint32_t TagToIdx(uint32_t tag, uint32_t fast_table_size) {
0394
0395 ABSL_DCHECK_EQ((fast_table_size & (fast_table_size - 1)), uint32_t{0});
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407 uint32_t idx_mask = fast_table_size - 1;
0408 return (tag >> 3) & idx_mask;
0409 }
0410
0411
0412 const uint16_t* field_lookup_begin() const {
0413 return reinterpret_cast<const uint16_t*>(reinterpret_cast<uintptr_t>(this) +
0414 lookup_table_offset);
0415 }
0416 uint16_t* field_lookup_begin() {
0417 return reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(this) +
0418 lookup_table_offset);
0419 }
0420
0421
0422 struct FieldEntry {
0423 uint32_t offset;
0424 int32_t has_idx;
0425 uint16_t aux_idx;
0426 uint16_t type_card;
0427
0428 static constexpr uint16_t kNoAuxIdx = 0xFFFF;
0429 };
0430
0431
0432 const FieldEntry* field_entries_begin() const {
0433 return reinterpret_cast<const FieldEntry*>(
0434 reinterpret_cast<uintptr_t>(this) + field_entries_offset);
0435 }
0436 absl::Span<const FieldEntry> field_entries() const {
0437 return {field_entries_begin(), num_field_entries};
0438 }
0439 FieldEntry* field_entries_begin() {
0440 return reinterpret_cast<FieldEntry*>(reinterpret_cast<uintptr_t>(this) +
0441 field_entries_offset);
0442 }
0443
0444
0445 union FieldAux {
0446 constexpr FieldAux() : message_default_p(nullptr) {}
0447 constexpr FieldAux(FieldAuxEnumData, const uint32_t* enum_data)
0448 : enum_data(enum_data) {}
0449 constexpr FieldAux(field_layout::Offset off) : offset(off.off) {}
0450 constexpr FieldAux(int32_t range_first, int32_t range_last)
0451 : enum_range{range_first, range_last} {}
0452 constexpr FieldAux(const MessageLite* msg) : message_default_p(msg) {}
0453 constexpr FieldAux(FieldAuxDefaultMessage, const void* msg)
0454 : message_default_p(msg) {}
0455 constexpr FieldAux(const TcParseTableBase* table) : table(table) {}
0456 constexpr FieldAux(MapAuxInfo map_info) : map_info(map_info) {}
0457 constexpr FieldAux(LazyEagerVerifyFnType verify_func)
0458 : verify_func(verify_func) {}
0459 struct {
0460 int32_t first;
0461 int32_t last;
0462 } enum_range;
0463 uint32_t offset;
0464 const void* message_default_p;
0465 const uint32_t* enum_data;
0466 const TcParseTableBase* table;
0467 MapAuxInfo map_info;
0468 LazyEagerVerifyFnType verify_func;
0469
0470 const MessageLite* message_default() const {
0471 return static_cast<const MessageLite*>(message_default_p);
0472 }
0473 const MessageLite* message_default_weak() const {
0474 return *static_cast<const MessageLite* const*>(message_default_p);
0475 }
0476 };
0477 const FieldAux* field_aux(uint32_t idx) const {
0478 return reinterpret_cast<const FieldAux*>(reinterpret_cast<uintptr_t>(this) +
0479 aux_offset) +
0480 idx;
0481 }
0482 FieldAux* field_aux(uint32_t idx) {
0483 return reinterpret_cast<FieldAux*>(reinterpret_cast<uintptr_t>(this) +
0484 aux_offset) +
0485 idx;
0486 }
0487 const FieldAux* field_aux(const FieldEntry* entry) const {
0488 return field_aux(entry->aux_idx);
0489 }
0490
0491
0492 const char* name_data() const {
0493 return reinterpret_cast<const char*>(reinterpret_cast<uintptr_t>(this) +
0494 aux_offset +
0495 num_aux_entries * sizeof(FieldAux));
0496 }
0497 char* name_data() {
0498 return reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(this) +
0499 aux_offset +
0500 num_aux_entries * sizeof(FieldAux));
0501 }
0502
0503 const MessageLite* default_instance() const { return class_data->prototype; }
0504 };
0505
0506 #if defined(_MSC_VER) && !defined(_WIN64)
0507 #pragma warning(pop)
0508 #endif
0509
0510 static_assert(sizeof(TcParseTableBase::FastFieldEntry) <= 16,
0511 "Fast field entry is too big.");
0512 static_assert(sizeof(TcParseTableBase::FieldEntry) <= 16,
0513 "Field entry is too big.");
0514
0515 template <size_t kFastTableSizeLog2, size_t kNumFieldEntries = 0,
0516 size_t kNumFieldAux = 0, size_t kNameTableSize = 0,
0517 size_t kFieldLookupSize = 2>
0518 struct TcParseTable {
0519 TcParseTableBase header;
0520
0521
0522
0523
0524
0525
0526
0527 std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)>
0528 fast_entries;
0529
0530
0531 std::array<uint16_t, kFieldLookupSize> field_lookup_table;
0532
0533 std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
0534 std::array<TcParseTableBase::FieldAux, kNumFieldAux> aux_entries;
0535 std::array<char, kNameTableSize == 0 ? 1 : kNameTableSize> field_names;
0536 };
0537
0538
0539
0540
0541
0542 template <size_t kFastTableSizeLog2, size_t kNumFieldEntries,
0543 size_t kNameTableSize, size_t kFieldLookupSize>
0544 struct TcParseTable<kFastTableSizeLog2, kNumFieldEntries, 0, kNameTableSize,
0545 kFieldLookupSize> {
0546 TcParseTableBase header;
0547 std::array<TcParseTableBase::FastFieldEntry, (1 << kFastTableSizeLog2)>
0548 fast_entries;
0549 std::array<uint16_t, kFieldLookupSize> field_lookup_table;
0550 std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
0551 std::array<char, kNameTableSize == 0 ? 1 : kNameTableSize> field_names;
0552 };
0553
0554
0555
0556 template <size_t kNameTableSize, size_t kFieldLookupSize>
0557 struct TcParseTable<0, 0, 0, kNameTableSize, kFieldLookupSize> {
0558 TcParseTableBase header;
0559
0560
0561 std::array<TcParseTableBase::FastFieldEntry, 1> fast_entries;
0562 std::array<uint16_t, kFieldLookupSize> field_lookup_table;
0563 std::array<char, kNameTableSize == 0 ? 1 : kNameTableSize> field_names;
0564 };
0565
0566 static_assert(std::is_standard_layout<TcParseTable<1>>::value,
0567 "TcParseTable must be standard layout.");
0568
0569 static_assert(offsetof(TcParseTable<1>, fast_entries) ==
0570 sizeof(TcParseTableBase),
0571 "Table entries must be laid out after TcParseTableBase.");
0572
0573 template <typename T,
0574 PROTOBUF_CC const char* (*func)(T*, const char*, ParseContext*)>
0575 PROTOBUF_CC const char* StubParseImpl(PROTOBUF_TC_PARAM_DECL) {
0576 return func(static_cast<T*>(msg), ptr, ctx);
0577 }
0578
0579 template <typename T,
0580 PROTOBUF_CC const char* (*func)(T*, const char*, ParseContext*)>
0581 constexpr TcParseTable<0> CreateStubTcParseTable(
0582 const ClassData* class_data,
0583 TcParseTableBase::PostLoopHandler post_loop_handler = nullptr) {
0584 return {
0585 {
0586 0,
0587 0,
0588 0,
0589 0,
0590 0,
0591 0,
0592 0,
0593 0,
0594 0,
0595 0,
0596 class_data,
0597 post_loop_handler,
0598 nullptr,
0599 #ifdef PROTOBUF_PREFETCH_PARSE_TABLE
0600 nullptr,
0601 #endif
0602 },
0603 {{{StubParseImpl<T, func>, {}}}},
0604 };
0605 }
0606
0607 }
0608 }
0609 }
0610
0611 #include "google/protobuf/port_undef.inc"
0612
0613 #endif