Merge pull request #69 from haberman/oneofdesc

Added support for loading oneofs from descriptors.
pull/13171/head
Joshua Haberman 8 years ago committed by GitHub
commit b176b976a5
  1. 19
      tests/test.proto
  2. BIN
      tests/test.proto.pb
  3. 69
      upb/descriptor/reader.c

@ -6,6 +6,8 @@
// ^ |`---|--------^ // ^ |`---|--------^
// +----------+----+ F // +----------+----+ F
syntax = "proto2";
message A { message A {
optional B b = 1; optional B b = 1;
} }
@ -46,4 +48,21 @@ message SimplePrimitives {
optional sint32 i32 = 7; optional sint32 i32 = 7;
optional bool b = 8; optional bool b = 8;
optional string str = 9; optional string str = 9;
oneof foo {
int32 oneof_int32 = 10;
string oneof_string = 11;
}
oneof bar {
int64 oneof_int64 = 13;
bytes oneof_bytes = 14;
}
message Nested {
oneof foo {
int32 oneof_int32 = 10;
string b = 11;
}
}
} }

Binary file not shown.

@ -29,6 +29,8 @@ typedef struct {
/* Index of the first def that is under this scope. For msgdefs, the /* Index of the first def that is under this scope. For msgdefs, the
* msgdef itself is at start-1. */ * msgdef itself is at start-1. */
int start; int start;
uint32_t oneof_start;
uint32_t oneof_index;
} upb_descreader_frame; } upb_descreader_frame;
/* The maximum number of nested declarations that are allowed, ie. /* The maximum number of nested declarations that are allowed, ie.
@ -49,6 +51,7 @@ struct upb_descreader {
upb_filedef *file; /* The last file in files. */ upb_filedef *file; /* The last file in files. */
upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING]; upb_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
int stack_len; int stack_len;
upb_inttable oneofs;
uint32_t number; uint32_t number;
char *name; char *name;
@ -126,16 +129,27 @@ static upb_def *upb_descreader_last(upb_descreader *r) {
void upb_descreader_startcontainer(upb_descreader *r) { void upb_descreader_startcontainer(upb_descreader *r) {
upb_descreader_frame *f = &r->stack[r->stack_len++]; upb_descreader_frame *f = &r->stack[r->stack_len++];
f->start = upb_filedef_defcount(r->file); f->start = upb_filedef_defcount(r->file);
f->oneof_start = upb_inttable_count(&r->oneofs);
f->oneof_index = 0;
f->name = NULL; f->name = NULL;
} }
bool upb_descreader_endcontainer(upb_descreader *r) { bool upb_descreader_endcontainer(upb_descreader *r) {
upb_descreader_frame *f = &r->stack[--r->stack_len]; upb_descreader_frame *f = &r->stack[r->stack_len - 1];
while (upb_inttable_count(&r->oneofs) > f->oneof_start) {
upb_oneofdef *o = upb_value_getptr(upb_inttable_pop(&r->oneofs));
bool ok = upb_msgdef_addoneof(upb_descreader_top(r), o, &r->oneofs, NULL);
UPB_ASSERT(ok);
}
if (!upb_descreader_qualify(r->file, f->name, f->start)) { if (!upb_descreader_qualify(r->file, f->name, f->start)) {
return false; return false;
} }
upb_gfree(f->name); upb_gfree(f->name);
f->name = NULL; f->name = NULL;
r->stack_len--;
return true; return true;
} }
@ -145,6 +159,26 @@ void upb_descreader_setscopename(upb_descreader *r, char *str) {
f->name = str; f->name = str;
} }
static upb_oneofdef *upb_descreader_getoneof(upb_descreader *r,
uint32_t index) {
bool found;
upb_value val;
upb_descreader_frame *f = &r->stack[r->stack_len-1];
/* DescriptorProto messages can be nested, so we will see the nested messages
* between when we see the FieldDescriptorProto and the OneofDescriptorProto.
* We need to preserve the oneofs in between these two things. */
index += f->oneof_start;
while (upb_inttable_count(&r->oneofs) <= index) {
upb_inttable_push(&r->oneofs, upb_value_ptr(upb_oneofdef_new(&r->oneofs)));
}
found = upb_inttable_lookup(&r->oneofs, index, &val);
UPB_ASSERT(found);
return upb_value_getptr(val);
}
/** Handlers for google.protobuf.FileDescriptorSet. ***************************/ /** Handlers for google.protobuf.FileDescriptorSet. ***************************/
static void *fileset_startfile(void *closure, const void *hd) { static void *fileset_startfile(void *closure, const void *hd) {
@ -536,6 +570,33 @@ static size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
return n; return n;
} }
static bool field_ononeofindex(void *closure, const void *hd, int32_t index) {
upb_descreader *r = closure;
upb_oneofdef *o = upb_descreader_getoneof(r, index);
bool ok = upb_oneofdef_addfield(o, r->f, NULL, NULL);
UPB_UNUSED(hd);
UPB_ASSERT(ok);
return true;
}
/** Handlers for google.protobuf.OneofDescriptorProto. ************************/
static size_t oneof_name(void *closure, const void *hd, const char *buf,
size_t n, const upb_bufhandle *handle) {
upb_descreader *r = closure;
upb_descreader_frame *f = &r->stack[r->stack_len-1];
upb_oneofdef *o = upb_descreader_getoneof(r, f->oneof_index++);
char *name_null_terminated = upb_strndup(buf, n);
bool ok = upb_oneofdef_setname(o, name_null_terminated, NULL);
UPB_UNUSED(hd);
UPB_UNUSED(handle);
UPB_ASSERT(ok);
free(name_null_terminated);
return n;
}
/** Handlers for google.protobuf.DescriptorProto ******************************/ /** Handlers for google.protobuf.DescriptorProto ******************************/
static bool msg_start(void *closure, const void *hd) { static bool msg_start(void *closure, const void *hd) {
@ -687,6 +748,10 @@ static void reghandlers(const void *closure, upb_handlers *h) {
&field_onextendee, NULL); &field_onextendee, NULL);
upb_handlers_setstring(h, F(FieldDescriptorProto, default_value), upb_handlers_setstring(h, F(FieldDescriptorProto, default_value),
&field_ondefaultval, NULL); &field_ondefaultval, NULL);
upb_handlers_setint32(h, F(FieldDescriptorProto, oneof_index),
&field_ononeofindex, NULL);
} else if (upbdefs_google_protobuf_OneofDescriptorProto_is(m)) {
upb_handlers_setstring(h, F(OneofDescriptorProto, name), &oneof_name, NULL);
} else if (upbdefs_google_protobuf_FieldOptions_is(m)) { } else if (upbdefs_google_protobuf_FieldOptions_is(m)) {
upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL); upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL);
upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL); upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL);
@ -709,6 +774,7 @@ void descreader_cleanup(void *_r) {
upb_gfree(r->name); upb_gfree(r->name);
upb_inttable_uninit(&r->files); upb_inttable_uninit(&r->files);
upb_inttable_uninit(&r->oneofs);
upb_gfree(r->default_string); upb_gfree(r->default_string);
while (r->stack_len > 0) { while (r->stack_len > 0) {
upb_descreader_frame *f = &r->stack[--r->stack_len]; upb_descreader_frame *f = &r->stack[--r->stack_len];
@ -726,6 +792,7 @@ upb_descreader *upb_descreader_create(upb_env *e, const upb_handlers *h) {
} }
upb_inttable_init(&r->files, UPB_CTYPE_PTR); upb_inttable_init(&r->files, UPB_CTYPE_PTR);
upb_inttable_init(&r->oneofs, UPB_CTYPE_PTR);
upb_sink_reset(upb_descreader_input(r), h, r); upb_sink_reset(upb_descreader_input(r), h, r);
r->stack_len = 0; r->stack_len = 0;
r->name = NULL; r->name = NULL;

Loading…
Cancel
Save