diff options
Diffstat (limited to 'upb/descriptor/reader.c')
-rw-r--r-- | upb/descriptor/reader.c | 401 |
1 files changed, 171 insertions, 230 deletions
diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c index 8177560..16f3b24 100644 --- a/upb/descriptor/reader.c +++ b/upb/descriptor/reader.c @@ -3,21 +3,38 @@ * * Copyright (c) 2008-2009 Google Inc. See LICENSE for details. * Author: Josh Haberman <jhaberman@gmail.com> + * + * XXX: The routines in this file that consume a string do not currently + * support having the string span buffers. In the future, as upb_sink and + * its buffering/sharing functionality evolve there should be an easy and + * idiomatic way of correctly handling this case. For now, we accept this + * limitation since we currently only parse descriptors from single strings. */ -#include <stdlib.h> +#include "upb/descriptor/reader.h" + #include <errno.h> +#include <stdlib.h> +#include <string.h> +#include "upb/bytestream.h" #include "upb/def.h" -#include "upb/descriptor/descriptor_const.h" -#include "upb/descriptor/reader.h" +#include "upb/descriptor/descriptor.upb.h" + +static char *upb_strndup(const char *buf, size_t n) { + char *ret = malloc(n + 1); + if (!ret) return NULL; + memcpy(ret, buf, n); + ret[n] = '\0'; + return ret; +} // Returns a newly allocated string that joins input strings together, for example: // join("Foo.Bar", "Baz") -> "Foo.Bar.Baz" // join("", "Baz") -> "Baz" -// Caller owns a ref on the returned string. */ +// Caller owns a ref on the returned string. static char *upb_join(const char *base, const char *name) { if (!base || strlen(base) == 0) { - return strdup(name); + return upb_strdup(name); } else { char *ret = malloc(strlen(base) + strlen(name) + 2); ret[0] = '\0'; @@ -74,10 +91,6 @@ static void upb_deflist_qualify(upb_deflist *l, char *str, int32_t start) { } } -// Forward declares for top-level file descriptors. -static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h); -static upb_mhandlers * upb_enumdef_register_EnumDescriptorProto(upb_handlers *h); - void upb_descreader_init(upb_descreader *r) { upb_deflist_init(&r->defs); upb_status_init(&r->status); @@ -107,7 +120,7 @@ static upb_msgdef *upb_descreader_top(upb_descreader *r) { if (r->stack_len <= 1) return NULL; int index = r->stack[r->stack_len-1].start - 1; assert(index >= 0); - return upb_downcast_msgdef(r->defs.defs[index]); + return upb_downcast_msgdef_mutable(r->defs.defs[index]); } static upb_def *upb_descreader_last(upb_descreader *r) { @@ -136,144 +149,80 @@ void upb_descreader_setscopename(upb_descreader *r, char *str) { } // Handlers for google.protobuf.FileDescriptorProto. -static upb_flow_t upb_descreader_FileDescriptorProto_startmsg(void *_r) { +static bool file_startmsg(void *_r) { upb_descreader *r = _r; upb_descreader_startcontainer(r); - return UPB_CONTINUE; + return true; } -static void upb_descreader_FileDescriptorProto_endmsg(void *_r, - upb_status *status) { - (void)status; +static void file_endmsg(void *_r, upb_status *status) { + UPB_UNUSED(status); upb_descreader *r = _r; upb_descreader_endcontainer(r); } -static upb_flow_t upb_descreader_FileDescriptorProto_package(void *_r, - upb_value fval, - upb_value val) { - (void)fval; +static size_t file_onpackage(void *_r, void *fval, const char *buf, size_t n) { + UPB_UNUSED(fval); upb_descreader *r = _r; - upb_descreader_setscopename( - r, upb_byteregion_strdup(upb_value_getbyteregion(val))); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_descreader_register_FileDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_descreader_FileDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_descreader_FileDescriptorProto_endmsg); - -#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDNUM -#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ ## field ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(PACKAGE), FTYPE(PACKAGE), false); - upb_fhandlers_setvalue(f, &upb_descreader_FileDescriptorProto_package); - - upb_mhandlers_newfhandlers_subm(m, FNUM(MESSAGE_TYPE), FTYPE(MESSAGE_TYPE), true, - upb_msgdef_register_DescriptorProto(h)); - upb_mhandlers_newfhandlers_subm(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true, - upb_enumdef_register_EnumDescriptorProto(h)); - // TODO: services, extensions - return m; -} -#undef FNUM -#undef FTYPE - -static upb_mhandlers *upb_descreader_register_FileDescriptorSet(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - -#define FNUM(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDNUM -#define FTYPE(field) GOOGLE_PROTOBUF_FILEDESCRIPTORSET_ ## field ## __FIELDTYPE - upb_mhandlers_newfhandlers_subm(m, FNUM(FILE), FTYPE(FILE), true, - upb_descreader_register_FileDescriptorProto(h)); - return m; -} -#undef FNUM -#undef FTYPE - -upb_mhandlers *upb_descreader_reghandlers(upb_handlers *h) { - h->should_jit = false; - return upb_descreader_register_FileDescriptorSet(h); + // XXX: see comment at the top of the file. + upb_descreader_setscopename(r, upb_strndup(buf, n)); + return n; } -// google.protobuf.EnumValueDescriptorProto. -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_startmsg(void *_r) { +// Handlers for google.protobuf.EnumValueDescriptorProto. +static bool enumval_startmsg(void *_r) { upb_descreader *r = _r; r->saw_number = false; r->saw_name = false; - return UPB_CONTINUE; + return true; } -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_name(void *_r, - upb_value fval, - upb_value val) { - (void)fval; +static size_t enumval_onname(void *_r, void *fval, const char *buf, size_t n) { + UPB_UNUSED(fval); upb_descreader *r = _r; + // XXX: see comment at the top of the file. free(r->name); - r->name = upb_byteregion_strdup(upb_value_getbyteregion(val)); + r->name = upb_strndup(buf, n); r->saw_name = true; - return UPB_CONTINUE; + return n; } -static upb_flow_t upb_enumdef_EnumValueDescriptorProto_number(void *_r, - upb_value fval, - upb_value val) { - (void)fval; +static bool enumval_onnumber(void *_r, void *fval, int32_t val) { + UPB_UNUSED(fval); upb_descreader *r = _r; - r->number = upb_value_getint32(val); + r->number = val; r->saw_number = true; - return UPB_CONTINUE; + return true; } -static void upb_enumdef_EnumValueDescriptorProto_endmsg(void *_r, - upb_status *status) { +static void enumval_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; if(!r->saw_number || !r->saw_name) { upb_status_seterrliteral(status, "Enum value missing name or number."); return; } - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); + upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); if (upb_enumdef_numvals(e) == 0) { // The default value of an enum (in the absence of an explicit default) is // its first listed value. upb_enumdef_setdefault(e, r->number); } - upb_enumdef_addval(e, r->name, r->number); + upb_enumdef_addval(e, r->name, r->number, status); free(r->name); r->name = NULL; } -static upb_mhandlers *upb_enumdef_register_EnumValueDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumValueDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_enumdef_EnumValueDescriptorProto_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f; - f = upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_name); - - f = upb_mhandlers_newfhandlers(m, FNUM(NUMBER), FTYPE(NUMBER), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumValueDescriptorProto_number); - return m; -} -#undef FNUM -#undef FTYPE -// google.protobuf.EnumDescriptorProto. -static upb_flow_t upb_enumdef_EnumDescriptorProto_startmsg(void *_r) { +// Handlers for google.protobuf.EnumDescriptorProto. +static bool enum_startmsg(void *_r) { upb_descreader *r = _r; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_enumdef_new(&r->defs))); - return UPB_CONTINUE; + upb_deflist_push(&r->defs, upb_upcast(upb_enumdef_new(&r->defs))); + return true; } -static void upb_enumdef_EnumDescriptorProto_endmsg(void *_r, upb_status *status) { +static void enum_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; - upb_enumdef *e = upb_downcast_enumdef(upb_descreader_last(r)); + upb_enumdef *e = upb_downcast_enumdef_mutable(upb_descreader_last(r)); if (upb_def_fullname(upb_descreader_last((upb_descreader*)_r)) == NULL) { upb_status_seterrliteral(status, "Enum had no name."); return; @@ -284,46 +233,28 @@ static void upb_enumdef_EnumDescriptorProto_endmsg(void *_r, upb_status *status) } } -static upb_flow_t upb_enumdef_EnumDescriptorProto_name(void *_r, - upb_value fval, - upb_value val) { - (void)fval; +static size_t enum_onname(void *_r, void *fval, const char *buf, size_t n) { + UPB_UNUSED(fval); upb_descreader *r = _r; - char *fullname = upb_byteregion_strdup(upb_value_getbyteregion(val)); + // XXX: see comment at the top of the file. + char *fullname = upb_strndup(buf, n); upb_def_setfullname(upb_descreader_last(r), fullname); free(fullname); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_enumdef_register_EnumDescriptorProto(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_enumdef_EnumDescriptorProto_startmsg); - upb_mhandlers_setendmsg(m, &upb_enumdef_EnumDescriptorProto_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_enumdef_EnumDescriptorProto_name); - - upb_mhandlers_newfhandlers_subm(m, FNUM(VALUE), FTYPE(VALUE), true, - upb_enumdef_register_EnumValueDescriptorProto(h)); - return m; + return n; } -#undef FNUM -#undef FTYPE -static upb_flow_t upb_fielddef_startmsg(void *_r) { +// Handlers for google.protobuf.FieldDescriptorProto +static bool field_startmsg(void *_r) { upb_descreader *r = _r; r->f = upb_fielddef_new(&r->defs); free(r->default_string); r->default_string = NULL; - return UPB_CONTINUE; + return true; } // Converts the default value in string "str" into "d". Passes a ref on str. // Returns true on success. -static bool upb_fielddef_parsedefault(char *str, upb_value *d, int type) { +static bool parse_default(char *str, upb_value *d, int type) { bool success = true; if (str) { switch(type) { @@ -397,29 +328,24 @@ static bool upb_fielddef_parsedefault(char *str, upb_value *d, int type) { return success; } -static void upb_fielddef_endmsg(void *_r, upb_status *status) { +static void field_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; upb_fielddef *f = r->f; // TODO: verify that all required fields were present. - assert(f->number != -1 && upb_fielddef_name(f) != NULL); - assert((upb_fielddef_subtypename(f) != NULL) == upb_hassubdef(f)); - - // Field was successfully read, add it as a field of the msgdef. - upb_msgdef *m = upb_descreader_top(r); - upb_msgdef_addfield(m, f, &r->defs); - r->f = NULL; + assert(upb_fielddef_number(f) != 0 && upb_fielddef_name(f) != NULL); + assert((upb_fielddef_subdefname(f) != NULL) == upb_fielddef_hassubdef(f)); if (r->default_string) { - if (upb_issubmsg(f)) { + if (upb_fielddef_issubmsg(f)) { upb_status_seterrliteral(status, "Submessages cannot have defaults."); return; } - if (upb_isstring(f) || f->type == UPB_TYPE(ENUM)) { + if (upb_fielddef_isstring(f) || upb_fielddef_type(f) == UPB_TYPE(ENUM)) { upb_fielddef_setdefaultcstr(f, r->default_string); } else { upb_value val; upb_value_setptr(&val, NULL); // Silence inaccurate compiler warnings. - if (!upb_fielddef_parsedefault(r->default_string, &val, f->type)) { + if (!parse_default(r->default_string, &val, upb_fielddef_type(f))) { // We don't worry too much about giving a great error message since the // compiler should have ensured this was correct. upb_status_seterrliteral(status, "Error converting default value."); @@ -430,132 +356,147 @@ static void upb_fielddef_endmsg(void *_r, upb_status *status) { } } -static upb_flow_t upb_fielddef_ontype(void *_r, upb_value fval, upb_value val) { - (void)fval; +static bool field_ontype(void *_r, void *fval, int32_t val) { + UPB_UNUSED(fval); upb_descreader *r = _r; - upb_fielddef_settype(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; + upb_fielddef_settype(r->f, val); + return true; } -static upb_flow_t upb_fielddef_onlabel(void *_r, upb_value fval, upb_value val) { - (void)fval; +static bool field_onlabel(void *_r, void *fval, int32_t val) { + UPB_UNUSED(fval); upb_descreader *r = _r; - upb_fielddef_setlabel(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; + upb_fielddef_setlabel(r->f, val); + return true; } -static upb_flow_t upb_fielddef_onnumber(void *_r, upb_value fval, upb_value val) { - (void)fval; +static bool field_onnumber(void *_r, void *fval, int32_t val) { + UPB_UNUSED(fval); upb_descreader *r = _r; - upb_fielddef_setnumber(r->f, upb_value_getint32(val)); - return UPB_CONTINUE; + upb_fielddef_setnumber(r->f, val); + return true; } -static upb_flow_t upb_fielddef_onname(void *_r, upb_value fval, upb_value val) { - (void)fval; +static size_t field_onname(void *_r, void *fval, const char *buf, size_t n) { + UPB_UNUSED(fval); upb_descreader *r = _r; - char *name = upb_byteregion_strdup(upb_value_getbyteregion(val)); + // XXX: see comment at the top of the file. + char *name = upb_strndup(buf, n); upb_fielddef_setname(r->f, name); free(name); - return UPB_CONTINUE; + return n; } -static upb_flow_t upb_fielddef_ontypename(void *_r, upb_value fval, - upb_value val) { - (void)fval; +static size_t field_ontypename(void *_r, void *fval, const char *buf, + size_t n) { + UPB_UNUSED(fval); upb_descreader *r = _r; - char *name = upb_byteregion_strdup(upb_value_getbyteregion(val)); - upb_fielddef_setsubtypename(r->f, name); + // XXX: see comment at the top of the file. + char *name = upb_strndup(buf, n); + upb_fielddef_setsubdefname(r->f, name); free(name); - return UPB_CONTINUE; + return n; } -static upb_flow_t upb_fielddef_ondefaultval(void *_r, upb_value fval, - upb_value val) { - (void)fval; +static size_t field_ondefaultval(void *_r, void *fval, const char *buf, + size_t n) { + UPB_UNUSED(fval); upb_descreader *r = _r; // Have to convert from string to the correct type, but we might not know the - // type yet. + // type yet, so we save it as a string until the end of the field. + // XXX: see comment at the top of the file. free(r->default_string); - r->default_string = upb_byteregion_strdup(upb_value_getbyteregion(val)); - return UPB_CONTINUE; -} - -static upb_mhandlers *upb_fielddef_register_FieldDescriptorProto( - upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_fielddef_startmsg); - upb_mhandlers_setendmsg(m, &upb_fielddef_endmsg); - -#define FIELD(name, handler) \ - upb_fhandlers_setvalue( \ - upb_mhandlers_newfhandlers(m, \ - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDNUM, \ - GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_ ## name ## __FIELDTYPE, \ - false), \ - handler); - FIELD(TYPE, &upb_fielddef_ontype); - FIELD(LABEL, &upb_fielddef_onlabel); - FIELD(NUMBER, &upb_fielddef_onnumber); - FIELD(NAME, &upb_fielddef_onname); - FIELD(TYPE_NAME, &upb_fielddef_ontypename); - FIELD(DEFAULT_VALUE, &upb_fielddef_ondefaultval); - return m; -} -#undef FNUM -#undef FTYPE - - -// google.protobuf.DescriptorProto. -static upb_flow_t upb_msgdef_startmsg(void *_r) { + r->default_string = upb_strndup(buf, n); + return n; +} + +// Handlers for google.protobuf.DescriptorProto (representing a message). +static bool msg_startmsg(void *_r) { upb_descreader *r = _r; - upb_deflist_push(&r->defs, UPB_UPCAST(upb_msgdef_new(&r->defs))); + upb_deflist_push(&r->defs, upb_upcast(upb_msgdef_new(&r->defs))); upb_descreader_startcontainer(r); - return UPB_CONTINUE; + return true; } -static void upb_msgdef_endmsg(void *_r, upb_status *status) { +static void msg_endmsg(void *_r, upb_status *status) { upb_descreader *r = _r; upb_msgdef *m = upb_descreader_top(r); - if(!upb_def_fullname(UPB_UPCAST(m))) { + if(!upb_def_fullname(upb_upcast(m))) { upb_status_seterrliteral(status, "Encountered message with no name."); return; } upb_descreader_endcontainer(r); } -static upb_flow_t upb_msgdef_onname(void *_r, upb_value fval, upb_value val) { - (void)fval; +static size_t msg_onname(void *_r, void *fval, const char *buf, size_t n) { + UPB_UNUSED(fval); upb_descreader *r = _r; upb_msgdef *m = upb_descreader_top(r); - char *name = upb_byteregion_strdup(upb_value_getbyteregion(val)); - upb_def_setfullname(UPB_UPCAST(m), name); + // XXX: see comment at the top of the file. + char *name = upb_strndup(buf, n); + upb_def_setfullname(upb_upcast(m), name); upb_descreader_setscopename(r, name); // Passes ownership of name. - return UPB_CONTINUE; + return n; } -static upb_mhandlers *upb_msgdef_register_DescriptorProto(upb_handlers *h) { - upb_mhandlers *m = upb_handlers_newmhandlers(h); - upb_mhandlers_setstartmsg(m, &upb_msgdef_startmsg); - upb_mhandlers_setendmsg(m, &upb_msgdef_endmsg); - -#define FNUM(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDNUM -#define FTYPE(f) GOOGLE_PROTOBUF_DESCRIPTORPROTO_ ## f ## __FIELDTYPE - upb_fhandlers *f = - upb_mhandlers_newfhandlers(m, FNUM(NAME), FTYPE(NAME), false); - upb_fhandlers_setvalue(f, &upb_msgdef_onname); - - upb_mhandlers_newfhandlers_subm(m, FNUM(FIELD), FTYPE(FIELD), true, - upb_fielddef_register_FieldDescriptorProto(h)); - upb_mhandlers_newfhandlers_subm(m, FNUM(ENUM_TYPE), FTYPE(ENUM_TYPE), true, - upb_enumdef_register_EnumDescriptorProto(h)); +static bool msg_onendfield(void *_r, void *fval) { + UPB_UNUSED(fval); + upb_descreader *r = _r; + upb_msgdef *m = upb_descreader_top(r); + upb_msgdef_addfield(m, r->f, &r->defs); + r->f = NULL; + return true; +} - // DescriptorProto is self-recursive, so we must link the definition. - upb_mhandlers_newfhandlers_subm( - m, FNUM(NESTED_TYPE), FTYPE(NESTED_TYPE), true, m); +static bool discardfield(void *_r, void *fval) { + UPB_UNUSED(fval); + upb_descreader *r = _r; + // Discard extension field so we don't leak it. + upb_fielddef_unref(r->f, &r->defs); + r->f = NULL; + return true; +} + +static void reghandlers(void *closure, upb_handlers *h) { + UPB_UNUSED(closure); + const upb_msgdef *m = upb_handlers_msgdef(h); + + if (m == GOOGLE_PROTOBUF_DESCRIPTORPROTO) { + upb_handlers_setstartmsg(h, &msg_startmsg); + upb_handlers_setendmsg(h, &msg_endmsg); + upb_handlers_setstring_n(h, "name", &msg_onname, NULL, NULL); + upb_handlers_setendsubmsg_n(h, "field", &msg_onendfield, NULL, NULL); + // TODO: support extensions + upb_handlers_setendsubmsg_n(h, "extension", &discardfield, NULL, NULL); + } else if (m == GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO) { + upb_handlers_setstartmsg(h, &file_startmsg); + upb_handlers_setendmsg(h, &file_endmsg); + upb_handlers_setstring_n(h, "package", &file_onpackage, NULL, NULL); + // TODO: support extensions + upb_handlers_setendsubmsg_n(h, "extension", &discardfield, NULL, NULL); + } else if (m == GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO) { + upb_handlers_setstartmsg(h, &enumval_startmsg); + upb_handlers_setendmsg(h, &enumval_endmsg); + upb_handlers_setstring_n(h, "name", &enumval_onname, NULL, NULL); + upb_handlers_setint32_n(h, "number", &enumval_onnumber, NULL, NULL); + } else if (m == GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO) { + upb_handlers_setstartmsg(h, &enum_startmsg); + upb_handlers_setendmsg(h, &enum_endmsg); + upb_handlers_setstring_n(h, "name", &enum_onname, NULL, NULL); + } else if (m == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO) { + upb_handlers_setstartmsg(h, &field_startmsg); + upb_handlers_setendmsg(h, &field_endmsg); + upb_handlers_setint32_n (h, "type", &field_ontype, NULL, NULL); + upb_handlers_setint32_n (h, "label", &field_onlabel, NULL, NULL); + upb_handlers_setint32_n (h, "number", &field_onnumber, NULL, NULL); + upb_handlers_setstring_n(h, "name", &field_onname, NULL, NULL); + upb_handlers_setstring_n(h, "type_name", &field_ontypename, NULL, NULL); + upb_handlers_setstring_n( + h, "default_value", &field_ondefaultval, NULL, NULL); + } +} - // TODO: extensions. - return m; +const upb_handlers *upb_descreader_newhandlers(const void *owner) { + return upb_handlers_newfrozen( + GOOGLE_PROTOBUF_FILEDESCRIPTORSET, owner, reghandlers, NULL); } -#undef FNUM -#undef FTYPE |