From 65cd34dd00f45eee93407c52eacb084db7906a78 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Sat, 11 Jun 2022 17:06:13 -0700 Subject: [PATCH] The mini descriptor encoder now uses the internal api (upb_MessageDef, upb_FileDef, etc) instead of dealing directly with the proto fields. So much simpler and cleaner! PiperOrigin-RevId: 454389613 --- upb/def.c | 8 + upb/def.h | 2 + upb/mini_descriptor.c | 232 ++++++++------------------ upb/mini_descriptor.h | 12 +- upbc/code_generator_request.c | 296 +++++++++++++--------------------- 5 files changed, 190 insertions(+), 360 deletions(-) diff --git a/upb/def.c b/upb/def.c index c745ff9f77..6ddc45bbbb 100644 --- a/upb/def.c +++ b/upb/def.c @@ -649,6 +649,14 @@ bool upb_FieldDef_IsString(const upb_FieldDef* f) { upb_FieldDef_CType(f) == kUpb_CType_Bytes; } +bool upb_FieldDef_IsOptional(const upb_FieldDef* f) { + return upb_FieldDef_Label(f) == kUpb_Label_Optional; +} + +bool upb_FieldDef_IsRequired(const upb_FieldDef* f) { + return upb_FieldDef_Label(f) == kUpb_Label_Required; +} + bool upb_FieldDef_IsRepeated(const upb_FieldDef* f) { return upb_FieldDef_Label(f) == kUpb_Label_Repeated; } diff --git a/upb/def.h b/upb/def.h index bea2558e4b..c520f858fa 100644 --- a/upb/def.h +++ b/upb/def.h @@ -116,6 +116,8 @@ const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f); uint32_t upb_FieldDef_Index(const upb_FieldDef* f); bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f); bool upb_FieldDef_IsString(const upb_FieldDef* f); +bool upb_FieldDef_IsOptional(const upb_FieldDef* f); +bool upb_FieldDef_IsRequired(const upb_FieldDef* f); bool upb_FieldDef_IsRepeated(const upb_FieldDef* f); bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f); bool upb_FieldDef_IsMap(const upb_FieldDef* f); diff --git a/upb/mini_descriptor.c b/upb/mini_descriptor.c index 8004964b19..21383704d2 100644 --- a/upb/mini_descriptor.c +++ b/upb/mini_descriptor.c @@ -27,14 +27,9 @@ #include "upb/mini_descriptor.h" -#include #include -#include -#include #include -#include -#include "upb/def.h" #include "upb/mini_table.h" // Must be last. @@ -86,90 +81,25 @@ static void upb_DescState_Emit(const DescState* d, upb_StringView* str) { /******************************************************************************/ -// Type and Field accessors. - -static inline bool upb_Type_IsPackable(upb_FieldType type) { - return (type != kUpb_FieldType_String && type != kUpb_FieldType_Group && - type != kUpb_FieldType_Message && type != kUpb_FieldType_Bytes); -} - -static inline bool upb_Field_IsOneof(const google_protobuf_FieldDescriptorProto* f) { - return google_protobuf_FieldDescriptorProto_has_oneof_index(f); -} - -static inline bool upb_Field_IsOptional(const google_protobuf_FieldDescriptorProto* f) { - const upb_Label label = google_protobuf_FieldDescriptorProto_label(f); - return label == kUpb_Label_Optional; -} - -static inline bool upb_Field_IsRepeated(const google_protobuf_FieldDescriptorProto* f) { - const upb_Label label = google_protobuf_FieldDescriptorProto_label(f); - return label == kUpb_Label_Repeated; -} - -static inline bool upb_Field_IsRequired(const google_protobuf_FieldDescriptorProto* f) { - const upb_Label label = google_protobuf_FieldDescriptorProto_label(f); - return label == kUpb_Label_Required; -} - -static inline bool upb_Field_IsPackable(const google_protobuf_FieldDescriptorProto* f) { - if (!upb_Field_IsRepeated(f)) return false; - - const upb_FieldType type = google_protobuf_FieldDescriptorProto_type(f); - return upb_Type_IsPackable(type); -} - -static bool upb_Field_IsPacked(const google_protobuf_FieldDescriptorProto* f, - upb_Syntax syntax) { - if (!upb_Field_IsPackable(f)) return false; - - const bool has_options = google_protobuf_FieldDescriptorProto_has_options(f); - const google_protobuf_FieldOptions* options = google_protobuf_FieldDescriptorProto_options(f); - - switch (syntax) { - case kUpb_Syntax_Proto2: - if (!has_options) return false; - break; - - default: - if (!has_options) return true; - if (!google_protobuf_FieldOptions_has_packed(options)) return true; - break; - } - - return google_protobuf_FieldOptions_packed(options); -} - -static inline int Field_OneofIndex(const google_protobuf_FieldDescriptorProto* f) { - return google_protobuf_FieldDescriptorProto_oneof_index(f); -} - -static bool upb_Field_HasPresence(const google_protobuf_FieldDescriptorProto* f, - upb_Syntax syntax) { - if (upb_Field_IsRepeated(f)) return false; - - const upb_FieldType type = google_protobuf_FieldDescriptorProto_type(f); - return type == kUpb_FieldType_Message || type == kUpb_FieldType_Group || - upb_Field_IsOneof(f) || syntax == kUpb_Syntax_Proto2; -} - -uint64_t upb_Field_Modifier(const google_protobuf_FieldDescriptorProto* f, - upb_Syntax syntax) { +// Copied from upbc/protoc-gen-upb.cc TODO(salo): can we consolidate? +static uint64_t upb_Field_Modifier(const upb_FieldDef* f) { uint64_t out = 0; - if (upb_Field_IsRepeated(f)) { + if (upb_FieldDef_IsRepeated(f)) { out |= kUpb_FieldModifier_IsRepeated; } - if (upb_Field_IsPacked(f, syntax)) { + if (upb_FieldDef_IsPacked(f)) { out |= kUpb_FieldModifier_IsPacked; } - if (google_protobuf_FieldDescriptorProto_type(f) == kUpb_FieldType_Enum && - syntax == kUpb_Syntax_Proto2) { - out |= kUpb_FieldModifier_IsClosedEnum; + if (upb_FieldDef_Type(f) == kUpb_FieldType_Enum) { + const upb_FileDef* file_def = upb_EnumDef_File(upb_FieldDef_EnumSubDef(f)); + if (upb_FileDef_Syntax(file_def) == kUpb_Syntax_Proto2) { + out |= kUpb_FieldModifier_IsClosedEnum; + } } - if (upb_Field_IsOptional(f) && !upb_Field_HasPresence(f, syntax)) { + if (upb_FieldDef_IsOptional(f) && !upb_FieldDef_HasPresence(f)) { out |= kUpb_FieldModifier_IsProto3Singular; } - if (upb_Field_IsRequired(f)) { + if (upb_FieldDef_IsRequired(f)) { out |= kUpb_FieldModifier_IsRequired; } return out; @@ -179,71 +109,51 @@ uint64_t upb_Field_Modifier(const google_protobuf_FieldDescriptorProto* f, // Sort by enum value. static int upb_MiniDescriptor_CompareEnums(const void* a, const void* b) { - const google_protobuf_EnumValueDescriptorProto* A = *(void**)a; - const google_protobuf_EnumValueDescriptorProto* B = *(void**)b; - if ((uint32_t)google_protobuf_EnumValueDescriptorProto_number(A) < - (uint32_t)google_protobuf_EnumValueDescriptorProto_number(B)) + const upb_EnumValueDef* A = *(void**)a; + const upb_EnumValueDef* B = *(void**)b; + if ((uint32_t)upb_EnumValueDef_Number(A) < + (uint32_t)upb_EnumValueDef_Number(B)) return -1; - if ((uint32_t)google_protobuf_EnumValueDescriptorProto_number(A) > - (uint32_t)google_protobuf_EnumValueDescriptorProto_number(B)) + if ((uint32_t)upb_EnumValueDef_Number(A) > + (uint32_t)upb_EnumValueDef_Number(B)) return 1; return 0; } // Sort by field number. static int upb_MiniDescriptor_CompareFields(const void* a, const void* b) { - const google_protobuf_FieldDescriptorProto* A = *(void**)a; - const google_protobuf_FieldDescriptorProto* B = *(void**)b; - if (google_protobuf_FieldDescriptorProto_number(A) < - google_protobuf_FieldDescriptorProto_number(B)) - return -1; - if (google_protobuf_FieldDescriptorProto_number(A) > - google_protobuf_FieldDescriptorProto_number(B)) - return 1; + const upb_FieldDef* A = *(void**)a; + const upb_FieldDef* B = *(void**)b; + if (upb_FieldDef_Number(A) < upb_FieldDef_Number(B)) return -1; + if (upb_FieldDef_Number(A) > upb_FieldDef_Number(B)) return 1; return 0; } -// Sort first by oneof index then by field number. -static int upb_MiniDescriptor_CompareOneofs(const void* a, const void* b) { - const google_protobuf_FieldDescriptorProto* A = *(void**)a; - const google_protobuf_FieldDescriptorProto* B = *(void**)b; - const int indexA = upb_Field_IsOneof(A) ? Field_OneofIndex(A) : -1; - const int indexB = upb_Field_IsOneof(B) ? Field_OneofIndex(B) : -1; - if (indexA < indexB) return -1; - if (indexA > indexB) return 1; - if (google_protobuf_FieldDescriptorProto_number(A) < - google_protobuf_FieldDescriptorProto_number(B)) - return -1; - if (google_protobuf_FieldDescriptorProto_number(A) > - google_protobuf_FieldDescriptorProto_number(B)) - return 1; - return 0; -} - -upb_StringView upb_MiniDescriptor_EncodeEnum( - const google_protobuf_EnumDescriptorProto* enum_type, upb_Arena* a) { +upb_StringView upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* enum_def, + upb_Arena* a) { upb_StringView out; out.data = NULL; out.size = 0; - size_t len = 0; - const google_protobuf_EnumValueDescriptorProto* const* value_types = - google_protobuf_EnumDescriptorProto_value(enum_type, &len); + DescState s; + upb_DescState_Init(&s); // Copy and sort. - google_protobuf_EnumValueDescriptorProto** sorted = upb_gmalloc(len * sizeof(void*)); + const size_t len = upb_EnumDef_ValueCount(enum_def); + const upb_EnumValueDef** sorted = upb_gmalloc(len * sizeof(void*)); if (!sorted) goto err; - memcpy(sorted, value_types, len * sizeof(void*)); - qsort(sorted, len, sizeof(void*), upb_MiniDescriptor_CompareEnums); - DescState s; - upb_DescState_Init(&s); + for (size_t i = 0; i < len; i++) { + sorted[i] = upb_EnumDef_Value(enum_def, i); + } + qsort(sorted, len, sizeof(void*), upb_MiniDescriptor_CompareEnums); upb_MtDataEncoder_StartEnum(&s.e); for (size_t i = 0; i < len; i++) { if (!upb_DescState_Grow(&s, a)) goto err; - const uint32_t number = google_protobuf_EnumValueDescriptorProto_number(sorted[i]); + const upb_EnumValueDef* value_def = sorted[i]; + const int number = upb_EnumValueDef_Number(value_def); s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, number); UPB_ASSERT(s.ptr); } @@ -259,9 +169,8 @@ err: return out; } -upb_StringView upb_MiniDescriptor_EncodeExtension( - const google_protobuf_FieldDescriptorProto* extension_type, upb_Syntax syntax, - upb_Arena* a) { +upb_StringView upb_MiniDescriptor_EncodeExtension(const upb_FieldDef* field_def, + upb_Arena* a) { upb_StringView out; out.data = NULL; out.size = 0; @@ -272,9 +181,10 @@ upb_StringView upb_MiniDescriptor_EncodeExtension( if (!upb_DescState_Grow(&s, a)) goto err; upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0); - const upb_FieldType type = google_protobuf_FieldDescriptorProto_type(extension_type); - const int number = google_protobuf_FieldDescriptorProto_number(extension_type); - const uint64_t modifier = upb_Field_Modifier(extension_type, syntax); + UPB_ASSERT(upb_FieldDef_IsExtension(field_def)); + const upb_FieldType type = upb_FieldDef_Type(field_def); + const int number = upb_FieldDef_Number(field_def); + const uint64_t modifier = upb_Field_Modifier(field_def); upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifier); upb_DescState_Emit(&s, &out); @@ -284,67 +194,57 @@ err: } upb_StringView upb_MiniDescriptor_EncodeMessage( - const google_protobuf_DescriptorProto* message_type, upb_Syntax syntax, - upb_Arena* a) { + const upb_MessageDef* message_def, upb_Arena* a) { upb_StringView out; out.data = NULL; out.size = 0; - size_t len = 0; - const google_protobuf_FieldDescriptorProto* const* field_types = - google_protobuf_DescriptorProto_field(message_type, &len); + DescState s; + upb_DescState_Init(&s); - // Copy and sort. - google_protobuf_FieldDescriptorProto** sorted = upb_gmalloc(len * sizeof(void*)); + // Make a copy. + const size_t len = upb_MessageDef_FieldCount(message_def); + const upb_FieldDef** sorted = upb_gmalloc(len * sizeof(void*)); if (!sorted) goto err; - memcpy(sorted, field_types, len * sizeof(void*)); - qsort(sorted, len, sizeof(void*), upb_MiniDescriptor_CompareFields); - DescState s; - upb_DescState_Init(&s); + // Sort the copy. + for (size_t i = 0; i < len; i++) { + sorted[i] = upb_MessageDef_Field(message_def, i); + } + qsort(sorted, len, sizeof(void*), upb_MiniDescriptor_CompareFields); if (!upb_DescState_Grow(&s, a)) goto err; upb_MtDataEncoder_StartMessage(&s.e, s.ptr, 0); // Encode the fields. - size_t oneof_fields = 0; for (size_t i = 0; i < len; i++) { - google_protobuf_FieldDescriptorProto* field_type = sorted[i]; - if (upb_Field_IsOneof(field_type)) { - // Put all oneof fields at the beginning of the list for the next pass. - sorted[oneof_fields++] = field_type; - } - - const upb_FieldType type = google_protobuf_FieldDescriptorProto_type(field_type); - const int number = google_protobuf_FieldDescriptorProto_number(field_type); - const uint64_t modifier = upb_Field_Modifier(field_type, syntax); + const upb_FieldDef* field_def = sorted[i]; + const int number = upb_FieldDef_Number(field_def); + const upb_FieldType type = upb_FieldDef_Type(field_def); + const uint64_t modifier = upb_Field_Modifier(field_def); if (!upb_DescState_Grow(&s, a)) goto err; s.ptr = upb_MtDataEncoder_PutField(&s.e, s.ptr, type, number, modifier); UPB_ASSERT(s.ptr); } - qsort(sorted, oneof_fields, sizeof(void*), upb_MiniDescriptor_CompareOneofs); - // Encode the oneofs. - int previous_index = -1; - for (size_t i = 0; i < oneof_fields; i++) { - google_protobuf_FieldDescriptorProto* field_type = sorted[i]; - if (!upb_Field_IsOneof(field_type)) continue; + const int oneof_count = upb_MessageDef_OneofCount(message_def); + for (int i = 0; i < oneof_count; i++) { + if (!upb_DescState_Grow(&s, a)) goto err; + s.ptr = upb_MtDataEncoder_StartOneof(&s.e, s.ptr); + UPB_ASSERT(s.ptr); + + const upb_OneofDef* oneof_def = upb_MessageDef_Oneof(message_def, i); + const int field_count = upb_OneofDef_FieldCount(oneof_def); + for (int j = 0; j < field_count; j++) { + const upb_FieldDef* field_def = upb_OneofDef_Field(oneof_def, j); + const int number = upb_FieldDef_Number(field_def); - const int index = Field_OneofIndex(field_type); - if (previous_index != index) { if (!upb_DescState_Grow(&s, a)) goto err; - s.ptr = upb_MtDataEncoder_StartOneof(&s.e, s.ptr); + s.ptr = upb_MtDataEncoder_PutOneofField(&s.e, s.ptr, number); UPB_ASSERT(s.ptr); - - previous_index = index; } - - if (!upb_DescState_Grow(&s, a)) goto err; - s.ptr = upb_MtDataEncoder_PutOneofField( - &s.e, s.ptr, google_protobuf_FieldDescriptorProto_number(field_type)); - UPB_ASSERT(s.ptr); } upb_DescState_Emit(&s, &out); diff --git a/upb/mini_descriptor.h b/upb/mini_descriptor.h index 0a53a723e8..829d008048 100644 --- a/upb/mini_descriptor.h +++ b/upb/mini_descriptor.h @@ -40,16 +40,14 @@ extern "C" { /** upb_MiniDescriptor ********************************************************/ -upb_StringView upb_MiniDescriptor_EncodeEnum( - const google_protobuf_EnumDescriptorProto* enum_type, upb_Arena* a); +upb_StringView upb_MiniDescriptor_EncodeEnum(const upb_EnumDef* enum_def, + upb_Arena* a); -upb_StringView upb_MiniDescriptor_EncodeExtension( - const google_protobuf_FieldDescriptorProto* extension_type, upb_Syntax syntax, - upb_Arena* a); +upb_StringView upb_MiniDescriptor_EncodeExtension(const upb_FieldDef* field_def, + upb_Arena* a); upb_StringView upb_MiniDescriptor_EncodeMessage( - const google_protobuf_DescriptorProto* message_type, upb_Syntax syntax, - upb_Arena* a); + const upb_MessageDef* message_def, upb_Arena* a); #ifdef __cplusplus } /* extern "C" */ diff --git a/upbc/code_generator_request.c b/upbc/code_generator_request.c index 95b8347a07..2591690f15 100644 --- a/upbc/code_generator_request.c +++ b/upbc/code_generator_request.c @@ -27,261 +27,183 @@ #include "upbc/code_generator_request.h" -#include #include #include -#include -#include #include -#include #include "google/protobuf/compiler/plugin.upb.h" -#include "upb/def.h" #include "upb/mini_descriptor.h" #include "upb/mini_table.h" // Must be last. #include "upb/port_def.inc" -enum { - kErrArenaMalloc = 1, - kErrEnumName, - kErrExtensionName, - kErrFieldName, - kErrFilePackage, - kErrMapCollision, - kErrMiniDescriptorsSet, - kErrStateGrow, -}; - -/* upbc_PathState *************************************************************/ - -// Manages the current fully qualified path name as we dig down into a proto. -// Basically just a string that grows and shrinks like a stack. - -typedef struct { - size_t len; - char path[4000]; // TODO(salo): make this dynamic -} upbc_PathState; - -static void upbc_PathState_Init(upbc_PathState* p) { p->len = 0; } - -static void upbc_PathState_Push(upbc_PathState* p, upb_StringView name) { - if (p->len) { - p->path[p->len++] = '.'; - } - memcpy(&p->path[p->len], name.data, name.size); - p->len += name.size; -} - -static void upbc_PathState_Pop(upbc_PathState* p, upb_StringView name) { - p->len -= name.size; - if (p->len) { - p->len--; - } -} - -static upb_StringView upbc_PathState_String(const upbc_PathState* p) { - return upb_StringView_FromDataAndSize(p->path, p->len); -} - /******************************************************************************/ -// Kitchen sink storage for the mini descriptor state. +// Kitchen sink storage for all of our state as we build the mini descriptors. typedef struct { - upb_Arena* a; - upb_Syntax syntax; + upb_Arena* arena; + upb_Status* status; + upb_DefPool* symtab; upbc_CodeGeneratorRequest* out; - jmp_buf err; - - upbc_PathState path; -} upbc_ScrapeState; + jmp_buf jmp; +} upbc_State; -static void upbc_ScrapeState_Init(upbc_ScrapeState* s, upb_Arena* a) { - s->a = a; - - upbc_PathState_Init(&s->path); - - s->out = upbc_CodeGeneratorRequest_new(a); - if (!s->out) UPB_LONGJMP(s->err, kErrArenaMalloc); +static void upbc_State_Fini(upbc_State* s) { + if (s->symtab) upb_DefPool_Free(s->symtab); } -static void upbc_ScrapeState_Push(upbc_ScrapeState* s, upb_StringView name) { - upbc_PathState_Push(&s->path, name); - - const upb_StringView key = upbc_PathState_String(&s->path); - if (upbc_CodeGeneratorRequest_mini_descriptors_get(s->out, key, NULL)) { - UPB_LONGJMP(s->err, kErrMapCollision); - } +static void upbc_Error(upbc_State* s, const char* fn, const char* msg) { + upb_Status_SetErrorFormat(s->status, "%s(): %s", fn, msg); + upbc_State_Fini(s); + UPB_LONGJMP(s->jmp, -1); } -static void upbc_ScrapeState_Pop(upbc_ScrapeState* s, upb_StringView name) { - upbc_PathState_Pop(&s->path, name); -} +static void upbc_State_Init(upbc_State* s) { + s->symtab = upb_DefPool_New(); + if (!s->symtab) upbc_Error(s, __func__, "could not allocate def pool"); -static void upbc_ScrapeState_String(upbc_ScrapeState* s, - upb_StringView encoding) { - const upb_StringView path = upbc_PathState_String(&s->path); - bool ok = upbc_CodeGeneratorRequest_mini_descriptors_set(s->out, path, - encoding, s->a); - if (!ok) UPB_LONGJMP(s->err, kErrMiniDescriptorsSet); + s->out = upbc_CodeGeneratorRequest_new(s->arena); + if (!s->out) upbc_Error(s, __func__, "could not allocate request"); } -/******************************************************************************/ - -// File accessors. - -static upb_Syntax upbc_File_Syntax(const google_protobuf_FileDescriptorProto* file) { - if (google_protobuf_FileDescriptorProto_has_syntax(file)) { - const upb_StringView syntax = google_protobuf_FileDescriptorProto_syntax(file); - const upb_StringView proto3 = upb_StringView_FromString("proto3"); - if (upb_StringView_IsEqual(syntax, proto3)) return kUpb_Syntax_Proto3; - } - return kUpb_Syntax_Proto2; +static void upbc_State_Emit(upbc_State* s, const char* name, + upb_StringView encoding) { + const upb_StringView key = upb_StringView_FromString(name); + bool ok = upbc_CodeGeneratorRequest_mini_descriptors_set(s->out, key, + encoding, s->arena); + if (!ok) upbc_Error(s, __func__, "could not set mini descriptor in map"); } /******************************************************************************/ // Forward declaration. -static void upbc_Scrape_Messages(upbc_ScrapeState*, - const google_protobuf_DescriptorProto* const*, size_t); - -static void upbc_Scrape_Enum(upbc_ScrapeState* s, - const google_protobuf_EnumDescriptorProto* enum_type) { - if (!google_protobuf_EnumDescriptorProto_has_name(enum_type)) { - UPB_LONGJMP(s->err, kErrEnumName); - } - const upb_StringView name = google_protobuf_EnumDescriptorProto_name(enum_type); - - upbc_ScrapeState_Push(s, name); +static void upbc_Scrape_Message(upbc_State*, const upb_MessageDef*); +static void upbc_Scrape_Enum(upbc_State* s, const upb_EnumDef* enum_def) { + const char* name = upb_EnumDef_FullName(enum_def); const upb_StringView encoding = - upb_MiniDescriptor_EncodeEnum(enum_type, s->a); + upb_MiniDescriptor_EncodeEnum(enum_def, s->arena); + upbc_State_Emit(s, name, encoding); +} - upbc_ScrapeState_String(s, encoding); - upbc_ScrapeState_Pop(s, name); +static void upbc_Scrape_Extension(upbc_State* s, + const upb_FieldDef* field_def) { + const char* name = upb_FieldDef_FullName(field_def); + const upb_StringView encoding = + upb_MiniDescriptor_EncodeExtension(field_def, s->arena); + upbc_State_Emit(s, name, encoding); } -static void upbc_Scrape_Enums( - upbc_ScrapeState* s, const google_protobuf_EnumDescriptorProto* const* enum_types, - size_t len) { +static void upbc_Scrape_FileEnums(upbc_State* s, const upb_FileDef* file_def) { + const size_t len = upb_FileDef_TopLevelEnumCount(file_def); for (size_t i = 0; i < len; i++) { - upbc_Scrape_Enum(s, enum_types[i]); + const upb_EnumDef* enum_def = upb_FileDef_TopLevelEnum(file_def, i); + upbc_Scrape_Enum(s, enum_def); } } -static void upbc_Scrape_Extension( - upbc_ScrapeState* s, const google_protobuf_FieldDescriptorProto* extension_type) { - if (!google_protobuf_FieldDescriptorProto_has_name(extension_type)) { - UPB_LONGJMP(s->err, kErrExtensionName); +static void upbc_Scrape_FileExtensions(upbc_State* s, + const upb_FileDef* file_def) { + const size_t len = upb_FileDef_TopLevelExtensionCount(file_def); + for (size_t i = 0; i < len; i++) { + const upb_FieldDef* field_def = upb_FileDef_TopLevelExtension(file_def, i); + upbc_Scrape_Extension(s, field_def); } - const upb_StringView name = google_protobuf_FieldDescriptorProto_name(extension_type); - - upbc_ScrapeState_Push(s, name); - - const upb_StringView encoding = - upb_MiniDescriptor_EncodeExtension(extension_type, s->syntax, s->a); - - upbc_ScrapeState_String(s, encoding); - upbc_ScrapeState_Pop(s, name); } -static void upbc_Scrape_Extensions( - const google_protobuf_FieldDescriptorProto* const* extension_types, size_t len, - upbc_ScrapeState* s) { +static void upbc_Scrape_FileMessages(upbc_State* s, + const upb_FileDef* file_def) { + const size_t len = upb_FileDef_TopLevelMessageCount(file_def); for (size_t i = 0; i < len; i++) { - upbc_Scrape_Extension(s, extension_types[i]); + const upb_MessageDef* message_def = + upb_FileDef_TopLevelMessage(file_def, i); + upbc_Scrape_Message(s, message_def); } } -static void upbc_Scrape_File(upbc_ScrapeState* s, - const google_protobuf_FileDescriptorProto* file_type) { - if (!google_protobuf_FileDescriptorProto_has_package(file_type)) { - UPB_LONGJMP(s->err, kErrFilePackage); - } - const upb_StringView package = google_protobuf_FileDescriptorProto_package(file_type); - upbc_ScrapeState_Push(s, package); +static void upbc_Scrape_File(upbc_State* s, const upb_FileDef* file_def) { + upbc_Scrape_FileEnums(s, file_def); + upbc_Scrape_FileExtensions(s, file_def); + upbc_Scrape_FileMessages(s, file_def); +} - s->syntax = upbc_File_Syntax(file_type); +static void upbc_Scrape_Files(upbc_State* s) { + const google_protobuf_compiler_CodeGeneratorRequest* request = + upbc_CodeGeneratorRequest_request(s->out); size_t len = 0; - const google_protobuf_EnumDescriptorProto* const* enum_types = - google_protobuf_FileDescriptorProto_enum_type(file_type, &len); - upbc_Scrape_Enums(s, enum_types, len); - - const google_protobuf_FieldDescriptorProto* const* extension_types = - google_protobuf_FileDescriptorProto_extension(file_type, &len); - upbc_Scrape_Extensions(extension_types, len, s); + const google_protobuf_FileDescriptorProto* const* file_types = + google_protobuf_compiler_CodeGeneratorRequest_proto_file(request, &len); - const google_protobuf_DescriptorProto* const* message_types = - google_protobuf_FileDescriptorProto_message_type(file_type, &len); - upbc_Scrape_Messages(s, message_types, len); + for (size_t i = 0; i < len; i++) { + const upb_FileDef* file_def = + upb_DefPool_AddFile(s->symtab, file_types[i], s->status); + if (!file_def) upbc_Error(s, __func__, "could not add file to def pool"); - upbc_ScrapeState_Pop(s, package); + upbc_Scrape_File(s, file_def); + } } -static void upbc_Scrape_Files( - upbc_ScrapeState* s, const google_protobuf_FileDescriptorProto* const* file_types, - size_t len) { +static void upbc_Scrape_NestedEnums(upbc_State* s, + const upb_MessageDef* message_def) { + const size_t len = upb_MessageDef_NestedEnumCount(message_def); for (size_t i = 0; i < len; i++) { - upbc_Scrape_File(s, file_types[i]); + const upb_EnumDef* enum_def = upb_MessageDef_NestedEnum(message_def, i); + upbc_Scrape_Enum(s, enum_def); } } -static void upbc_Scrape_Message(upbc_ScrapeState* s, - const google_protobuf_DescriptorProto* message_type) { - if (!google_protobuf_DescriptorProto_has_name(message_type)) return; - - const upb_StringView name = google_protobuf_DescriptorProto_name(message_type); - upbc_ScrapeState_Push(s, name); - - const upb_StringView encoding = - upb_MiniDescriptor_EncodeMessage(message_type, s->syntax, s->a); - upbc_ScrapeState_String(s, encoding); - - size_t len = 0; - const google_protobuf_EnumDescriptorProto* const* enum_types = - google_protobuf_DescriptorProto_enum_type(message_type, &len); - upbc_Scrape_Enums(s, enum_types, len); - - const google_protobuf_FieldDescriptorProto* const* extension_types = - google_protobuf_DescriptorProto_extension(message_type, &len); - upbc_Scrape_Extensions(extension_types, len, s); - - const google_protobuf_DescriptorProto* const* nested_types = - google_protobuf_DescriptorProto_nested_type(message_type, &len); - upbc_Scrape_Messages(s, nested_types, len); - - upbc_ScrapeState_Pop(s, name); +static void upbc_Scrape_NestedExtensions(upbc_State* s, + const upb_MessageDef* message_def) { + const size_t len = upb_MessageDef_NestedExtensionCount(message_def); + for (size_t i = 0; i < len; i++) { + const upb_FieldDef* field_def = + upb_MessageDef_NestedExtension(message_def, i); + upbc_Scrape_Extension(s, field_def); + } } -static void upbc_Scrape_Messages( - upbc_ScrapeState* s, const google_protobuf_DescriptorProto* const* message_types, - size_t len) { +static void upbc_Scrape_NestedMessages(upbc_State* s, + const upb_MessageDef* message_def) { + const size_t len = upb_MessageDef_NestedMessageCount(message_def); for (size_t i = 0; i < len; i++) { - upbc_Scrape_Message(s, message_types[i]); + const upb_MessageDef* nested_def = + upb_MessageDef_NestedMessage(message_def, i); + upbc_Scrape_Message(s, nested_def); } } +static void upbc_Scrape_Message(upbc_State* s, + const upb_MessageDef* message_def) { + const char* name = upb_MessageDef_FullName(message_def); + const upb_StringView encoding = + upb_MiniDescriptor_EncodeMessage(message_def, s->arena); + upbc_State_Emit(s, name, encoding); + + upbc_Scrape_NestedEnums(s, message_def); + upbc_Scrape_NestedExtensions(s, message_def); + upbc_Scrape_NestedMessages(s, message_def); +} + upbc_CodeGeneratorRequest* upbc_MakeCodeGeneratorRequest( - google_protobuf_compiler_CodeGeneratorRequest* request, upb_Arena* a, + google_protobuf_compiler_CodeGeneratorRequest* request, upb_Arena* arena, upb_Status* status) { - upbc_ScrapeState s; - int err = UPB_SETJMP(s.err); - if (err) { - upb_Status_SetErrorFormat(status, "%s(): error %d", __func__, err); - return NULL; - } - upbc_ScrapeState_Init(&s, a); + upbc_State s = { + .arena = arena, + .status = status, + .symtab = NULL, + .out = NULL, + }; - size_t len = 0; - const google_protobuf_FileDescriptorProto* const* file_types = - google_protobuf_compiler_CodeGeneratorRequest_proto_file(request, &len); - upbc_Scrape_Files(&s, file_types, len); + if (UPB_SETJMP(s.jmp)) return NULL; + upbc_State_Init(&s); upbc_CodeGeneratorRequest_set_request(s.out, request); + upbc_Scrape_Files(&s); + upbc_State_Fini(&s); return s.out; }