Added support for loading oneofs from descriptors.

pull/13171/head
Josh Haberman 8 years ago
parent dfc409618f
commit 074a050bb1
  1. 19
      tests/test.proto
  2. BIN
      tests/test.proto.pb
  3. 68
      upb/descriptor/reader.c

@ -6,6 +6,8 @@
// ^ |`---|--------^
// +----------+----+ F
syntax = "proto2";
message A {
optional B b = 1;
}
@ -46,4 +48,21 @@ message SimplePrimitives {
optional sint32 i32 = 7;
optional bool b = 8;
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
* msgdef itself is at start-1. */
int start;
uint32_t oneof_start;
uint32_t oneof_index;
} upb_descreader_frame;
/* 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_descreader_frame stack[UPB_MAX_MESSAGE_NESTING];
int stack_len;
upb_inttable oneofs;
uint32_t number;
char *name;
@ -126,16 +129,27 @@ static upb_def *upb_descreader_last(upb_descreader *r) {
void upb_descreader_startcontainer(upb_descreader *r) {
upb_descreader_frame *f = &r->stack[r->stack_len++];
f->start = upb_filedef_defcount(r->file);
f->oneof_start = upb_inttable_count(&r->oneofs);
f->oneof_index = 0;
f->name = NULL;
}
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)) {
return false;
}
upb_gfree(f->name);
f->name = NULL;
r->stack_len--;
return true;
}
@ -145,6 +159,23 @@ void upb_descreader_setscopename(upb_descreader *r, char *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];
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. ***************************/
static void *fileset_startfile(void *closure, const void *hd) {
@ -536,6 +567,35 @@ static size_t field_ondefaultval(void *closure, const void *hd, const char *buf,
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_UNUSED(hd);
ok = upb_oneofdef_addfield(o, r->f, NULL, NULL);
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++);
bool ok;
char *name_null_terminated = upb_strndup(buf, n);
UPB_UNUSED(hd);
UPB_UNUSED(handle);
ok = upb_oneofdef_setname(o, name_null_terminated, NULL);
UPB_ASSERT(ok);
free(name_null_terminated);
return n;
}
/** Handlers for google.protobuf.DescriptorProto ******************************/
static bool msg_start(void *closure, const void *hd) {
@ -687,6 +747,10 @@ static void reghandlers(const void *closure, upb_handlers *h) {
&field_onextendee, NULL);
upb_handlers_setstring(h, F(FieldDescriptorProto, default_value),
&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)) {
upb_handlers_setbool(h, F(FieldOptions, lazy), &field_onlazy, NULL);
upb_handlers_setbool(h, F(FieldOptions, packed), &field_onpacked, NULL);
@ -709,6 +773,7 @@ void descreader_cleanup(void *_r) {
upb_gfree(r->name);
upb_inttable_uninit(&r->files);
upb_inttable_uninit(&r->oneofs);
upb_gfree(r->default_string);
while (r->stack_len > 0) {
upb_descreader_frame *f = &r->stack[--r->stack_len];
@ -726,6 +791,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->oneofs, UPB_CTYPE_PTR);
upb_sink_reset(upb_descreader_input(r), h, r);
r->stack_len = 0;
r->name = NULL;

Loading…
Cancel
Save