summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tests/test.proto19
-rw-r--r--tests/test.proto.pbbin353 -> 652 bytes
-rw-r--r--upb/descriptor/reader.c68
3 files changed, 86 insertions, 1 deletions
diff --git a/tests/test.proto b/tests/test.proto
index 40e185b..e790cbf 100644
--- a/tests/test.proto
+++ b/tests/test.proto
@@ -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;
+ }
+ }
}
diff --git a/tests/test.proto.pb b/tests/test.proto.pb
index 9fc835a..a587fb1 100644
--- a/tests/test.proto.pb
+++ b/tests/test.proto.pb
Binary files differ
diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c
index 82fd574..be3eed8 100644
--- a/upb/descriptor/reader.c
+++ b/upb/descriptor/reader.c
@@ -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;
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback