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
pull/13171/head
Protobuf Team Bot 3 years ago committed by Copybara-Service
parent bb38fc9c4d
commit 65cd34dd00
  1. 8
      upb/def.c
  2. 2
      upb/def.h
  3. 232
      upb/mini_descriptor.c
  4. 12
      upb/mini_descriptor.h
  5. 296
      upbc/code_generator_request.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;
}

@ -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);

@ -27,14 +27,9 @@
#include "upb/mini_descriptor.h"
#include <assert.h>
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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);

@ -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" */

@ -27,261 +27,183 @@
#include "upbc/code_generator_request.h"
#include <assert.h>
#include <inttypes.h>
#include <setjmp.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#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;
}

Loading…
Cancel
Save