28 #include "absl/container/flat_hash_map.h"
29 #include "absl/container/flat_hash_set.h"
30 #include "absl/strings/ascii.h"
31 #include "absl/strings/substitute.h"
32 #include "google/protobuf/compiler/code_generator.h"
33 #include "google/protobuf/compiler/plugin.h"
34 #include "google/protobuf/descriptor.h"
35 #include "google/protobuf/descriptor.pb.h"
36 #include "google/protobuf/wire_format.h"
42 #include "upb/port_def.inc"
47 namespace protoc = ::google::protobuf::compiler;
48 namespace protobuf = ::google::protobuf;
53 inline std::vector<const google::protobuf::FieldDescriptor*> FieldHotnessOrder(
55 std::vector<const google::protobuf::FieldDescriptor*>
fields;
56 for (
int i = 0;
i <
message->field_count();
i++) {
62 return std::make_pair(!a->is_required(), a->number()) <
63 std::make_pair(!b->is_required(), b->number());
81 assert(
ext->is_extension());
83 if (
ext->extension_scope()) {
94 const char* kEnumsInit =
"enums_layout";
95 const char* kExtensionsInit =
"extensions_layout";
96 const char* kMessagesInit =
"messages_layout";
99 std::vector<const protobuf::EnumDescriptor*>* enums) {
100 enums->reserve(enums->size() +
message->enum_type_count());
101 for (
int i = 0;
i <
message->enum_type_count();
i++) {
102 enums->push_back(
message->enum_type(
i));
104 for (
int i = 0;
i <
message->nested_type_count();
i++) {
105 AddEnums(
message->nested_type(
i), enums);
109 std::vector<const protobuf::EnumDescriptor*> SortedEnums(
111 std::vector<const protobuf::EnumDescriptor*> enums;
112 enums.reserve(
file->enum_type_count());
113 for (
int i = 0;
i <
file->enum_type_count();
i++) {
114 enums.push_back(
file->enum_type(
i));
116 for (
int i = 0;
i <
file->message_type_count();
i++) {
117 AddEnums(
file->message_type(
i), &enums);
122 std::vector<int32_t> SortedUniqueEnumNumbers(
124 std::vector<int32_t>
values;
125 values.reserve(
e->value_count());
126 for (
int i = 0;
i <
e->value_count();
i++) {
127 values.push_back(
e->value(
i)->number());
136 std::vector<const protobuf::Descriptor*>* messages) {
138 for (
int i = 0;
i <
message->nested_type_count();
i++) {
139 AddMessages(
message->nested_type(
i), messages);
148 std::vector<const protobuf::Descriptor*> SortedMessages(
150 std::vector<const protobuf::Descriptor*> messages;
151 for (
int i = 0;
i <
file->message_type_count();
i++) {
152 AddMessages(
file->message_type(
i), &messages);
157 void AddExtensionsFromMessage(
159 std::vector<const protobuf::FieldDescriptor*>* exts) {
160 for (
int i = 0;
i <
message->extension_count();
i++) {
161 exts->push_back(
message->extension(
i));
163 for (
int i = 0;
i <
message->nested_type_count();
i++) {
164 AddExtensionsFromMessage(
message->nested_type(
i), exts);
173 std::vector<const protobuf::FieldDescriptor*> SortedExtensions(
175 std::vector<const protobuf::FieldDescriptor*>
ret;
176 for (
int i = 0;
i <
file->extension_count();
i++) {
179 for (
int i = 0;
i <
file->message_type_count();
i++) {
180 AddExtensionsFromMessage(
file->message_type(
i), &
ret);
185 std::vector<const protobuf::FieldDescriptor*> FieldNumberOrder(
187 std::vector<const protobuf::FieldDescriptor*>
fields;
188 for (
int i = 0;
i <
message->field_count();
i++) {
194 return a->number() < b->number();
205 std::string maybe_const = is_const ?
"const " :
"";
206 switch (
field->cpp_type()) {
209 field->file() !=
field->message_type()->file() ?
"struct " :
"";
229 return "upb_StringView";
231 fprintf(
stderr,
"Unexpected type");
237 switch (
field->cpp_type()) {
239 return "UPB_SIZE(2, 3)";
257 return "UPB_SIZE(3, 4)";
259 fprintf(
stderr,
"Unexpected type");
265 switch (
field->cpp_type()) {
269 return !
field->default_value_string().empty();
271 return field->default_value_int32() != 0;
273 return field->default_value_int64() != 0;
275 return field->default_value_uint32() != 0;
277 return field->default_value_uint64() != 0;
279 return field->default_value_float() != 0;
281 return field->default_value_double() != 0;
283 return field->default_value_bool() !=
false;
287 return field->default_value_enum()->number() != 0;
294 switch (
field->cpp_type()) {
302 field->default_value_int32());
305 field->default_value_int64());
308 field->default_value_uint32());
311 field->default_value_uint64());
317 return field->default_value_bool() ?
"true" :
"false";
328 return CTypeInternal(
field,
false);
332 return CTypeInternal(
field,
true);
341 class FilePlatformLayout {
367 void ResolveIntraFileReferences();
389 void SetSubTableStrings();
401 ExtensionMap extension_map_;
407 auto it = table_map_.find(
m);
408 assert(
it != table_map_.end());
414 auto it = extension_map_.find(fd);
415 assert(
it != extension_map_.end());
419 void FilePlatformLayout::ResolveIntraFileReferences() {
422 for (
const auto&
pair : table_map_) {
425 for (
const auto* f : FieldNumberOrder(
pair.first)) {
426 if (
f->message_type() &&
f->message_type()->file() ==
f->file()) {
442 assert((val & kMask) == 0);
454 const char*
str =
reinterpret_cast<const char*
>(as_int & ~SubTag::kMask);
455 switch (as_int & SubTag::kMask) {
456 case SubTag::kMessage:
466 void FilePlatformLayout::SetSubTableStrings() {
467 for (
const auto&
pair : table_map_) {
469 for (
const auto* f : FieldNumberOrder(
pair.first)) {
474 if (
IsNull(sub))
continue;
486 }
else if (
f->message_type()) {
487 return PackSub(AllocStr(MessageInit(
f->message_type())), SubTag::kMessage);
490 return PackSub(AllocStr(EnumInit(
f->enum_type())), SubTag::kEnum);
503 for (
const auto&
m : SortedMessages(fd)) {
504 table_map_[
m] = MakeMiniTable(
m);
506 ResolveIntraFileReferences();
507 SetSubTableStrings();
511 std::vector<const protobuf::FieldDescriptor*> sorted = SortedExtensions(fd);
513 for (
const auto* f : sorted) {
517 GetFieldModifiers(f));
524 fprintf(
stderr,
"Error building mini-table: %s\n",
529 AllocStr(MessageInit(
f->containing_type())));
530 ext.sub = PackSubForField(f, &
ext.field);
536 if (
m->options().message_set_wire_format()) {
538 }
else if (
m->options().map_entry()) {
542 m->map_value()->enum_type() &&
543 m->map_value()->enum_type()->file()->syntax() ==
547 return MakeRegularMiniTable(
m);
554 e.StartMessage(GetMessageModifiers(
m));
555 for (
const auto* f : FieldNumberOrder(
m)) {
557 GetFieldModifiers(f));
559 for (
int i = 0;
i <
m->real_oneof_decl_count();
i++) {
564 e.PutOneofField(
f->number());
572 fprintf(
stderr,
"Error building mini-table: %s\n",
status.error_message());
578 uint64_t FilePlatformLayout::GetMessageModifiers(
587 if (
m->extension_range_count() > 0) {
591 assert(!
m->options().map_entry());
595 uint64_t FilePlatformLayout::GetFieldModifiers(
602 if (
f->enum_type() &&
f->enum_type()->file()->syntax() ==
606 if (
f->is_optional() && !
f->has_presence()) {
628 return layout32_.GetMiniTable(
m);
632 return layout64_.GetMiniTable(
m);
637 GetMiniTable32(
f->containing_type()),
f->number());
639 GetMiniTable64(
f->containing_type()),
f->number());
646 GetMiniTable32(
f->containing_type()),
f->number());
648 GetMiniTable64(
f->containing_type()),
f->number());
655 GetMiniTable64(d)->
size);
660 GetMiniTable64(
f->containing_type()),
f->number());
665 return GetHasbitIndex(f) > 0;
670 return layout64_.GetExtension(f);
675 FilePlatformLayout layout32_;
676 FilePlatformLayout layout64_;
680 std::vector<const protobuf::EnumValueDescriptor*>
values;
681 for (
int i = 0;
i <
desc->value_count();
i++) {
687 return a->number() < b->number();
690 for (
size_t i = 0;
i <
values.size();
i++) {
693 if (i !=
values.size() - 1) {
704 UPB_INLINE bool $0_has_$1(const struct $2* msg) {
705 return _upb_Message_Getext(msg, &$3) != NULL;
709 ExtensionLayout(ext));
713 UPB_INLINE void $0_clear_$1(struct $2* msg) {
714 _upb_Message_Clearext(msg, &$3);
718 ExtensionLayout(ext));
720 if (
ext->is_repeated()) {
721 }
else if (
ext->message_type()) {
724 UPB_INLINE $0 $1_$2(const struct $3* msg) {
725 const upb_Message_Extension* ext = _upb_Message_Getext(msg, &$4);
727 return *UPB_PTR_AT(&ext->data, 0, $0);
730 CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
735 UPB_INLINE void $1_set_$2(struct $3* msg, $0 ext, upb_Arena* arena) {
736 const upb_Message_Extension* msg_ext =
737 _upb_Message_Getorcreateext(msg, &$4, arena);
739 *UPB_PTR_AT(&msg_ext->data, 0, $0) = ext;
742 CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
749 UPB_INLINE $0 $1_$2(const struct $3* msg) {
750 const upb_Message_Extension* ext = _upb_Message_Getext(msg, &$4);
751 return ext ? *UPB_PTR_AT(&ext->data, 0, $0) : $5;
754 CTypeConst(ext), ExtensionIdentBase(ext), ext->name(),
764 UPB_INLINE $0* $0_new(upb_Arena* arena) {
765 return ($0*)_upb_Message_New(&$1, arena);
767 UPB_INLINE $0* $0_parse(const char* buf, size_t size, upb_Arena* arena) {
768 $0* ret = $0_new(arena);
769 if (!ret) return NULL;
770 if (upb_Decode(buf, size, ret, &$1, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
775 UPB_INLINE $0* $0_parse_ex(const char* buf, size_t size,
776 const upb_ExtensionRegistry* extreg,
777 int options, upb_Arena* arena) {
778 $0* ret = $0_new(arena);
779 if (!ret) return NULL;
780 if (upb_Decode(buf, size, ret, &$1, extreg, options, arena) !=
781 kUpb_DecodeStatus_Ok) {
786 UPB_INLINE char* $0_serialize(const $0* msg, upb_Arena* arena, size_t* len) {
787 return upb_Encode(msg, &$1, 0, arena, len);
789 UPB_INLINE char* $0_serialize_ex(const $0* msg, int options,
790 upb_Arena* arena, size_t* len) {
791 return upb_Encode(msg, &$1, options, arena, len);
801 output(
"typedef enum {\n");
808 "} $0_oneofcases;\n",
812 UPB_INLINE $0_oneofcases $1_$2_case(const $1* msg) {
813 return ($0_oneofcases)*UPB_PTR_AT(msg, $3, int32_t);
816 fullname, msg_name, oneof->name(), layout.GetOneofCaseOffset(oneof));
825 UPB_INLINE bool $0_has_$1(const $0* msg) {
826 return _upb_hasbit(msg, $2);
830 } else if (
field->real_containing_oneof()) {
833 UPB_INLINE bool $0_has_$1(const $0* msg) {
834 return _upb_getoneofcase(msg, $2) == $3;
837 msg_name, field->name(),
838 layout.GetOneofCaseOffset(field->real_containing_oneof()),
840 } else if (
field->message_type()) {
843 UPB_INLINE bool $0_has_$1(const $0* msg) {
844 return _upb_has_submsg_nohasbit(msg, $2);
854 if (
field ==
field->containing_type()->map_key() ||
855 field ==
field->containing_type()->map_value()) {
860 if (
field->real_containing_oneof()) {
865 ?
"upb_StringView_FromDataAndSize(NULL, 0)"
869 UPB_INLINE void $0_clear_$1(const $0* msg) {
870 UPB_WRITE_ONEOF(msg, $2, $3, $7, $4, $6_NOT_SET);
874 layout.GetOneofCaseOffset(field->real_containing_oneof()),
875 field->number(), oneof_fullname, default_value);
877 if (
field->message_type()) {
880 UPB_INLINE void $0_clear_$1(const $0* msg) {
881 *UPB_PTR_AT(msg, $2, const upb_Message*) = NULL;
889 UPB_INLINE void $0_clear_$1(const $0* msg) {
890 *UPB_PTR_AT(msg, $3, $2) = upb_StringView_FromDataAndSize(NULL, 0);
891 _upb_clearhas(msg, $4);
899 UPB_INLINE void $0_clear_$1(const $0* msg) {
900 *UPB_PTR_AT(msg, $3, $2) = 0;
901 _upb_clearhas(msg, $4);
911 UPB_INLINE void $0_clear_$1(const $0* msg) {
912 *UPB_PTR_AT(msg, $3, $2) = upb_StringView_FromDataAndSize(NULL, 0);
920 UPB_INLINE void $0_clear_$1(const $0* msg) {
921 *UPB_PTR_AT(msg, $3, $2) = 0;
936 UPB_INLINE void $0_clear_$1(const $0* msg) {
937 _upb_array_detach(msg, $2);
951 UPB_INLINE size_t $0_$1_size(const $0* msg) {
952 return _upb_msg_map_size(msg, $2);
958 UPB_INLINE bool $0_$1_get(const $0* msg, $2 key, $3* val) {
959 return _upb_msg_map_get(msg, $4, &key, $5, val, $6);
962 msg_name, field->name(), CType(key), CType(val),
972 UPB_INLINE $0 $1_$2_next(const $1* msg, size_t* iter) {
973 return ($0)_upb_msg_map_next(msg, $3, iter);
983 UPB_INLINE $0 $1_$2(const $1* msg) {
985 _upb_msg_map_$2(msg, &ret, $4);
1000 UPB_INLINE $0 const* $1_$2(const $1* msg, size_t* len) {
1001 return ($0 const*)_upb_array_accessor(msg, $3, len);
1012 UPB_INLINE $0 $1_$2(const $1* msg) {
1013 return UPB_READ_ONEOF(msg, $0, $3, $4, $5, $6);
1017 layout.GetOneofCaseOffset(field->real_containing_oneof()),
1024 if (HasNonZeroDefault(
field)) {
1027 UPB_INLINE $0 $1_$2(const $1* msg) {
1028 return $1_has_$2(msg) ? *UPB_PTR_AT(msg, $3, $0) : $4;
1036 UPB_INLINE $0 $1_$2(const $1* msg) {
1037 return *UPB_PTR_AT(msg, $3, $0);
1048 if (
field->is_map()) {
1050 }
else if (
field->containing_type()->options().map_entry()) {
1052 }
else if (
field->is_repeated()) {
1054 }
else if (
field->real_containing_oneof()) {
1069 UPB_INLINE void $0_$1_clear($0* msg) { _upb_msg_map_clear(msg, $2); }
1074 UPB_INLINE bool $0_$1_set($0* msg, $2 key, $3 val, upb_Arena* a) {
1075 return _upb_msg_map_set(msg, $4, &key, $5, &val, $6, a);
1078 msg_name, field->name(), CType(key), CType(val),
1088 UPB_INLINE bool $0_$1_delete($0* msg, $2 key) {
1089 return _upb_msg_map_delete(msg, $3, &key, $4);
1098 UPB_INLINE $0 $1_$2_nextmutable($1* msg, size_t* iter) {
1099 return ($0)_upb_msg_map_next(msg, $3, iter);
1106 const FileLayout&
layout,
1110 UPB_INLINE $0* $1_mutable_$2($1* msg, size_t* len) {
1111 return ($0*)_upb_array_mutable_accessor(msg, $3, len);
1117 UPB_INLINE $0* $1_resize_$2($1* msg, size_t len, upb_Arena* arena) {
1118 return ($0*)_upb_Array_Resize_accessor2(msg, $3, len, $4, arena);
1126 UPB_INLINE struct $0* $1_add_$2($1* msg, upb_Arena* arena) {
1127 struct $0* sub = (struct $0*)_upb_Message_New(&$3, arena);
1128 bool ok = _upb_Array_Append_accessor2(msg, $4, $5, &sub, arena);
1129 if (!ok) return NULL;
1139 UPB_INLINE bool $1_add_$2($1* msg, $0 val, upb_Arena* arena) {
1140 return _upb_Array_Append_accessor2(msg, $3, $4, &val, arena);
1149 const FileLayout&
layout,
1151 if (
field ==
field->containing_type()->map_key()) {
1158 output(
"UPB_INLINE void $0_set_$1($0 *msg, $2 value) {\n", msg_name,
1161 if (
field ==
field->containing_type()->map_value()) {
1163 " _upb_msg_map_set_value(msg, &value, $0);\n"
1167 :
"sizeof(" + CType(
field) +
")");
1168 }
else if (
field->real_containing_oneof()) {
1170 " UPB_WRITE_ONEOF(msg, $0, $1, value, $2, $3);\n"
1173 layout.GetOneofCaseOffset(
field->real_containing_oneof()),
1180 " *UPB_PTR_AT(msg, $1, $0) = value;\n"
1188 !
field->containing_type()->options().map_entry()) {
1191 UPB_INLINE struct $0* $1_mutable_$2($1* msg, upb_Arena* arena) {
1192 struct $0* sub = (struct $0*)$1_$2(msg);
1194 sub = (struct $0*)_upb_Message_New(&$3, arena);
1195 if (!sub) return NULL;
1196 $1_set_$2(msg, sub);
1202 MessageInit(field->message_type()));
1209 if (
field->is_map()) {
1211 }
else if (
field->is_repeated()) {
1223 if (!
message->options().map_entry()) {
1227 for (
int i = 0;
i <
message->real_oneof_decl_count();
i++) {
1233 if (
field->is_repeated()) {
1250 void WriteHeader(
const FileLayout&
layout, Output&
output) {
1254 "#ifndef $0_UPB_H_\n"
1255 "#define $0_UPB_H_\n\n"
1256 "#include \"upb/msg_internal.h\"\n"
1257 "#include \"upb/decode.h\"\n"
1258 "#include \"upb/decode_fast.h\"\n"
1259 "#include \"upb/encode.h\"\n\n",
1262 for (
int i = 0;
i <
file->public_dependency_count();
i++) {
1264 output(
"/* Public Imports. */\n");
1267 if (i ==
file->public_dependency_count() - 1) {
1273 "#include \"upb/port_def.inc\"\n"
1275 "#ifdef __cplusplus\n"
1280 const std::vector<const protobuf::Descriptor*> this_file_messages =
1281 SortedMessages(
file);
1282 const std::vector<const protobuf::FieldDescriptor*> this_file_exts =
1283 SortedExtensions(
file);
1286 for (
auto message : this_file_messages) {
1289 for (
auto message : this_file_messages) {
1292 for (
auto message : this_file_messages) {
1293 output(
"extern const upb_MiniTable $0;\n", MessageInit(
message));
1295 for (
auto ext : this_file_exts) {
1296 output(
"extern const upb_MiniTable_Extension $0;\n", ExtensionLayout(
ext));
1301 std::map<std::string, const protobuf::Descriptor*> forward_messages;
1303 for (
auto*
message : this_file_messages) {
1304 for (
int i = 0;
i <
message->field_count();
i++) {
1307 field->file() !=
field->message_type()->file()) {
1308 forward_messages[
field->message_type()->full_name()] =
1309 field->message_type();
1313 for (
auto ext : this_file_exts) {
1314 if (
ext->file() !=
ext->containing_type()->file()) {
1315 forward_messages[
ext->containing_type()->full_name()] =
1316 ext->containing_type();
1319 for (
const auto&
pair : forward_messages) {
1322 for (
const auto&
pair : forward_messages) {
1323 output(
"extern const upb_MiniTable $0;\n", MessageInit(
pair.second));
1326 if (!this_file_messages.empty()) {
1330 std::vector<const protobuf::EnumDescriptor*> this_file_enums =
1333 this_file_enums.begin(), this_file_enums.end(),
1335 return a->full_name() < b->full_name();
1338 for (
auto enumdesc : this_file_enums) {
1339 output(
"typedef enum {\n");
1340 DumpEnumValues(enumdesc,
output);
1347 for (
const auto* enumdesc : this_file_enums) {
1348 output(
"extern const upb_MiniTable_Enum $0;\n", EnumInit(enumdesc));
1354 for (
auto message : this_file_messages) {
1358 for (
auto ext : this_file_exts) {
1373 for (
const auto*
message : this_file_messages) {
1377 if (size32 > max32) {
1381 if (size64 > max64) {
1390 output(
"#define _UPB_MAXOPT_SIZE UPB_SIZE($0, $1)\n\n", max32, max64);
1394 "#ifdef __cplusplus\n"
1395 "} /* extern \"C\" */\n"
1398 "#include \"upb/port_undef.inc\"\n"
1400 "#endif /* $0_UPB_H_ */\n",
1404 typedef std::pair<std::string, uint64_t> TableEntry;
1407 protobuf::internal::WireFormatLite::WireType wire_type =
1408 protobuf::internal::WireFormat::WireTypeForField(
field);
1410 protobuf::internal::WireFormatLite::MakeTag(
field->number(), wire_type);
1412 protobuf::io::CodedOutputStream::WriteVarint32ToArray(unencoded_tag,
1415 memcpy(&encoded_tag, tag_bytes,
sizeof(encoded_tag));
1426 return (
tag & 0xf8) >> 3;
1429 bool TryFillTableEntry(
const FileLayout&
layout,
1513 if (
field->is_repeated()) {
1516 if (
field->real_containing_oneof()) {
1517 size_t case_offset = ~mt_f->
presence;
1518 if (case_offset > 0xffff)
return false;
1519 assert(
field->number() < 256);
1521 data |= case_offset << 32;
1526 if (hasbit_index > 31)
return false;
1528 data |= hasbit_index << 24;
1533 if (
idx > 255)
return false;
1538 if (
field->message_type()->file() ==
field->file()) {
1547 std::vector<size_t> breaks = {64, 128, 192, 256};
1548 for (
auto brk : breaks) {
1555 expected_tag > 0xff ?
"2" :
"1", size_ceil);
1559 expected_tag > 0xff ?
"2" :
"1");
1566 const FileLayout&
layout) {
1567 std::vector<TableEntry>
table;
1570 int slot = GetTableSlot(
field);
1580 while ((
size_t)slot >=
table.size()) {
1582 table.resize(
size, TableEntry{
"fastdecode_generic", 0});
1584 if (
table[slot].
first !=
"fastdecode_generic") {
1602 ret =
"kUpb_FieldMode_Map";
1605 ret =
"kUpb_FieldMode_Array";
1608 ret =
"kUpb_FieldMode_Scalar";
1625 rep =
"kUpb_FieldRep_1Byte";
1628 rep =
"kUpb_FieldRep_4Byte";
1631 rep =
"kUpb_FieldRep_Pointer";
1634 rep =
"kUpb_FieldRep_StringView";
1637 rep =
"kUpb_FieldRep_8Byte";
1647 output(
"{$0, UPB_SIZE($1, $2), UPB_SIZE($3, $4), $5, $6, $7}",
1660 WriteField(field64, field32,
output);
1666 Output&
output,
bool fasttable_enabled) {
1673 std::vector<std::string>
subs;
1678 subs.push_back(FilePlatformLayout::GetSub(mt_64->
subs[
f->submsg_index]));
1682 if (!
subs.empty()) {
1683 std::string submsgs_array_name = msg_name +
"_submsgs";
1684 submsgs_array_ref =
"&" + submsgs_array_name +
"[0]";
1685 output(
"static const upb_MiniTable_Sub $0[$1] = {\n", submsgs_array_name,
1688 for (
const auto& sub :
subs) {
1696 std::string fields_array_name = msg_name +
"__fields";
1697 fields_array_ref =
"&" + fields_array_name +
"[0]";
1698 output(
"static const upb_MiniTable_Field $0[$1] = {\n", fields_array_name,
1706 std::vector<TableEntry>
table;
1709 if (fasttable_enabled) {
1713 if (
table.size() > 1) {
1714 assert((
table.size() & (
table.size() - 1)) == 0);
1715 table_mask = (
table.size() - 1) << 3;
1718 std::string msgext =
"kUpb_ExtMode_NonExtendable";
1720 if (
message->extension_range_count()) {
1721 if (
message->options().message_set_wire_format()) {
1722 msgext =
"kUpb_ExtMode_IsMessageSet";
1724 msgext =
"kUpb_ExtMode_Extendable";
1728 output(
"const upb_MiniTable $0 = {\n", MessageInit(
message));
1729 output(
" $0,\n", submsgs_array_ref);
1730 output(
" $0,\n", fields_array_ref);
1734 if (!
table.empty()) {
1735 output(
" UPB_FASTTABLE_INIT({\n");
1736 for (
const auto& ent :
table) {
1737 output(
" {0x$1, &$0},\n", ent.first,
1750 std::vector<const protobuf::EnumDescriptor*> this_file_enums =
1755 for (
const auto* e : this_file_enums) {
1757 std::vector<int32_t>
values;
1758 for (
auto number : SortedUniqueEnumNumbers(e)) {
1767 values_init = EnumInit(e) +
"_values";
1768 output(
"static const int32_t $0[$1] = {\n", values_init,
values.size());
1775 output(
"const upb_MiniTable_Enum $0 = {\n", EnumInit(e));
1776 output(
" $0,\n", values_init);
1783 if (!this_file_enums.empty()) {
1784 output(
"static const upb_MiniTable_Enum *$0[$1] = {\n", kEnumsInit,
1785 this_file_enums.size());
1786 for (
const auto* e : this_file_enums) {
1787 output(
" &$0,\n", EnumInit(e));
1793 return this_file_enums.size();
1796 int WriteMessages(
const FileLayout&
layout, Output&
output,
1797 bool fasttable_enabled) {
1799 std::vector<const protobuf::Descriptor*> file_messages = SortedMessages(
file);
1801 if (file_messages.empty())
return 0;
1803 for (
auto message : file_messages) {
1807 output(
"static const upb_MiniTable *$0[$1] = {\n", kMessagesInit,
1808 file_messages.size());
1809 for (
auto message : file_messages) {
1814 return file_messages.size();
1820 output(
" &$0,\n",
reinterpret_cast<const char*
>(
ext->extendee));
1821 output(
" $0,\n", FilePlatformLayout::GetSub(
ext->sub));
1824 int WriteExtensions(
const FileLayout&
layout, Output&
output) {
1825 auto exts = SortedExtensions(
layout.descriptor());
1828 if (exts.empty())
return 0;
1831 std::map<std::string, const protobuf::Descriptor*> forward_messages;
1833 for (
auto ext : exts) {
1834 forward_messages[
ext->containing_type()->full_name()] =
1835 ext->containing_type();
1836 if (
ext->message_type()) {
1837 forward_messages[
ext->message_type()->full_name()] =
ext->message_type();
1841 for (
const auto& decl : forward_messages) {
1842 output(
"extern const upb_MiniTable $0;\n", MessageInit(decl.second));
1845 for (
auto ext : exts) {
1846 output(
"const upb_MiniTable_Extension $0 = {\n ", ExtensionLayout(
ext));
1853 "static const upb_MiniTable_Extension *$0[$1] = {\n",
1854 kExtensionsInit, exts.size());
1856 for (
auto ext : exts) {
1857 output(
" &$0,\n", ExtensionLayout(
ext));
1867 void WriteSource(
const FileLayout&
layout, Output&
output,
1868 bool fasttable_enabled) {
1873 "#include <stddef.h>\n"
1874 "#include \"upb/msg_internal.h\"\n"
1875 "#include \"$0\"\n",
1878 for (
int i = 0;
i <
file->dependency_count();
i++) {
1884 "#include \"upb/port_def.inc\"\n"
1887 int msg_count = WriteMessages(
file,
output, fasttable_enabled);
1892 output(
" $0,\n", msg_count ? kMessagesInit :
"NULL");
1893 output(
" $0,\n", enum_count ? kEnumsInit :
"NULL");
1894 output(
" $0,\n", ext_count ? kExtensionsInit :
"NULL");
1895 output(
" $0,\n", msg_count);
1896 output(
" $0,\n", enum_count);
1897 output(
" $0,\n", ext_count);
1900 output(
"#include \"upb/port_undef.inc\"\n");
1909 uint64_t GetSupportedFeatures()
const override {
1910 return FEATURE_PROTO3_OPTIONAL;
1918 bool fasttable_enabled =
false;
1919 std::vector<std::pair<std::string, std::string>> params;
1922 for (
const auto&
pair : params) {
1923 if (
pair.first ==
"fasttable") {
1924 fasttable_enabled =
true;
1926 *
error =
"Unknown parameter: " +
pair.first;
1933 std::unique_ptr<protobuf::io::ZeroCopyOutputStream> h_output_stream(
1935 Output h_output(h_output_stream.get());
1936 WriteHeader(
layout, h_output);
1938 std::unique_ptr<protobuf::io::ZeroCopyOutputStream> c_output_stream(
1940 Output c_output(c_output_stream.get());
1941 WriteSource(
layout, c_output, fasttable_enabled);
1950 std::unique_ptr<google::protobuf::compiler::CodeGenerator> generator(