diff options
48 files changed, 5327 insertions, 2192 deletions
diff --git a/tests/bindings/lua/test.lua b/tests/bindings/lua/test.lua deleted file mode 100644 index 99f58f2..0000000 --- a/tests/bindings/lua/test.lua +++ /dev/null @@ -1,303 +0,0 @@ - -local upb = require "upb" -local lunit = require "lunit" - -if _VERSION >= 'Lua 5.2' then - _ENV = lunit.module("testupb", "seeall") -else - module("testupb", lunit.testcase, package.seeall) -end - -function test_fielddef() - local f = upb.FieldDef() - assert_false(f:is_frozen()) - assert_nil(f:number()) - assert_nil(f:name()) - assert_nil(f:type()) - assert_equal(upb.LABEL_OPTIONAL, f:label()) - - f:set_name("foo_field") - f:set_number(3) - f:set_label(upb.LABEL_REPEATED) - f:set_type(upb.TYPE_FLOAT) - - assert_equal("foo_field", f:name()) - assert_equal(3, f:number()) - assert_equal(upb.LABEL_REPEATED, f:label()) - assert_equal(upb.TYPE_FLOAT, f:type()) - - local f2 = upb.FieldDef{ - name = "foo", number = 5, type = upb.TYPE_DOUBLE, label = upb.LABEL_REQUIRED - } - - assert_equal("foo", f2:name()) - assert_equal(5, f2:number()) - assert_equal(upb.TYPE_DOUBLE, f2:type()) - assert_equal(upb.LABEL_REQUIRED, f2:label()) -end - -function test_enumdef() - local e = upb.EnumDef() - assert_equal(0, #e) - assert_nil(e:value(5)) - assert_nil(e:value("NONEXISTENT_NAME")) - - for name, value in e:values() do - fail() - end - - e:add("VAL1", 1) - e:add("VAL2", 2) - - local values = {} - for name, value in e:values() do - values[name] = value - end - - assert_equal(1, values["VAL1"]) - assert_equal(2, values["VAL2"]) - - local e2 = upb.EnumDef{ - values = { - {"FOO", 1}, - {"BAR", 77}, - } - } - - assert_equal(1, e2:value("FOO")) - assert_equal(77, e2:value("BAR")) - assert_equal("FOO", e2:value(1)) - assert_equal("BAR", e2:value(77)) -end - -function test_empty_msgdef() - local md = upb.MessageDef() - assert_nil(md:full_name()) -- Def without name is anonymous. - assert_false(md:is_frozen()) - assert_equal(0, #md) - assert_nil(md:field("nonexistent_field")) - assert_nil(md:field(3)) - for field in md:fields() do - fail() - end - - upb.freeze(md) - assert_true(md:is_frozen()) - assert_equal(0, #md) - assert_nil(md:field("nonexistent_field")) - assert_nil(md:field(3)) - for field in md:fields() do - fail() - end -end - -function test_msgdef_constructor() - local f1 = upb.FieldDef{name = "field1", number = 7, type = upb.TYPE_INT32} - local f2 = upb.FieldDef{name = "field2", number = 8, type = upb.TYPE_INT32} - local md = upb.MessageDef{ - full_name = "TestMessage", - fields = {f1, f2} - } - assert_equal("TestMessage", md:full_name()) - assert_false(md:is_frozen()) - assert_equal(2, #md) - assert_equal(f1, md:field("field1")) - assert_equal(f2, md:field("field2")) - assert_equal(f1, md:field(7)) - assert_equal(f2, md:field(8)) - local count = 0 - local found = {} - for field in md:fields() do - count = count + 1 - found[field] = true - end - assert_equal(2, count) - assert_true(found[f1]) - assert_true(found[f2]) - - upb.freeze(md) -end - -function test_msgdef_setters() - local md = upb.MessageDef() - md:set_full_name("Message1") - assert_equal("Message1", md:full_name()) - local f = upb.FieldDef{name = "field1", number = 3, type = upb.TYPE_DOUBLE} - md:add{f} - assert_equal(1, #md) - assert_equal(f, md:field("field1")) -end - -function test_msgdef_errors() - assert_error(function() upb.MessageDef{bad_initializer_key = 5} end) - local md = upb.MessageDef() - assert_error(function() - -- Duplicate field number. - upb.MessageDef{ - fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32} - } - } - end) - assert_error(function() - -- Duplicate field name. - upb.MessageDef{ - fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field1", number = 2, type = upb.TYPE_INT32} - } - } - end) - - -- attempt to set a name with embedded NULLs. - assert_error_match("names cannot have embedded NULLs", function() - md:set_full_name("abc\0def") - end) - - upb.freeze(md) - -- Attempt to mutate frozen MessageDef. - -- TODO(haberman): better error message and test for message. - assert_error(function() - md:add{upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}} - end) - assert_error(function() - md:set_full_name("abc") - end) - - -- Attempt to freeze a msgdef without freezing its subdef. - assert_error_match("is not frozen or being frozen", function() - m1 = upb.MessageDef() - upb.freeze( - upb.MessageDef{ - fields = { - upb.FieldDef{name = "f1", number = 1, type = upb.TYPE_MESSAGE, - subdef = m1} - } - } - ) - end) -end - -function test_symtab() - local empty = upb.SymbolTable() - assert_equal(0, #empty:getdefs(upb.DEF_ANY)) - - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "TestMessage"}, - upb.MessageDef{full_name = "ContainingMessage", fields = { - upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, - upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_MESSAGE, - subdef_name = ".TestMessage"} - } - } - } - - local msgdef1 = symtab:lookup("TestMessage") - local msgdef2 = symtab:lookup("ContainingMessage") - assert_not_nil(msgdef1) - assert_not_nil(msgdef2) - assert_equal(msgdef1, msgdef2:field("field2"):subdef()) - assert_true(msgdef1:is_frozen()) - assert_true(msgdef2:is_frozen()) - - symtab:add{ - upb.MessageDef{full_name = "ContainingMessage2", fields = { - upb.FieldDef{name = "field5", number = 5, type = upb.TYPE_MESSAGE, - subdef = msgdef2} - } - } - } - - local msgdef3 = symtab:lookup("ContainingMessage2") - assert_not_nil(msgdef3) - assert_equal(msgdef3:field("field5"):subdef(), msgdef2) -end - -function test_symtab_add_extension() - -- Adding an extension at the same time as the extendee. - local symtab = upb.SymbolTable{ - upb.MessageDef{full_name = "M1"}, - upb.FieldDef{name = "extension1", is_extension = true, number = 1, - type = upb.TYPE_INT32, containing_type_name = "M1"} - } - - local m1 = symtab:lookup("M1") - assert_not_nil(m1) - assert_equal(1, #m1) - - local f1 = m1:field("extension1") - assert_not_nil(f1) - assert_true(f1:is_extension()) - assert_true(f1:is_frozen()) - assert_equal(1, f1:number()) - - -- Adding an extension to an existing extendee. - symtab:add{ - upb.FieldDef{name = "extension2", is_extension = true, number = 2, - type = upb.TYPE_INT32, containing_type_name = "M1"} - } - - local m1_2 = symtab:lookup("M1") - assert_not_nil(m1_2) - assert_true(m1 ~= m1_2) - assert_equal(2, #m1_2) - - local f2 = m1_2:field("extension2") - assert_not_nil(f2) - assert_true(f2:is_extension()) - assert_true(f2:is_frozen()) - assert_equal(2, f2:number()) -end - --- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer --- can be defined in Lua. -if _VERSION >= 'Lua 5.2' then - function defer(fn) - setmetatable({}, { __gc = fn }) - end -else - function defer(fn) - getmetatable(newproxy(true)).__gc = fn - end -end - -function test_finalizer() - -- Tests that we correctly handle a call into an already-finalized object. - -- Collectible objects are finalized in the opposite order of creation. - do - local t = {} - defer(function() - assert_error_match("called into dead def", function() - -- Generic def call. - t[1]:full_name() - end) - assert_error_match("called into dead msgdef", function() - -- Specific msgdef call. - t[1]:add() - end) - assert_error_match("called into dead enumdef", function() - t[2]:values() - end) - assert_error_match("called into dead fielddef", function() - t[3]:number() - end) - assert_error_match("called into dead symtab", - function() t[4]:lookup() - end) - end) - t = { - upb.MessageDef(), - upb.EnumDef(), - upb.FieldDef(), - upb.SymbolTable(), - } - end - collectgarbage() -end - -local stats = lunit.main() - -if stats.failed > 0 or stats.errors > 0 then - error("One or more errors in test suite") -end diff --git a/tests/bindings/lua/upb.lua b/tests/bindings/lua/upb.lua new file mode 100644 index 0000000..f32a690 --- /dev/null +++ b/tests/bindings/lua/upb.lua @@ -0,0 +1,757 @@ + +local upb = require "upb" +local lunit = require "lunit" + +if _VERSION >= 'Lua 5.2' then + _ENV = lunit.module("testupb", "seeall") +else + module("testupb", lunit.testcase, package.seeall) +end + +function iter_to_array(iter) + local arr = {} + for v in iter do + arr[#arr + 1] = v + end + return arr +end + +function test_fielddef() + local f = upb.FieldDef() + assert_false(f:is_frozen()) + assert_nil(f:number()) + assert_nil(f:name()) + assert_nil(f:type()) + assert_equal(upb.LABEL_OPTIONAL, f:label()) + + f:set_name("foo_field") + f:set_number(3) + f:set_label(upb.LABEL_REPEATED) + f:set_type(upb.TYPE_FLOAT) + + assert_equal("foo_field", f:name()) + assert_equal(3, f:number()) + assert_equal(upb.LABEL_REPEATED, f:label()) + assert_equal(upb.TYPE_FLOAT, f:type()) + + local f2 = upb.FieldDef{ + name = "foo", number = 5, type = upb.TYPE_DOUBLE, label = upb.LABEL_REQUIRED + } + + assert_equal("foo", f2:name()) + assert_equal(5, f2:number()) + assert_equal(upb.TYPE_DOUBLE, f2:type()) + assert_equal(upb.LABEL_REQUIRED, f2:label()) +end + +function test_enumdef() + local e = upb.EnumDef() + assert_equal(0, #e) + assert_nil(e:value(5)) + assert_nil(e:value("NONEXISTENT_NAME")) + + for name, value in e:values() do + fail() + end + + e:add("VAL1", 1) + e:add("VAL2", 2) + + local values = {} + for name, value in e:values() do + values[name] = value + end + + assert_equal(1, values["VAL1"]) + assert_equal(2, values["VAL2"]) + + local e2 = upb.EnumDef{ + values = { + {"FOO", 1}, + {"BAR", 77}, + } + } + + assert_equal(1, e2:value("FOO")) + assert_equal(77, e2:value("BAR")) + assert_equal("FOO", e2:value(1)) + assert_equal("BAR", e2:value(77)) + + e2:freeze() + + local f = upb.FieldDef{type = upb.TYPE_ENUM} + + -- No default set and no EnumDef to get a default from. + assert_equal(f:default(), nil) + + f:set_subdef(upb.EnumDef()) + -- No default to pull in from the EnumDef. + assert_equal(f:default(), nil) + + f:set_subdef(e2) + -- First member added to e2. + assert_equal(f:default(), "FOO") + + f:set_subdef(nil) + assert_equal(f:default(), nil) + + f:set_default(1) + assert_equal(f:default(), 1) + + f:set_default("YOYOYO") + assert_equal(f:default(), "YOYOYO") + + f:set_subdef(e2) + f:set_default(1) + -- It prefers to return a string, and could resolve the explicit "1" we set + -- it to to the string value. + assert_equal(f:default(), "FOO") + + -- FieldDef can specify default value by name or number, but the value must + -- exist at freeze time. + local m1 = upb.build_defs{ + upb.MessageDef{ + full_name = "A", + fields = { + upb.FieldDef{ + name = "f1", + number = 1, + type = upb.TYPE_ENUM, + subdef = e2, + default = "BAR" + }, + upb.FieldDef{ + name = "f2", + number = 2, + type = upb.TYPE_ENUM, + subdef = e2, + default = 77 + } + } + } + } + + assert_equal(m1:field("f1"):default(), "BAR") + assert_equal(m1:field("f1"):default(), "BAR") + + assert_error_match( + "enum default for field A.f1 .DOESNT_EXIST. is not in the enum", + function() + local m1 = upb.build_defs{ + upb.MessageDef{ + full_name = "A", + fields = { + upb.FieldDef{ + name = "f1", + number = 1, + type = upb.TYPE_ENUM, + subdef = e2, + default = "DOESNT_EXIST" + } + } + } + } + end + ) + + assert_error_match( + "enum default for field A.f1 .142. is not in the enum", + function() + local m1 = upb.build_defs{ + upb.MessageDef{ + full_name = "A", + fields = { + upb.FieldDef{ + name = "f1", + number = 1, + type = upb.TYPE_ENUM, + subdef = e2, + default = 142 + } + } + } + } + end + ) +end + +function test_empty_msgdef() + local md = upb.MessageDef() + assert_nil(md:full_name()) -- Def without name is anonymous. + assert_false(md:is_frozen()) + assert_equal(0, #md) + assert_nil(md:field("nonexistent_field")) + assert_nil(md:field(3)) + for field in md:fields() do + fail() + end + + upb.freeze(md) + assert_true(md:is_frozen()) + assert_equal(0, #md) + assert_nil(md:field("nonexistent_field")) + assert_nil(md:field(3)) + for field in md:fields() do + fail() + end +end + +function test_msgdef_constructor() + local f1 = upb.FieldDef{name = "field1", number = 7, type = upb.TYPE_INT32} + local f2 = upb.FieldDef{name = "field2", number = 8, type = upb.TYPE_INT32} + local md = upb.MessageDef{ + full_name = "TestMessage", + fields = {f1, f2} + } + assert_equal("TestMessage", md:full_name()) + assert_false(md:is_frozen()) + assert_equal(2, #md) + assert_equal(f1, md:field("field1")) + assert_equal(f2, md:field("field2")) + assert_equal(f1, md:field(7)) + assert_equal(f2, md:field(8)) + local count = 0 + local found = {} + for field in md:fields() do + count = count + 1 + found[field] = true + end + assert_equal(2, count) + assert_true(found[f1]) + assert_true(found[f2]) + + upb.freeze(md) +end + +function test_iteration() + -- Test that we cannot crash the process even if we modify the set of fields + -- during iteration. + local md = upb.MessageDef{full_name = "TestMessage"} + + for i=1,10 do + md:add(upb.FieldDef{ + name = "field" .. tostring(i), + number = 1000 - i, + type = upb.TYPE_INT32 + }) + end + + local add = #md + for f in md:fields() do + if add > 0 then + add = add - 1 + for i=10000,11000 do + local field_name = "field" .. tostring(i) + -- We want to add fields to the table to trigger a table resize, + -- but we must skip it if the field name or number already exists + -- otherwise it will raise an error. + if md:field(field_name) == nil and + md:field(i) == nil then + md:add(upb.FieldDef{ + name = field_name, + number = i, + type = upb.TYPE_INT32 + }) + end + end + end + end + + -- Test that iterators don't crash the process even if the MessageDef goes + -- out of scope. + -- + -- Note: have previously verified that this can indeed crash the process if + -- we do not explicitly add a reference from the iterator to the underlying + -- MessageDef. + local iter = md:fields() + md = nil + collectgarbage() + while iter() do + end + + local ed = upb.EnumDef{ + values = { + {"FOO", 1}, + {"BAR", 77}, + } + } + iter = ed:values() + ed = nil + collectgarbage() + while iter() do + end +end + +function test_msgdef_setters() + local md = upb.MessageDef() + md:set_full_name("Message1") + assert_equal("Message1", md:full_name()) + local f = upb.FieldDef{name = "field1", number = 3, type = upb.TYPE_DOUBLE} + md:add(f) + assert_equal(1, #md) + assert_equal(f, md:field("field1")) +end + +function test_msgdef_errors() + assert_error(function() upb.MessageDef{bad_initializer_key = 5} end) + local md = upb.MessageDef() + assert_error(function() + -- Duplicate field number. + upb.MessageDef{ + fields = { + upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, + upb.FieldDef{name = "field2", number = 1, type = upb.TYPE_INT32} + } + } + end) + assert_error(function() + -- Duplicate field name. + upb.MessageDef{ + fields = { + upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, + upb.FieldDef{name = "field1", number = 2, type = upb.TYPE_INT32} + } + } + end) + + -- attempt to set a name with embedded NULLs. + assert_error_match("names cannot have embedded NULLs", function() + md:set_full_name("abc\0def") + end) + + upb.freeze(md) + -- Attempt to mutate frozen MessageDef. + assert_error_match("frozen", function() + md:add(upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}) + end) + assert_error_match("frozen", function() + md:set_full_name("abc") + end) + + -- Attempt to freeze a msgdef without freezing its subdef. + assert_error_match("is not frozen or being frozen", function() + m1 = upb.MessageDef() + upb.freeze( + upb.MessageDef{ + fields = { + upb.FieldDef{name = "f1", number = 1, type = upb.TYPE_MESSAGE, + subdef = m1} + } + } + ) + end) +end + +function test_symtab() + local empty = upb.SymbolTable() + assert_equal(0, #iter_to_array(empty:defs(upb.DEF_ANY))) + assert_equal(0, #iter_to_array(empty:defs(upb.DEF_MSG))) + assert_equal(0, #iter_to_array(empty:defs(upb.DEF_ENUM))) + + local symtab = upb.SymbolTable{ + upb.MessageDef{full_name = "TestMessage"}, + upb.MessageDef{full_name = "ContainingMessage", fields = { + upb.FieldDef{name = "field1", number = 1, type = upb.TYPE_INT32}, + upb.FieldDef{name = "field2", number = 2, type = upb.TYPE_MESSAGE, + subdef_name = ".TestMessage"} + } + } + } + + local msgdef1 = symtab:lookup("TestMessage") + local msgdef2 = symtab:lookup("ContainingMessage") + assert_not_nil(msgdef1) + assert_not_nil(msgdef2) + assert_equal(msgdef1, msgdef2:field("field2"):subdef()) + assert_true(msgdef1:is_frozen()) + assert_true(msgdef2:is_frozen()) + + symtab:add{ + upb.MessageDef{full_name = "ContainingMessage2", fields = { + upb.FieldDef{name = "field5", number = 5, type = upb.TYPE_MESSAGE, + subdef = msgdef2} + } + } + } + + local msgdef3 = symtab:lookup("ContainingMessage2") + assert_not_nil(msgdef3) + assert_equal(msgdef3:field("field5"):subdef(), msgdef2) + + -- Freeze the symtab and verify that mutating operations are not allowed. + assert_false(symtab:is_frozen()) + symtab:freeze() + assert_true(symtab:is_frozen()) + assert_error_match("frozen", function() symtab:freeze() end) + assert_error_match("frozen", function() + symtab:add{ + upb.MessageDef{full_name = "Foo"} + } + end) +end + +function test_symtab_add_extension() + -- Adding an extension at the same time as the extendee. + local symtab = upb.SymbolTable{ + upb.MessageDef{full_name = "M1"}, + upb.FieldDef{name = "extension1", is_extension = true, number = 1, + type = upb.TYPE_INT32, containing_type_name = "M1"} + } + + local m1 = symtab:lookup("M1") + assert_not_nil(m1) + assert_equal(1, #m1) + + local f1 = m1:field("extension1") + assert_not_nil(f1) + assert_true(f1:is_extension()) + assert_true(f1:is_frozen()) + assert_equal(1, f1:number()) + + -- Adding an extension to an existing extendee. + symtab:add{ + upb.FieldDef{name = "extension2", is_extension = true, number = 2, + type = upb.TYPE_INT32, containing_type_name = "M1"} + } + + local m1_2 = symtab:lookup("M1") + assert_not_nil(m1_2) + assert_true(m1 ~= m1_2) + assert_equal(2, #m1_2) + + local f2 = m1_2:field("extension2") + assert_not_nil(f2) + assert_true(f2:is_extension()) + assert_true(f2:is_frozen()) + assert_equal(2, f2:number()) +end + +function test_numeric_array() + local function test_for_numeric_type(upb_type, val, too_big, too_small, bad3) + local array = upb.Array(upb_type) + assert_equal(0, #array) + + -- 0 is never a valid index in Lua. + assert_error_match("array index", function() return array[0] end) + -- Past the end of the array. + assert_error_match("array index", function() return array[1] end) + + array[1] = val + assert_equal(val, array[1]) + assert_equal(1, #array) + -- Past the end of the array. + assert_error_match("array index", function() return array[2] end) + + array[2] = 10 + assert_equal(val, array[1]) + assert_equal(10, array[2]) + assert_equal(2, #array) + -- Past the end of the array. + assert_error_match("array index", function() return array[3] end) + + local n = 1 + for i, val in upb.ipairs(array) do + assert_equal(n, i) + n = n + 1 + assert_equal(array[i], val) + end + + -- Values that are out of range. + local errmsg = "not an integer or out of range" + if too_small then + assert_error_match(errmsg, function() array[3] = too_small end) + end + if too_big then + assert_error_match(errmsg, function() array[3] = too_big end) + end + if bad3 then + assert_error_match(errmsg, function() array[3] = bad3 end) + end + + -- Can't assign other Lua types. + errmsg = "bad argument #3" + assert_error_match(errmsg, function() array[3] = "abc" end) + assert_error_match(errmsg, function() array[3] = true end) + assert_error_match(errmsg, function() array[3] = false end) + assert_error_match(errmsg, function() array[3] = nil end) + assert_error_match(errmsg, function() array[3] = {} end) + assert_error_match(errmsg, function() array[3] = print end) + assert_error_match(errmsg, function() array[3] = array end) + end + + -- in-range of 64-bit types but not exactly representable as double + local bad64 = 2^68 - 1 + + test_for_numeric_type(upb.TYPE_UINT32, 2^32 - 1, 2^32, -1, 5.1) + test_for_numeric_type(upb.TYPE_UINT64, 2^63, 2^64, -1, bad64) + test_for_numeric_type(upb.TYPE_INT32, 2^31 - 1, 2^31, -2^31 - 1, 5.1) + -- Enums don't exist at a language level in Lua, so we just represent enum + -- values as int32s. + test_for_numeric_type(upb.TYPE_ENUM, 2^31 - 1, 2^31, -2^31 - 1, 5.1) + test_for_numeric_type(upb.TYPE_INT64, 2^62, 2^63, -2^64, bad64) + test_for_numeric_type(upb.TYPE_FLOAT, 10^38) + test_for_numeric_type(upb.TYPE_DOUBLE, 10^101) +end + +function test_string_array() + local function test_for_string_type(upb_type) + local array = upb.Array(upb_type) + assert_equal(0, #array) + + -- 0 is never a valid index in Lua. + assert_error_match("array index", function() return array[0] end) + -- Past the end of the array. + assert_error_match("array index", function() return array[1] end) + + array[1] = "foo" + assert_equal("foo", array[1]) + assert_equal(1, #array) + -- Past the end of the array. + assert_error_match("array index", function() return array[2] end) + + local array2 = upb.Array(upb_type) + assert_equal(0, #array2) + + array[2] = "bar" + assert_equal("foo", array[1]) + assert_equal("bar", array[2]) + assert_equal(2, #array) + -- Past the end of the array. + assert_error_match("array index", function() return array[3] end) + + local n = 1 + for i, val in upb.ipairs(array) do + assert_equal(n, i) + n = n + 1 + assert_equal(array[i], val) + end + assert_equal(3, n) + + -- Can't assign other Lua types. + assert_error_match("Expected string", function() array[3] = 123 end) + assert_error_match("Expected string", function() array[3] = true end) + assert_error_match("Expected string", function() array[3] = false end) + assert_error_match("Expected string", function() array[3] = nil end) + assert_error_match("Expected string", function() array[3] = {} end) + assert_error_match("Expected string", function() array[3] = print end) + assert_error_match("Expected string", function() array[3] = array end) + end + + test_for_string_type(upb.TYPE_STRING) + test_for_string_type(upb.TYPE_BYTES) +end + +function test_msg_primitives() + local function test_for_numeric_type(upb_type, val, too_big, too_small, bad3) + + msg = upb.Message( + upb.build_defs{ + upb.MessageDef{full_name = "TestMessage", fields = { + upb.FieldDef{name = "f", number = 1, type = upb_type}, + } + } + } + ) + + -- Defaults to nil + assert_nil(msg.f) + + msg.f = 0 + assert_equal(0, msg.f) + + msg.f = val + assert_equal(val, msg.f) + + local errmsg = "not an integer or out of range" + if too_small then + assert_error_match(errmsg, function() msg.f = too_small end) + end + if too_big then + assert_error_match(errmsg, function() msg.f = too_big end) + end + if bad3 then + assert_error_match(errmsg, function() msg.f = bad3 end) + end + + -- Can't assign other Lua types. + errmsg = "bad argument #3" + assert_error_match(errmsg, function() msg.f = "abc" end) + assert_error_match(errmsg, function() msg.f = true end) + assert_error_match(errmsg, function() msg.f = false end) + assert_error_match(errmsg, function() msg.f = nil end) + assert_error_match(errmsg, function() msg.f = {} end) + assert_error_match(errmsg, function() msg.f = print end) + assert_error_match(errmsg, function() msg.f = array end) + end + + local msgdef = upb.build_defs{ + upb.MessageDef{full_name = "TestMessage", fields = { + upb.FieldDef{name = "i32", number = 1, type = upb.TYPE_INT32}, + upb.FieldDef{name = "u32", number = 2, type = upb.TYPE_UINT32}, + upb.FieldDef{name = "i64", number = 3, type = upb.TYPE_INT64}, + upb.FieldDef{name = "u64", number = 4, type = upb.TYPE_UINT64}, + upb.FieldDef{name = "dbl", number = 5, type = upb.TYPE_DOUBLE}, + upb.FieldDef{name = "flt", number = 6, type = upb.TYPE_FLOAT}, + upb.FieldDef{name = "bool", number = 7, type = upb.TYPE_BOOL}, + } + } + } + + msg = upb.Message(msgdef) + + -- Unset member returns nil. This is unlike C++/Java, but is more + -- Lua-like behavior. + assert_equal(nil, msg.i32) + assert_equal(nil, msg.u32) + assert_equal(nil, msg.i64) + assert_equal(nil, msg.u64) + assert_equal(nil, msg.dbl) + assert_equal(nil, msg.flt) + assert_equal(nil, msg.bool) + + -- Attempts to access non-existent fields fail. + assert_error_match("no such field", function() msg.no_such = 1 end) + + msg.i32 = 10 + msg.u32 = 20 + msg.i64 = 30 + msg.u64 = 40 + msg.dbl = 50 + msg.flt = 60 + msg.bool = true + + assert_equal(10, msg.i32) + assert_equal(20, msg.u32) + assert_equal(30, msg.i64) + assert_equal(40, msg.u64) + assert_equal(50, msg.dbl) + assert_equal(60, msg.flt) + assert_equal(true, msg.bool) + + test_for_numeric_type(upb.TYPE_UINT32, 2^32 - 1, 2^32, -1, 5.1) + test_for_numeric_type(upb.TYPE_UINT64, 2^62, 2^64, -1, bad64) + test_for_numeric_type(upb.TYPE_INT32, 2^31 - 1, 2^31, -2^31 - 1, 5.1) + test_for_numeric_type(upb.TYPE_INT64, 2^61, 2^63, -2^64, bad64) + test_for_numeric_type(upb.TYPE_FLOAT, 2^20) + test_for_numeric_type(upb.TYPE_DOUBLE, 10^101) +end + +function test_msg_array() + local msgdef = upb.build_defs{ + upb.MessageDef{full_name = "TestMessage", fields = { + upb.FieldDef{name = "i32_array", number = 1, type = upb.TYPE_INT32, + label = upb.LABEL_REPEATED}, + } + } + } + + msg = upb.Message(msgdef) + + assert_nil(msg.i32_array) + + -- Can't assign a scalar; array is expected. + assert_error_match("lupb.array expected", function() msg.i32_array = 5 end) + + -- Can't assign array of the wrong type. + local function assign_int64() + msg.i32_array = upb.Array(upb.TYPE_INT64) + end + assert_error_match("Array type mismatch", assign_int64) + + local arr = upb.Array(upb.TYPE_INT32) + msg.i32_array = arr + assert_equal(arr, msg.i32_array) + + -- Can't assign other Lua types. + assert_error_match("array expected", function() msg.i32_array = "abc" end) + assert_error_match("array expected", function() msg.i32_array = true end) + assert_error_match("array expected", function() msg.i32_array = false end) + assert_error_match("array expected", function() msg.i32_array = nil end) + assert_error_match("array expected", function() msg.i32_array = {} end) + assert_error_match("array expected", function() msg.i32_array = print end) +end + +function test_msg_submsg() + local test_msgdef, submsg_msgdef = upb.build_defs{ + upb.MessageDef{full_name = "TestMessage", fields = { + upb.FieldDef{name = "submsg", number = 1, type = upb.TYPE_MESSAGE, + subdef_name = ".SubMessage"}, + } + }, + upb.MessageDef{full_name = "SubMessage"} + } + + msg = upb.Message(test_msgdef) + + assert_nil(msg.submsg) + + -- Can't assign message of the wrong type. + local function assign_int64() + msg.submsg = upb.Message(test_msgdef) + end + assert_error_match("Message type mismatch", assign_int64) + + local sub = upb.Message(submsg_msgdef) + msg.submsg = sub + assert_equal(sub, msg.submsg) + + -- Can't assign other Lua types. + assert_error_match("msg expected", function() msg.submsg = "abc" end) + assert_error_match("msg expected", function() msg.submsg = true end) + assert_error_match("msg expected", function() msg.submsg = false end) + assert_error_match("msg expected", function() msg.submsg = nil end) + assert_error_match("msg expected", function() msg.submsg = {} end) + assert_error_match("msg expected", function() msg.submsg = print end) +end + +-- Lua 5.1 and 5.2 have slightly different semantics for how a finalizer +-- can be defined in Lua. +if _VERSION >= 'Lua 5.2' then + function defer(fn) + setmetatable({}, { __gc = fn }) + end +else + function defer(fn) + getmetatable(newproxy(true)).__gc = fn + end +end + +function test_finalizer() + -- Tests that we correctly handle a call into an already-finalized object. + -- Collectible objects are finalized in the opposite order of creation. + do + local t = {} + defer(function() + assert_error_match("called into dead object", function() + -- Generic def call. + t[1]:full_name() + end) + assert_error_match("called into dead object", function() + -- Specific msgdef call. + t[1]:add() + end) + assert_error_match("called into dead object", function() + t[2]:values() + end) + assert_error_match("called into dead object", function() + t[3]:number() + end) + assert_error_match("called into dead object", + function() t[4]:lookup() + end) + end) + t = { + upb.MessageDef(), + upb.EnumDef(), + upb.FieldDef(), + upb.SymbolTable(), + } + end + collectgarbage() +end + +local stats = lunit.main() + +if stats.failed > 0 or stats.errors > 0 then + error("One or more errors in test suite") +end diff --git a/tests/bindings/lua/upb.pb.lua b/tests/bindings/lua/upb.pb.lua new file mode 100644 index 0000000..02b443a --- /dev/null +++ b/tests/bindings/lua/upb.pb.lua @@ -0,0 +1,70 @@ + +local upb = require "upb" +local pb = require "upb.pb" +local lunit = require "lunit" + +if _VERSION >= 'Lua 5.2' then + _ENV = lunit.module("testupb_pb", "seeall") +else + module("testupb_pb", lunit.testcase, package.seeall) +end + +local primitive_types_msg = upb.build_defs{ + upb.MessageDef{full_name = "TestMessage", fields = { + upb.FieldDef{name = "i32", number = 1, type = upb.TYPE_INT32}, + upb.FieldDef{name = "u32", number = 2, type = upb.TYPE_UINT32}, + upb.FieldDef{name = "i64", number = 3, type = upb.TYPE_INT64}, + upb.FieldDef{name = "u64", number = 4, type = upb.TYPE_UINT64}, + upb.FieldDef{name = "dbl", number = 5, type = upb.TYPE_DOUBLE}, + upb.FieldDef{name = "flt", number = 6, type = upb.TYPE_FLOAT}, + upb.FieldDef{name = "bool", number = 7, type = upb.TYPE_BOOL}, + } + } +} + +function test_decodermethod() + local dm = pb.DecoderMethod(primitive_types_msg) + + assert_error( + function() + -- Needs at least one argument to construct. + pb.DecoderMethod() + end) +end + +function test_parse_primitive() + local binary_pb = + "\008\128\128\128\128\002\016\128\128\128\128\004\024\128\128" + .. "\128\128\128\128\128\002\032\128\128\128\128\128\128\128\001\041\000" + .. "\000\000\000\000\000\248\063\053\000\000\096\064\056\001" + local dm = pb.DecoderMethod(primitive_types_msg) + msg = dm:parse(binary_pb) + assert_equal(536870912, msg.i32) + assert_equal(1073741824, msg.u32) + assert_equal(1125899906842624, msg.i64) + assert_equal(562949953421312, msg.u64) + assert_equal(1.5, msg.dbl) + assert_equal(3.5, msg.flt) + assert_equal(true, msg.bool) +end + +function test_parse_string() + local msgdef = upb.build_defs{ + upb.MessageDef{full_name = "TestMessage", fields = { + upb.FieldDef{name = "str", number = 1, type = upb.TYPE_STRING}, + } + } + } + + local binary_pb = "\010\005Hello" + local dm = pb.DecoderMethod(msgdef) + msg = dm:parse(binary_pb) + assert_equal("Hello", msg.str) +end + + +local stats = lunit.main() + +if stats.failed > 0 or stats.errors > 0 then + error("One or more errors in test suite") +end diff --git a/tests/pb/test_decoder.cc b/tests/pb/test_decoder.cc index 1660436..e016632 100644 --- a/tests/pb/test_decoder.cc +++ b/tests/pb/test_decoder.cc @@ -297,7 +297,7 @@ template<class T, bool F(int*, const uint32_t*, T)> void doreg(upb_handlers *h, uint32_t num) { const upb_fielddef *f = upb_msgdef_itof(upb_handlers_msgdef(h), num); ASSERT(f); - ASSERT(h->SetValueHandler<T>(f, UpbBindT(&F, new uint32_t(num)))); + ASSERT(h->SetValueHandler<T>(f, UpbBindT(F, new uint32_t(num)))); if (f->IsSequence()) { ASSERT(h->SetStartSequenceHandler(f, UpbBind(startseq, new uint32_t(num)))); ASSERT(h->SetEndSequenceHandler(f, UpbBind(endseq, new uint32_t(num)))); @@ -488,8 +488,22 @@ uint32_t Hash(const string& proto, const string* expected_output, size_t seam1, return hash; } -bool parse(upb::BytesSink* s, void* subc, const char* buf, size_t start, - size_t end, size_t* ofs, upb::Status* status) { +void CheckBytesParsed(const upb::pb::Decoder& decoder, size_t ofs) { + // We could have parsed as many as 10 bytes fewer than what the decoder + // previously accepted, since we can buffer up to 10 partial bytes internally + // before accumulating an entire value. + const int MAX_BUFFERED = 10; + + // We can't have parsed more data than the decoder callback is telling us it + // parsed. + ASSERT(decoder.BytesParsed() <= ofs); + ASSERT(ofs <= (decoder.BytesParsed() + MAX_BUFFERED)); +} + +bool parse(upb::pb::Decoder* decoder, void* subc, const char* buf, + size_t start, size_t end, size_t* ofs, upb::Status* status) { + CheckBytesParsed(*decoder, *ofs); + upb::BytesSink* s = decoder->input(); start = UPB_MAX(start, *ofs); if (start <= end) { size_t len = end - start; @@ -532,6 +546,7 @@ bool parse(upb::BytesSink* s, void* subc, const char* buf, size_t start, if (!status->ok()) return false; *ofs += parsed; + CheckBytesParsed(*decoder, *ofs); } return true; } @@ -569,12 +584,12 @@ void run_decoder(const string& proto, const string* expected_output) { fprintf(stderr, "Calling start()\n"); } - bool ok = - input->Start(proto.size(), &sub) && - parse(input, sub, proto.c_str(), 0, i, &ofs, &status) && - parse(input, sub, proto.c_str(), i, j, &ofs, &status) && - parse(input, sub, proto.c_str(), j, proto.size(), &ofs, &status) && - ofs == proto.size(); + bool ok = input->Start(proto.size(), &sub) && + parse(&decoder, sub, proto.c_str(), 0, i, &ofs, &status) && + parse(&decoder, sub, proto.c_str(), i, j, &ofs, &status) && + parse(&decoder, sub, proto.c_str(), j, proto.size(), &ofs, + &status) && + ofs == proto.size(); if (ok) { if (filter_hash) { @@ -940,6 +955,22 @@ void test_valid() { LINE("%u:1") LINE(">"), UPB_DESCRIPTOR_TYPE_INT32); + // String inside submsg. + uint32_t msg_fn = UPB_DESCRIPTOR_TYPE_MESSAGE; + assert_successful_parse( + submsg(msg_fn, + cat ( tag(UPB_DESCRIPTOR_TYPE_STRING, UPB_WIRE_TYPE_DELIMITED), + delim(string("abcde")) + ) + ), + LINE("<") + LINE("%u:{") + LINE(" <") + LINE(" %u:(5)\"abcde\"") + LINE(" >") + LINE("}") + LINE(">"), msg_fn, UPB_DESCRIPTOR_TYPE_STRING); + // Test implicit startseq/endseq. uint32_t repfl_fn = rep_fn(UPB_DESCRIPTOR_TYPE_FLOAT); uint32_t repdb_fn = rep_fn(UPB_DESCRIPTOR_TYPE_DOUBLE); @@ -956,7 +987,6 @@ void test_valid() { LINE(">"), repfl_fn, repfl_fn, repdb_fn, repdb_fn); // Submessage tests. - uint32_t msg_fn = UPB_DESCRIPTOR_TYPE_MESSAGE; assert_successful_parse( submsg(msg_fn, submsg(msg_fn, submsg(msg_fn, string()))), LINE("<") diff --git a/tests/test_cpp.cc b/tests/test_cpp.cc index 60d6527..fe0695f 100644 --- a/tests/test_cpp.cc +++ b/tests/test_cpp.cc @@ -153,6 +153,9 @@ static void TestSymbolTable(const char *descriptor_file) { std::cerr << "Couldn't load descriptor: " << status.error_message(); exit(1); } + ASSERT(!s->IsFrozen()); + s->Freeze(); + ASSERT(s->IsFrozen()); upb::reffed_ptr<const upb::MessageDef> md(s->LookupMessage("C")); ASSERT(md.get()); @@ -1038,6 +1041,39 @@ void TestMismatchedTypes() { // match top-level closure of sub-handlers. } +class IntIncrementer { + public: + IntIncrementer(int* x) : x_(x) { (*x_)++; } + ~IntIncrementer() { (*x_)--; } + + static void Handler(void* closure, const IntIncrementer* incrementer, + int32_t x) {} + + private: + int* x_; +}; + + +void TestHandlerDataDestruction() { + upb::reffed_ptr<upb::MessageDef> md(upb::MessageDef::New()); + upb::reffed_ptr<upb::FieldDef> f(upb::FieldDef::New()); + f->set_type(UPB_TYPE_INT32); + ASSERT(f->set_name("test", NULL)); + ASSERT(f->set_number(1, NULL)); + ASSERT(md->AddField(f, NULL)); + ASSERT(md->Freeze(NULL)); + + int x = 0; + { + upb::reffed_ptr<upb::Handlers> h(upb::Handlers::New(md.get())); + h->SetInt32Handler( + f.get(), UpbBind(&IntIncrementer::Handler, new IntIncrementer(&x))); + ASSERT(x == 1); + } + + ASSERT(x == 0); +} + extern "C" { int run_tests(int argc, char *argv[]) { @@ -1091,6 +1127,8 @@ int run_tests(int argc, char *argv[]) { TestMismatchedTypes(); + TestHandlerDataDestruction(); + #ifdef UPB_CXX11 #define ASSERT_STD_LAYOUT(type) \ static_assert(std::is_standard_layout<type>::value, \ diff --git a/tests/test_def.c b/tests/test_def.c index bf45a73..7efd2b0 100644 --- a/tests/test_def.c +++ b/tests/test_def.c @@ -17,10 +17,11 @@ const char *descriptor_file; static void test_empty_symtab() { upb_symtab *s = upb_symtab_new(&s); - int count; - const upb_def **defs = upb_symtab_getdefs(s, UPB_DEF_ANY, NULL, &count); - ASSERT(count == 0); - free(defs); + upb_symtab_iter i; + for (upb_symtab_begin(&i, s, UPB_DEF_ANY); !upb_symtab_done(&i); + upb_symtab_next(&i)) { + ASSERT(false); // Should not get here. + } upb_symtab_unref(s, &s); } @@ -33,6 +34,9 @@ static upb_symtab *load_test_proto(void *owner) { upb_status_errmsg(&status)); ASSERT(false); } + ASSERT(!upb_symtab_isfrozen(s)); + upb_symtab_freeze(s); + ASSERT(upb_symtab_isfrozen(s)); return s; } @@ -41,7 +45,8 @@ static void test_cycles() { // Test cycle detection by making a cyclic def's main refcount go to zero // and then be incremented to one again. - const upb_def *def = upb_symtab_lookup(s, "A", &def); + const upb_def *def = upb_symtab_lookup(s, "A"); + upb_def_ref(def, &def); ASSERT(def); ASSERT(upb_def_isfrozen(def)); upb_symtab_unref(s, &s); @@ -65,14 +70,12 @@ static void test_cycles() { static void test_fielddef_unref() { upb_symtab *s = load_test_proto(&s); - const upb_msgdef *md = upb_symtab_lookupmsg(s, "A", &md); + const upb_msgdef *md = upb_symtab_lookupmsg(s, "A"); const upb_fielddef *f = upb_msgdef_itof(md, 1); upb_fielddef_ref(f, &f); - // Unref symtab and msgdef; now fielddef is the only thing keeping the msgdef - // alive. + // Unref symtab; now fielddef is the only thing keeping the msgdef alive. upb_symtab_unref(s, &s); - upb_msgdef_unref(md, &md); // Check that md is still alive. ASSERT(strcmp(upb_msgdef_fullname(md), "A") == 0); @@ -141,29 +144,28 @@ static void test_replacement() { &s, NULL); upb_msgdef *m2 = upb_msgdef_newnamed("MyMessage2", &s); upb_enumdef *e = upb_enumdef_newnamed("MyEnum", &s); + upb_status status = UPB_STATUS_INIT; + ASSERT_STATUS(upb_enumdef_addval(e, "VAL1", 1, &status), &status); upb_def *newdefs[] = {UPB_UPCAST(m), UPB_UPCAST(m2), UPB_UPCAST(e)}; - upb_status status = UPB_STATUS_INIT; ASSERT_STATUS(upb_symtab_add(s, newdefs, 3, &s, &status), &status); // Try adding a new definition of MyEnum, MyMessage should get replaced with // a new version. - upb_enumdef *e2 = upb_enumdef_new(&s); - upb_enumdef_setfullname(e2, "MyEnum", NULL); + upb_enumdef *e2 = upb_enumdef_newnamed("MyEnum", &s); + ASSERT_STATUS(upb_enumdef_addval(e2, "VAL1", 1, &status), &status); upb_def *newdefs2[] = {UPB_UPCAST(e2)}; ASSERT_STATUS(upb_symtab_add(s, newdefs2, 1, &s, &status), &status); - const upb_msgdef *m3 = upb_symtab_lookupmsg(s, "MyMessage", &m3); + const upb_msgdef *m3 = upb_symtab_lookupmsg(s, "MyMessage"); ASSERT(m3); // Must be different because it points to MyEnum which was replaced. ASSERT(m3 != m); - upb_msgdef_unref(m3, &m3); - m3 = upb_symtab_lookupmsg(s, "MyMessage2", &m3); + m3 = upb_symtab_lookupmsg(s, "MyMessage2"); // Should be the same because it was not replaced, nor were any defs that // are reachable from it. ASSERT(m3 == m2); - upb_msgdef_unref(m3, &m3); upb_symtab_unref(s, &s); } diff --git a/tests/test_handlers.c b/tests/test_handlers.c index df22b8a..ad59465 100644 --- a/tests/test_handlers.c +++ b/tests/test_handlers.c @@ -18,7 +18,10 @@ static bool startmsg(void *c, const void *hd) { } static void test_error() { - upb_handlers *h = upb_handlers_new(GOOGLE_PROTOBUF_DESCRIPTORPROTO, &h); + const upb_symtab *s = upbdefs_google_protobuf_descriptor(&s); + upb_handlers *h = + upb_handlers_new(upbdefs_google_protobuf_DescriptorProto(s), &h); + upb_symtab_unref(s, &s); // Attempt to set the same handler twice causes error. ASSERT(upb_ok(upb_handlers_status(h))); diff --git a/tests/test_table.cc b/tests/test_table.cc index 747a97b..2d08abb 100644 --- a/tests/test_table.cc +++ b/tests/test_table.cc @@ -69,6 +69,25 @@ void test_strtable(const vector<std::string>& keys, uint32_t num_to_insert) { } ASSERT(all.empty()); + // Test iteration with resizes. + + for (int i = 0; i < 10; i++) { + for(upb_strtable_begin(&iter, &table); !upb_strtable_done(&iter); + upb_strtable_next(&iter)) { + // Even if we invalidate the iterator it should only return real elements. + const char *key = upb_strtable_iter_key(&iter); + std::string tmp(key, strlen(key)); + ASSERT(upb_value_getint32(upb_strtable_iter_value(&iter)) == m[tmp]); + + // Force a resize even though the size isn't changing. + // Also forces the table size to grow so some new buckets end up empty. + int new_lg2 = table.t.size_lg2 + 1; + // Don't use more than 64k tables, to avoid exhausting memory. + new_lg2 = UPB_MIN(new_lg2, 16); + upb_strtable_resize(&table, new_lg2); + } + } + upb_strtable_uninit(&table); } @@ -292,7 +311,9 @@ int run_tests(int argc, char *argv[]) { keys.push_back("google.protobuf.UninterpretedOption"); keys.push_back("google.protobuf.UninterpretedOption.NamePart"); - test_strtable(keys, 18); + for (int i = 0; i < 10; i++) { + test_strtable(keys, 18); + } int32_t *keys1 = get_contiguous_keys(8); test_inttable(keys1, 8, "Table size: 8, keys: 1-8 ===="); diff --git a/tests/test_vs_proto2.cc b/tests/test_vs_proto2.cc index dd20381..ed44a73 100644 --- a/tests/test_vs_proto2.cc +++ b/tests/test_vs_proto2.cc @@ -129,7 +129,8 @@ int run_tests(int argc, char *argv[]) MESSAGE_CIDENT msg1; MESSAGE_CIDENT msg2; - upb::reffed_ptr<const upb::Handlers> h(upb::googlepb::NewWriteHandlers(msg1)); + upb::reffed_ptr<const upb::Handlers> h( + upb::googlepb::WriteHandlers::New(msg1)); compare_metadata(msg1.GetDescriptor(), h->message_def()); @@ -146,7 +147,7 @@ int run_tests(int argc, char *argv[]) factory->GetPrototype(msg1.descriptor()); google::protobuf::Message* dyn_msg1 = prototype->New(); google::protobuf::Message* dyn_msg2 = prototype->New(); - h = upb::googlepb::NewWriteHandlers(*dyn_msg1); + h = upb::googlepb::WriteHandlers::New(*dyn_msg1); parse_and_compare(dyn_msg1, dyn_msg2, h.get(), str, len, false); parse_and_compare(dyn_msg1, dyn_msg2, h.get(), str, len, true); delete dyn_msg1; diff --git a/tools/dump_cinit.lua b/tools/dump_cinit.lua index c3104ee..86d605b 100644 --- a/tools/dump_cinit.lua +++ b/tools/dump_cinit.lua @@ -56,6 +56,15 @@ function const(obj, name, base) " constant for value: " .. val) end +function sortedkeys(tab) + arr = {} + for key in pairs(tab) do + arr[#arr + 1] = key + end + table.sort(arr) + return arr +end + function constlist(pattern) local ret = {} for k, v in pairs(upb) do @@ -84,9 +93,8 @@ end --]] local LinkTable = {} -function LinkTable:new(basename, types) +function LinkTable:new(types) local linktab = { - basename = basename, types = types, table = {}, -- ptr -> {type, 0-based offset} obj_arrays = {} -- Establishes the ordering for each object type @@ -111,7 +119,7 @@ end -- Returns a C symbol name for the given objtype and offset. function LinkTable:csym(objtype, offset) local typestr = assert(self.types[objtype]) - return string.format("%s_%s[%d]", self.basename, typestr, offset) + return string.format("%s[%d]", typestr, offset) end -- Returns the address of the given C object. @@ -119,7 +127,7 @@ function LinkTable:addr(obj) if obj == upbtable.NULL then return "NULL" else - local tabent = assert(self.table[obj], "unknown object") + local tabent = assert(self.table[obj], "unknown object: " .. tostring(obj)) return "&" .. self:csym(tabent[1], tabent[2]) end end @@ -246,27 +254,72 @@ local function emit_file_warning(append) append('// regenerated.\n\n') end +local function join(...) + return table.concat({...}, ".") +end + +local function split(str) + local ret = {} + for word in string.gmatch(str, "%w+") do + table.insert(ret, word) + end + return ret +end + +local function to_cident(...) + return string.gsub(join(...), "[%./]", "_") +end + +local function to_preproc(...) + return string.upper(to_cident(...)) +end + +local function getpackage(name) + local package_end = 0 + for i=1,string.len(name) do + if string.byte(name, i) == string.byte(".", 1) then + package_end = i - 1 + end + end + return string.sub(name, 1, package_end) +end + +local function relname(name) + local package = getpackage(name) + return string.sub(name, string.len(package) + 2) +end + +local function start_namespace(package, append) + local package_components = split(package) + for _, component in ipairs(package_components) do + append("namespace %s {\n", component) + end +end + +local function end_namespace(package, append) + local package_components = split(package) + for i=#package_components,1,-1 do + append("} // namespace %s\n", package_components[i]) + end +end + --[[ Top-level, exported dumper functions --]] -local function dump_defs_c(symtab, basename, append) - -- Add fielddefs for any msgdefs passed in. - local fielddefs = {} - for _, def in ipairs(symtab:getdefs(upb.DEF_MSG)) do - for field in def:fields() do - fielddefs[#fielddefs + 1] = field +local function dump_defs_c(symtab, basename, namespace, append) + local defs = {} + for def in symtab:defs(upb.DEF_ANY) do + defs[#defs + 1] = def + if (def:def_type() == upb.DEF_MSG) then + for field in def:fields() do + defs[#defs + 1] = field + end end end - -- Get a list of all defs and add fielddefs to it. - local defs = symtab:getdefs(upb.DEF_ANY) - for _, fielddef in ipairs(fielddefs) do - defs[#defs + 1] = fielddef - end - -- Sort all defs by (type, name). -- This gives us a linear ordering that we can use to create offsets into -- shared arrays like REFTABLES, hash table entries, and arrays. @@ -279,14 +332,14 @@ local function dump_defs_c(symtab, basename, append) ) -- Perform pre-pass to build the link table. - local linktab = LinkTable:new(basename, { + local linktab = LinkTable:new{ [upb.DEF_MSG] = "msgs", [upb.DEF_FIELD] = "fields", [upb.DEF_ENUM] = "enums", intentries = "intentries", strentries = "strentries", arrays = "arrays", - }) + } local reftable_count = 0 for _, def in ipairs(defs) do @@ -307,15 +360,22 @@ local function dump_defs_c(symtab, basename, append) end end + -- Symbol table entries. + reftable_count = reftable_count + 2 + for _, e in ipairs(upbtable.symtab_symtab(symtab).entries) do + linktab:add("strentries", e.ptr, e) + end + -- Emit forward declarations. emit_file_warning(append) - append('#include "upb/def.h"\n\n') - append("const upb_msgdef %s;\n", linktab:cdecl(upb.DEF_MSG)) - append("const upb_fielddef %s;\n", linktab:cdecl(upb.DEF_FIELD)) - append("const upb_enumdef %s;\n", linktab:cdecl(upb.DEF_ENUM)) - append("const upb_tabent %s;\n", linktab:cdecl("strentries")) - append("const upb_tabent %s;\n", linktab:cdecl("intentries")) - append("const _upb_value %s;\n", linktab:cdecl("arrays")) + append('#include "upb/def.h"\n') + append('#include "upb/symtab.h"\n\n') + append("static const upb_msgdef %s;\n", linktab:cdecl(upb.DEF_MSG)) + append("static const upb_fielddef %s;\n", linktab:cdecl(upb.DEF_FIELD)) + append("static const upb_enumdef %s;\n", linktab:cdecl(upb.DEF_ENUM)) + append("static const upb_tabent %s;\n", linktab:cdecl("strentries")) + append("static const upb_tabent %s;\n", linktab:cdecl("intentries")) + append("static const _upb_value %s;\n", linktab:cdecl("arrays")) append("\n") append("#ifdef UPB_DEBUG_REFS\n") append("static upb_inttable reftables[%d];\n", reftable_count) @@ -327,7 +387,7 @@ local function dump_defs_c(symtab, basename, append) local reftable = 0 - append("const upb_msgdef %s = {\n", linktab:cdecl(upb.DEF_MSG)) + append("static const upb_msgdef %s = {\n", linktab:cdecl(upb.DEF_MSG)) for m in linktab:objs(upb.DEF_MSG) do local tables = gettables(m) -- UPB_MSGDEF_INIT(name, selector_count, submsg_field_count, itof, ntof, @@ -344,7 +404,7 @@ local function dump_defs_c(symtab, basename, append) end append("};\n\n") - append("const upb_fielddef %s = {\n", linktab:cdecl(upb.DEF_FIELD)) + append("static const upb_fielddef %s = {\n", linktab:cdecl(upb.DEF_FIELD)) for f in linktab:objs(upb.DEF_FIELD) do local subdef = "NULL" if f:has_subdef() then @@ -376,7 +436,7 @@ local function dump_defs_c(symtab, basename, append) end append("};\n\n") - append("const upb_enumdef %s = {\n", linktab:cdecl(upb.DEF_ENUM)) + append("static const upb_enumdef %s = {\n", linktab:cdecl(upb.DEF_ENUM)) for e in linktab:objs(upb.DEF_ENUM) do local tables = gettables(e) -- UPB_ENUMDEF_INIT(name, ntoi, iton, defaultval) @@ -392,24 +452,37 @@ local function dump_defs_c(symtab, basename, append) end append("};\n\n") - append("const upb_tabent %s = {\n", linktab:cdecl("strentries")) + append("static const upb_tabent %s = {\n", linktab:cdecl("strentries")) for ent in linktab:objs("strentries") do append(dumper:tabent(ent)) end append("};\n\n"); - append("const upb_tabent %s = {\n", linktab:cdecl("intentries")) + append("static const upb_tabent %s = {\n", linktab:cdecl("intentries")) for ent in linktab:objs("intentries") do append(dumper:tabent(ent)) end append("};\n\n"); - append("const _upb_value %s = {\n", linktab:cdecl("arrays")) + append("static const _upb_value %s = {\n", linktab:cdecl("arrays")) for ent in linktab:objs("arrays") do append(dumper:arrayval(ent)) end append("};\n\n"); + append("static const upb_symtab symtab = " .. + "UPB_SYMTAB_INIT(%s, &reftables[%d], &reftables[%d]);\n\n", + dumper:strtable(upbtable.symtab_symtab(symtab)), + reftable, + reftable + 1); + + -- TODO: don't hardcode this. + append("const upb_symtab *%s_%s(const void *owner) " .. + "{\n", namespace, to_cident(basename)) + append(" upb_symtab_ref(&symtab, owner);\n") + append(" return &symtab;\n") + append("}\n\n") + append("#ifdef UPB_DEBUG_REFS\n") append("static upb_inttable reftables[%d] = {\n", reftable_count) for i = 1,reftable_count do @@ -421,31 +494,52 @@ local function dump_defs_c(symtab, basename, append) return linktab end -local function join(...) - return table.concat({...}, ".") -end +local function dump_defs_for_type(format, defs, namespace, append) + local sorted_defs = {} -local function to_cident(...) - return string.gsub(join(...), "%.", "_") -end + for def in defs do + sorted_defs[#sorted_defs + 1] = def + end -local function to_preproc(...) - return string.upper(to_cident(...)) + table.sort(sorted_defs, + function(a, b) return a:full_name() < b:full_name() end) + + for _, def in ipairs(sorted_defs) do + append(format, namespace, to_cident(def:full_name()), def:full_name()) + end + + append("\n") end -local function dump_defs_h(symtab, basename, append, linktab) - local ucase_basename = string.upper(basename) +local function dump_defs_h(symtab, basename, namespace, append, linktab) + local basename_preproc = to_preproc(basename) + append("// This file contains accessors for a set of compiled-in defs.\n") + append("// Note that unlike Google's protobuf, it does *not* define\n") + append("// generated classes or any other kind of data structure for\n") + append("// actually storing protobufs. It only contains *defs* which\n") + append("// let you reflect over a protobuf *schema*.\n") + append("//\n") emit_file_warning(append) - append('#ifndef %s_UPB_H_\n', ucase_basename) - append('#define %s_UPB_H_\n\n', ucase_basename) - append('#include "upb/def.h"\n\n') + append('#ifndef %s_UPB_H_\n', basename_preproc) + append('#define %s_UPB_H_\n\n', basename_preproc) + append('#include "upb/def.h"\n') + append('#include "upb/symtab.h"\n\n') append('#ifdef __cplusplus\n') append('extern "C" {\n') append('#endif\n\n') + local packages = {} + for def in symtab:defs(upb.DEF_ANY) do + if def:def_type() == upb.DEF_MSG then + packages[def:full_name()] = true + else + packages[getpackage(def:full_name())] = true + end + end + -- Dump C enums for proto enums. append("// Enums\n\n") - for _, def in ipairs(symtab:getdefs(upb.DEF_ENUM)) do + for def in symtab:defs(upb.DEF_ENUM) do local cident = to_cident(def:full_name()) append('typedef enum {\n') for k, v in def:values() do @@ -454,53 +548,116 @@ local function dump_defs_h(symtab, basename, append, linktab) append('} %s;\n\n', cident) end - -- Dump macros for referring to specific defs. - append("// Do not refer to these forward declarations; use the constants\n") - append("// below.\n") - append("extern const upb_msgdef %s;\n", linktab:cdecl(upb.DEF_MSG)) - append("extern const upb_fielddef %s;\n", linktab:cdecl(upb.DEF_FIELD)) - append("extern const upb_enumdef %s;\n\n", linktab:cdecl(upb.DEF_ENUM)) - append("// Constants for references to defs.\n") - append("// We hide these behind macros to decouple users from the\n") - append("// details of how we have statically defined them (ie. whether\n") - append("// each def has its own symbol or lives in an array of defs).\n") - for def in linktab:objs(upb.DEF_MSG) do - append("#define %s %s\n", to_preproc(def:full_name()), linktab:addr(def)) - end + append("const upb_symtab *%s_%s(const void *owner);" .. + "\n\n", namespace, to_cident(basename)) + + append("// MessageDefs\n") + dump_defs_for_type( + "UPB_INLINE const upb_msgdef *%s_%s(const upb_symtab *s) {\n" .. + " const upb_msgdef *m = upb_symtab_lookupmsg(s, \"%s\");\n" .. + " assert(m);\n" .. + " return m;\n" .. + "}\n", + symtab:defs(upb.DEF_MSG), + namespace, append) + append("\n") - local selector_types = constlist("HANDLER_") - local selectors = {} + append("// EnumDefs\n") + dump_defs_for_type( + "UPB_INLINE const upb_enumdef *%s_%s(const upb_symtab *s) {\n" .. + " const upb_enumdef *e = upb_symtab_lookupenum(s, \"%s\");\n" .. + " assert(e);\n" .. + " return e;\n" .. + "}\n", + symtab:defs(upb.DEF_ENUM), + namespace, append) + + -- fields + local fields = {} for f in linktab:objs(upb.DEF_FIELD) do - for sel_type_name, sel_type_value in pairs(selector_types) do - sel_type_name = sel_type_name:gsub("HANDLER_", "") - local sel = f:getsel(sel_type_value) - if sel then - local symname = f:containing_type():full_name() .. "." .. f:name() .. - "." .. sel_type_name - selectors[#selectors + 1] = {to_preproc(symname), sel} - end - end + local symname = f:containing_type():full_name() .. "." .. f:name() + fields[#fields + 1] = {to_cident(symname), f} end - table.sort(selectors, function(a, b) return a[1] < b[1] end) + table.sort(fields, function(a, b) return a[1] < b[1] end) - append("// Selector definitions.\n") - for _, selector in ipairs(selectors) do - append("#define %s %d\n", selector[1], selector[2]) + for _, field in ipairs(fields) do + local f = field[2] + append("UPB_INLINE const upb_fielddef *%s_%s(const upb_symtab *s) {" .. + " return upb_msgdef_itof(%s_%s(s), %d); }\n", + namespace, field[1], namespace, + to_cident(f:containing_type():full_name()), f:number()) end - append("\n") + append("\n") append('#ifdef __cplusplus\n') append('}; // extern "C"\n') append('#endif\n\n') - append('#endif // %s_UPB_H_\n', ucase_basename) + append("#ifdef __cplusplus\n\n") + + append("namespace %s {\n", namespace) + + start_namespace(basename, append) + append("inline upb::reffed_ptr<const upb::SymbolTable> SymbolTable() {\n") + append(" const upb::SymbolTable* s = %s_google_protobuf_descriptor(&s);\n", + namespace) + append(" return upb::reffed_ptr<const upb::SymbolTable>(s, &s);\n") + append("}\n") + end_namespace(basename, append) + append("\n") + + + append([[#define RETURN_REFFED(type, func) \ + const type* obj = func(%s::google::protobuf::descriptor::SymbolTable().get()); \ + return upb::reffed_ptr<const type>(obj); + +]], namespace) + + for _, package in ipairs(sortedkeys(packages)) do + start_namespace(package, append) + + local def = symtab:lookup(package) + if def then + assert(def:def_type() == upb.DEF_MSG) + append("inline upb::reffed_ptr<const upb::MessageDef> MessageDef() " .. + "{ RETURN_REFFED(upb::MessageDef, %s_%s) }\n", + namespace, to_cident(def:full_name())) + end + + for f in linktab:objs(upb.DEF_FIELD) do + if f:containing_type():full_name() == package then + append("inline upb::reffed_ptr<const upb::FieldDef> %s() " .. + "{ RETURN_REFFED(upb::FieldDef, %s_%s_%s) }\n", + f:name(), namespace, to_cident(f:containing_type():full_name()), + f:name()) + end + end + + for e in linktab:objs(upb.DEF_ENUM) do + if getpackage(e:full_name()) == package then + append("inline upb::reffed_ptr<const upb::EnumDef> %s() " .. + "{ RETURN_REFFED(upb::EnumDef, %s_%s) }\n", + relname(e:full_name()), namespace, to_cident(e:full_name())) + end + end + + end_namespace(package, append) + append("\n") + end + + append("} // namespace %s\n\n\n", namespace) + + append("#undef RETURN_REFFED\n") + append("#endif // __cplusplus\n\n") + + append('#endif // %s_UPB_H_\n', basename_preproc) end function export.dump_defs(symtab, basename, append_h, append_c) - local linktab = dump_defs_c(symtab, basename, append_c) - dump_defs_h(symtab, basename, append_h, linktab) + local linktab = dump_defs_c(symtab, basename, "upbdefs", append_c) + dump_defs_h(symtab, basename, "upbdefs", append_h, linktab) end return export diff --git a/tools/test_cinit.lua b/tools/test_cinit.lua index 3ed77b5..c181363 100644 --- a/tools/test_cinit.lua +++ b/tools/test_cinit.lua @@ -42,28 +42,19 @@ if arg[1] == "generate" then local appendc = dump_cinit.file_appender(f) local appendh = dump_cinit.file_appender(f_h) f:write('#include "lua.h"\n') - f:write('#define ELEMENTS(array) (sizeof(array)/sizeof(*array))\n') f:write('#include "upb/bindings/lua/upb.h"\n') - dump_cinit.dump_defs(symtab, "test", appendh, appendc) + dump_cinit.dump_defs(symtab, "testdefs", appendh, appendc) f:write([[int luaopen_staticdefs(lua_State *L) { - lua_newtable(L); - for (int i = 0; i < ELEMENTS(test_msgs); i++) { - lupb_def_pushnewrapper(L, UPB_UPCAST(&test_msgs[i]), NULL); - lua_rawseti(L, -2, i + 1); - } - for (int i = 0; i < ELEMENTS(test_enums); i++) { - lupb_def_pushnewrapper(L, UPB_UPCAST(&test_enums[i]), NULL); - lua_rawseti(L, -2, ELEMENTS(test_msgs) + i + 1); - } + const upb_symtab *s = upbdefs_testdefs(&s); + lupb_symtab_pushwrapper(L, s, &s); return 1; }]]) f_h:close() f:close() elseif arg[1] == "test" then - local staticdefs = require "staticdefs" - - local msg = assert(staticdefs[1]) - local enum = assert(staticdefs[2]) + local symtab = require "staticdefs" + local msg = assert(symtab:lookup("MyMessage")) + local enum = assert(symtab:lookup("MyEnum")) local f2 = assert(msg:field("field2")) assert(msg:def_type() == upb.DEF_MSG) assert(msg:full_name() == "MyMessage") diff --git a/upb/bindings/googlepb/bridge.cc b/upb/bindings/googlepb/bridge.cc index c8e3474..a666ff6 100644 --- a/upb/bindings/googlepb/bridge.cc +++ b/upb/bindings/googlepb/bridge.cc @@ -16,8 +16,8 @@ #include <map> #include <string> #include "upb/def.h" -#include "upb/bindings/googlepb/proto1.h" -#include "upb/bindings/googlepb/proto2.h" +#include "upb/bindings/googlepb/proto1.int.h" +#include "upb/bindings/googlepb/proto2.int.h" #include "upb/handlers.h" #define ASSERT_STATUS(status) do { \ @@ -39,31 +39,24 @@ namespace goog = ::proto2; namespace goog = ::google::protobuf; #endif -namespace { - -const goog::Message* GetPrototype(const goog::Message& m, - const goog::FieldDescriptor* f) { - const goog::Message* ret = NULL; -#ifdef UPB_GOOGLE3 - ret = upb::google::GetProto1WeakPrototype(m, f); - if (ret) return ret; -#endif +namespace upb { +namespace googlepb { - if (f->cpp_type() == goog::FieldDescriptor::CPPTYPE_MESSAGE) { - ret = upb::google::GetFieldPrototype(m, f); +const goog::Message* TryGetFieldPrototype(const goog::Message& m, + const goog::FieldDescriptor* f) { + const goog::Message* ret = upb::googlepb::GetProto2FieldPrototype(m, f); #ifdef UPB_GOOGLE3 - if (!ret) ret = upb::google::GetProto1FieldPrototype(m, f); + if (!ret) ret = upb::googlepb::GetProto1FieldPrototype(m, f); #endif - assert(ret); - } return ret; } -} // namespace - -namespace upb { -namespace googlepb { - +const goog::Message* GetFieldPrototype(const goog::Message& m, + const goog::FieldDescriptor* f) { + const goog::Message* ret = TryGetFieldPrototype(m, f); + assert(ret); + return ret; +} /* DefBuilder ****************************************************************/ @@ -117,20 +110,11 @@ const MessageDef* DefBuilder::GetMaybeUnfrozenMessageDef( reffed_ptr<FieldDef> DefBuilder::NewFieldDef(const goog::FieldDescriptor* f, const goog::Message* m) { - const goog::Message* subm = NULL; - const goog::Message* weak_prototype = NULL; - - if (m) { -#ifdef UPB_GOOGLE3 - weak_prototype = upb::google::GetProto1WeakPrototype(*m, f); -#endif - subm = GetPrototype(*m, f); - } - reffed_ptr<FieldDef> upb_f(FieldDef::New()); Status status; upb_f->set_number(f->number(), &status); upb_f->set_label(FieldDef::ConvertLabel(f->label())); + upb_f->set_descriptor_type(FieldDef::ConvertDescriptorType(f->type())); #ifdef UPB_GOOGLE3 upb_f->set_lazy(f->options().lazy()); #endif @@ -142,11 +126,19 @@ reffed_ptr<FieldDef> DefBuilder::NewFieldDef(const goog::FieldDescriptor* f, upb_f->set_name(f->name(), &status); } - // For weak fields, weak_prototype will be non-NULL even though the proto2 - // descriptor does not indicate a submessage field. - upb_f->set_descriptor_type(weak_prototype - ? UPB_DESCRIPTOR_TYPE_MESSAGE - : FieldDef::ConvertDescriptorType(f->type())); + const goog::Message* subm = NULL; + + if (m) { + subm = TryGetFieldPrototype(*m, f); + + if (upb_f->type() == UPB_TYPE_MESSAGE) { + assert(subm); + } else if (subm) { + // Weak field: subm will be weak prototype even though the proto2 + // descriptor does not indicate a submessage field. + upb_f->set_descriptor_type(UPB_DESCRIPTOR_TYPE_MESSAGE); + } + } switch (upb_f->type()) { case UPB_TYPE_INT32: @@ -213,6 +205,35 @@ const MessageDef* DefBuilder::GetMessageDefExpandWeak( } +/* WriteHandlers *************************************************************/ + +// static +bool WriteHandlers::AddFieldHandler(const goog::Message& m, + const goog::FieldDescriptor* f, + upb::Handlers* h) { + const FieldDef* upb_f = h->message_def()->FindFieldByNumber(f->number()); + if (!upb_f) return false; + if (upb::googlepb::TrySetWriteHandlers(f, m, upb_f, h)) return true; +#ifdef UPB_GOOGLE3 + if (upb::googlepb::TrySetProto1WriteHandlers(f, m, upb_f, h)) return true; +#endif + + // Unsupported reflection class. + // + // Should we fall back to using the public Reflection interface in this + // case? It's unclear whether it's supported behavior for users to + // create their own Reflection classes. + return false; +} + +// static +upb::reffed_ptr<const upb::Handlers> WriteHandlers::New( + const goog::Message& m) { + CodeCache cache; + return upb::reffed_ptr<const upb::Handlers>(cache.GetWriteHandlers(m)); +} + + /* CodeCache *****************************************************************/ const Handlers* CodeCache::GetMaybeUnfrozenWriteHandlers( @@ -234,21 +255,11 @@ const Handlers* CodeCache::GetMaybeUnfrozenWriteHandlers( } assert(proto2_f); - if (!upb::google::TrySetWriteHandlers(proto2_f, m, upb_f, h) -#ifdef UPB_GOOGLE3 - && !upb::google::TrySetProto1WriteHandlers(proto2_f, m, upb_f, h) -#endif - ) { - // Unsupported reflection class. - // - // Should we fall back to using the public Reflection interface in this - // case? It's unclear whether it's supported behavior for users to - // create their own Reflection classes. - assert(false); - } + bool ok = WriteHandlers::AddFieldHandler(m, proto2_f, h); + UPB_ASSERT_VAR(ok, ok); if (upb_f->type() == UPB_TYPE_MESSAGE) { - const goog::Message* prototype = GetPrototype(m, proto2_f); + const goog::Message* prototype = GetFieldPrototype(m, proto2_f); assert(prototype); const upb::Handlers* sub_handlers = GetMaybeUnfrozenWriteHandlers(upb_f->message_subdef(), *prototype); @@ -269,10 +280,5 @@ const Handlers* CodeCache::GetWriteHandlers(const goog::Message& m) { return ret; } -upb::reffed_ptr<const upb::Handlers> NewWriteHandlers(const goog::Message& m) { - CodeCache cache; - return upb::reffed_ptr<const upb::Handlers>(cache.GetWriteHandlers(m)); -} - } // namespace googlepb } // namespace upb diff --git a/upb/bindings/googlepb/bridge.h b/upb/bindings/googlepb/bridge.h index 9eed51b..9878247 100644 --- a/upb/bindings/googlepb/bridge.h +++ b/upb/bindings/googlepb/bridge.h @@ -63,13 +63,6 @@ namespace upb { namespace googlepb { -// Returns a upb::Handlers object that can be used to populate a proto2::Message -// object of the same type as "m." For more control over handler caching and -// reuse, instantiate a CodeCache object below. -upb::reffed_ptr<const upb::Handlers> NewWriteHandlers(const proto2::Message& m); -upb::reffed_ptr<const upb::Handlers> NewWriteHandlers( - const ::google::protobuf::Message& m); - // Builds upb::Defs from proto2::Descriptors, and caches all built Defs for // reuse. CodeCache (below) uses this internally; there is no need to use this // class directly unless you only want Defs without corresponding Handlers. @@ -159,6 +152,41 @@ class DefBuilder { std::vector<Def*> to_freeze_; }; +// Handlers to populate a proto2::Message with incoming data. +class WriteHandlers { + public: + // Returns a upb::Handlers object that can be used to populate a + // proto2::Message object of the same type as "m." For more control over + // handler caching and reuse, instantiate a CodeCache object below. + static upb::reffed_ptr<const upb::Handlers> New(const proto2::Message& m); + static upb::reffed_ptr<const upb::Handlers> New( + const ::google::protobuf::Message& m); + + // TODO(haberman): add an interface that takes a list of field paths, + // something like: + // + // // Returns a Handlers instance that will populate the given field paths + // // only, dropping data for all other field paths on the floor. + // static upb::reffed_ptr<const upb::Handlers> New( + // const proto2::Message& m, + // const std::vector<std::string>& paths); + + // A lower-level interface with field granularity. + // + // Adds a handler to the given upb::Handlers for parsing the given field. If + // you only want to write certain fields into the proto2 message at parse + // time, call these methods ONLY for the fields you want to parse. + // + // The given field can be either a regular field or an extension, as long as + // its containing_type() matches this message. + static bool AddFieldHandler(const proto2::Message& m, + const proto2::FieldDescriptor* f, + upb::Handlers* h); + static bool AddFieldHandler(const ::google::protobuf::Message& m, + const ::google::protobuf::FieldDescriptor* f, + upb::Handlers* h); +}; + // Builds and caches upb::Handlers for populating proto2 generated classes. // // This class is NOT thread-safe. @@ -199,6 +227,29 @@ class CodeCache { std::vector<Handlers*> to_freeze_; }; +// Functions for getting prototypes; these are only necessary if you are +// building handlers manually, field by field. + +// Given a message and a field descriptor for that message, returns a prototype +// for the submessage. Requires that this is a submessage field or a weak +// field. +const proto2::Message* GetFieldPrototype(const proto2::Message& m, + const proto2::FieldDescriptor* f); +const ::google::protobuf::Message* GetFieldPrototype( + const ::google::protobuf::Message& m, + const ::google::protobuf::FieldDescriptor* f); + +// Given a message and a field descriptor for that message, returns a prototype +// for the submessage, or NULL if this is not a submessage field or a weak +// field. If this returns non-NULL even though the descriptor's type is not a +// submessage, then this is a weak field. If you don't know what a weak field +// is, you are probably not using one. +const proto2::Message* TryGetFieldPrototype(const proto2::Message& m, + const proto2::FieldDescriptor* f); +const ::google::protobuf::Message* TryGetFieldPrototype( + const ::google::protobuf::Message& m, + const ::google::protobuf::FieldDescriptor* f); + } // namespace googlepb } // namespace upb diff --git a/upb/bindings/googlepb/proto1.cc b/upb/bindings/googlepb/proto1.cc index c317cdf..0b46fed 100644 --- a/upb/bindings/googlepb/proto1.cc +++ b/upb/bindings/googlepb/proto1.cc @@ -16,13 +16,20 @@ // dynamic_cast<> in this file: // https://groups.google.com/a/google.com/d/msg/c-style/7Zp_XCX0e7s/I6dpzno4l-MJ -#include "upb/bindings/googlepb/proto1.h" +#include "upb/bindings/googlepb/proto1.int.h" #include <memory> +// TEMPORARY measure until we update the friend declarations in proto1. +// Can't do in a single CL because of components. +#define private public +#define protected public #include "net/proto2/public/repeated_field.h" #include "net/proto/internal_layout.h" #include "net/proto/proto2_reflection.h" +#undef private +#undef protected + #include "upb/def.h" #include "upb/handlers.h" #include "upb/shim/shim.h" @@ -36,7 +43,7 @@ template <class T> static T* GetPointer(void* message, size_t offset) { } namespace upb { -namespace google { +namespace googlepb { class P2R_Handlers { public: @@ -466,18 +473,18 @@ class P2R_Handlers { bool TrySetProto1WriteHandlers(const proto2::FieldDescriptor* proto2_f, const proto2::Message& m, const upb::FieldDef* upb_f, upb::Handlers* h) { - return P2R_Handlers::TrySet(proto2_f, m, upb_f, h); -} - -const proto2::Message* GetProto1WeakPrototype( - const proto2::Message& m, const proto2::FieldDescriptor* f) { - return P2R_Handlers::GetWeakPrototype(m, f); + return googlepb::P2R_Handlers::TrySet(proto2_f, m, upb_f, h); } const proto2::Message* GetProto1FieldPrototype( const proto2::Message& m, const proto2::FieldDescriptor* f) { - return P2R_Handlers::GetFieldPrototype(m, f); + const proto2::Message *weak = googlepb::P2R_Handlers::GetWeakPrototype(m, f); + if (weak) return weak; + if (f->cpp_type() != proto2::FieldDescriptor::CPPTYPE_MESSAGE) { + return NULL; + } + return googlepb::P2R_Handlers::GetFieldPrototype(m, f); } -} // namespace google +} // namespace googlepb } // namespace upb diff --git a/upb/bindings/googlepb/proto1.h b/upb/bindings/googlepb/proto1.int.h index eb550ac..64ebb2f 100644 --- a/upb/bindings/googlepb/proto1.h +++ b/upb/bindings/googlepb/proto1.int.h @@ -7,8 +7,7 @@ // Support for registering field handlers that can write into a legacy proto1 // message. This functionality is only needed inside Google. // -// This is a low-level interface; the high-level interface in google.h is -// more user-friendly. +// This is an internal-only interface. #ifndef UPB_GOOGLE_PROTO1_H_ #define UPB_GOOGLE_PROTO1_H_ @@ -24,7 +23,7 @@ class Handlers; } namespace upb { -namespace google { +namespace googlepb { // Sets field handlers in the given Handlers object for writing to a single // field (as described by "proto2_f" and "upb_f") into a message constructed @@ -35,17 +34,12 @@ bool TrySetProto1WriteHandlers(const proto2::FieldDescriptor* proto2_f, const proto2::Message& prototype, const upb::FieldDef* upb_f, upb::Handlers* h); -// Returns a prototype for the given field in "m", if it is weak. The returned -// message could be the linked-in message type or OpaqueMessage, if the weak -// message is *not* linked in. Otherwise returns NULL. -const proto2::Message* GetProto1WeakPrototype(const proto2::Message& m, - const proto2::FieldDescriptor* f); - -// Returns a prototype for the given non-weak field in "m". +// Returns a prototype for the given this (possibly-weak) field. Returns NULL +// if this is not a submessage field of any kind (weak or no). const proto2::Message* GetProto1FieldPrototype( const proto2::Message& m, const proto2::FieldDescriptor* f); -} // namespace google +} // namespace googlepb } // namespace upb #endif // UPB_GOOGLE_PROTO1_H_ diff --git a/upb/bindings/googlepb/proto2.cc b/upb/bindings/googlepb/proto2.cc index 04e504b..224e2b9 100644 --- a/upb/bindings/googlepb/proto2.cc +++ b/upb/bindings/googlepb/proto2.cc @@ -13,10 +13,12 @@ // and protobuf opensource both in a single binary without the two conflicting. // However we must be careful not to violate the ODR. -#include "upb/bindings/googlepb/proto2.h" +#include "upb/bindings/googlepb/proto2.int.h" + +#include <map> #include "upb/def.h" -#include "upb/bindings/googlepb/proto1.h" +#include "upb/bindings/googlepb/proto1.int.h" #include "upb/handlers.h" #include "upb/shim/shim.h" #include "upb/sink.h" @@ -237,10 +239,26 @@ case goog::FieldDescriptor::cpptype: \ return (r->has_bits_offset_ * 8) + f->index(); } +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + static size_t GetOneofDiscriminantOffset( + const goog::FieldDescriptor* f, + const goog::internal::GeneratedMessageReflection* r) { + assert(f->containing_oneof()); + return r->oneof_case_offset_ + f->containing_oneof()->index(); + } +#endif + static uint16_t GetOffset( const goog::FieldDescriptor* f, const goog::internal::GeneratedMessageReflection* r) { - return r->offsets_[f->index()]; + int index = f->index(); +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + if (f->containing_oneof()) { + index = + f->containing_type()->field_count() + f->containing_oneof()->index(); + } +#endif + return r->offsets_[index]; } class FieldOffset { @@ -274,6 +292,154 @@ case goog::FieldDescriptor::cpptype: \ int8_t mask_; }; +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + class OneofFieldData { + public: + OneofFieldData(const goog::FieldDescriptor* f, + const goog::internal::GeneratedMessageReflection* r) + : field_number_offset_(GetOneofDiscriminantOffset(f, r)), + field_number_(f->number()) { + const goog::OneofDescriptor* oneof = f->containing_oneof(); + + // Determine the type of each discriminant value, so we know what kind of + // value to delete if we are changing the type. + // + // For example, we may find that the oneof has three possible values: an + // int32, a message, and a string. For the int32 there is nothing to + // delete, but the message and the string need to be deleted when we + // switch to another oneof type, to avoid leaking it. + // + // TODO(haberman): share this map of types between all fields in the + // oneof. Right now we duplicate it for each one, which is wasteful. + for (int i = 0; i < oneof->field_count(); i++) { + const goog::FieldDescriptor* oneof_f = oneof->field(i); + OneofType& type = types_[oneof_f->number()]; + + switch (oneof_f->cpp_type()) { + case goog::FieldDescriptor::CPPTYPE_STRING: + type = GetTypeForString(oneof_f); + break; + case goog::FieldDescriptor::CPPTYPE_MESSAGE: +#ifdef UPB_GOOGLE3 + if (oneof_f->options().lazy()) { + type = ONEOF_TYPE_LAZYFIELD; + break; + } +#endif + type = ONEOF_TYPE_MESSAGE; + break; + + default: + type = ONEOF_TYPE_NONE; + break; + } + } + + // "0" indicates that the field is not set. + types_[0] = ONEOF_TYPE_NONE; + } + + int32_t* GetFieldPointer(goog::Message* message) const { + return GetPointer<int32_t>(message, field_number_offset_); + } + + // Returns whether this is different than the previous value of the + // field_number; this implies that the current value was freed (if + // necessary) and the caller should allocate a new instance. + bool SetOneofHas(goog::Message* m, const FieldOffset* ofs) const { + int32_t *field_number = GetFieldPointer(m); + if (*field_number == field_number_) { + return false; + } else { + switch (types_.at(*field_number)) { + case ONEOF_TYPE_NONE: + break; + case ONEOF_TYPE_STRING: + delete *ofs->GetFieldPointer<std::string*>(m); + break; + case ONEOF_TYPE_MESSAGE: + delete *ofs->GetFieldPointer<goog::Message*>(m); + break; +#ifdef UPB_GOOGLE3 + case ONEOF_TYPE_GLOBALSTRING: + delete *ofs->GetFieldPointer<string*>(m); + break; + case ONEOF_TYPE_CORD: + delete *ofs->GetFieldPointer<Cord*>(m); + break; + case ONEOF_TYPE_STRINGPIECE: + delete *ofs->GetFieldPointer<goog::internal::StringPieceField*>(m); + break; + case ONEOF_TYPE_LAZYFIELD: + delete *ofs->GetFieldPointer<goog::internal::LazyField*>(m); + break; +#endif + } + *field_number = field_number_; + return true; + } + } + + private: + enum OneofType { + ONEOF_TYPE_NONE, + ONEOF_TYPE_STRING, + ONEOF_TYPE_MESSAGE, +#ifdef UPB_GOOGLE3 + ONEOF_TYPE_GLOBALSTRING, + ONEOF_TYPE_CORD, + ONEOF_TYPE_STRINGPIECE, + ONEOF_TYPE_LAZYFIELD, +#endif + }; + + OneofType GetTypeForString(const goog::FieldDescriptor* f) { + switch (f->options().ctype()) { + case goog::FieldOptions::STRING: +#ifdef UPB_GOOGLE3 + return ONEOF_TYPE_GLOBALSTRING; +#else + return ONEOF_TYPE_STRING; +#endif + +#ifdef UPB_GOOGLE3 + case goog::FieldOptions::CORD: + return ONEOF_TYPE_CORD; + case goog::FieldOptions::STRING_PIECE: + return ONEOF_TYPE_STRINGPIECE; +#endif + default: + assert(false); + return ONEOF_TYPE_NONE; + } + } + + // Offset of the uint32 that specifies which field is set. + size_t field_number_offset_; + + // Field number for this field. + int32_t field_number_; + + // The types of the oneof fields, indexed by field_number_. + std::map<int32_t, OneofType> types_; + }; + + class OneofFieldHandlerData : public FieldOffset { + public: + OneofFieldHandlerData(const goog::FieldDescriptor* f, + const goog::internal::GeneratedMessageReflection* r) + : FieldOffset(f, r), + oneof_data_(f, r) {} + + bool SetOneofHas(goog::Message* message) const { + return oneof_data_.SetOneofHas(message, this); + } + + public: + OneofFieldData oneof_data_; + }; +#endif // GOOGLE_PROTOBUF_HAS_ONEOF + class ExtensionFieldData { public: ExtensionFieldData( @@ -352,7 +518,16 @@ case goog::FieldDescriptor::cpptype: \ CHKRET(h->SetValueHandler<T>( f, UpbBindT(SetPrimitiveExtension<T>, data.release()))); } - } else { + } +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + else if (proto2_f->containing_oneof()) { + assert(!proto2_f->is_repeated()); + CHKRET(h->SetValueHandler<T>( + f, UpbBindT(SetOneofPrimitive<T>, + new OneofFieldHandlerData(proto2_f, r)))); + } +#endif + else { if (f->IsSequence()) { SetStartRepeatedField<T>(proto2_f, r, f, h); CHKRET(h->SetValueHandler<T>(f, UpbMakeHandlerT(AppendPrimitive<T>))); @@ -383,6 +558,17 @@ case goog::FieldDescriptor::cpptype: \ val, set); } +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + template <typename T> + static void SetOneofPrimitive(goog::Message* m, + const OneofFieldHandlerData* data, T val) { + data->SetOneofHas(m); + const FieldOffset* ofs = data; + T* ptr = ofs->GetFieldPointer<T>(m); + *ptr = val; + } +#endif + // Enum ////////////////////////////////////////////////////////////////////// class EnumHandlerData : public FieldOffset { @@ -506,7 +692,15 @@ case goog::FieldDescriptor::cpptype: \ upb::Handlers* h) { assert(!proto2_f->is_extension()); CHKRET(h->SetStringHandler(f, UpbMakeHandlerT(&OnStringBuf<T>))); - if (f->IsSequence()) { +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + if (proto2_f->containing_oneof()) { + assert(!f->IsSequence()); + CHKRET(h->SetStartStringHandler( + f, UpbBindT(&StartOneofString<T>, + new OneofFieldHandlerData(proto2_f, r)))); + } else +#endif + if (f->IsSequence()) { SetStartRepeatedPtrField<T>(proto2_f, r, f, h); CHKRET( h->SetStartStringHandler(f, UpbMakeHandlerT(StartRepeatedString<T>))); @@ -545,6 +739,22 @@ case goog::FieldDescriptor::cpptype: \ return str; } +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + template <typename T> + static T* StartOneofString(goog::Message* m, + const OneofFieldHandlerData* data, + size_t size_hint) { + const FieldOffset* ofs = data; + T** str = ofs->GetFieldPointer<T*>(m); + if (data->SetOneofHas(m)) { + *str = new T(); + } else { + (*str)->clear(); + } + return *str; + } +#endif + // StringExtension /////////////////////////////////////////////////////////// template <typename T> @@ -598,6 +808,24 @@ case goog::FieldDescriptor::cpptype: \ const goog::Message* const prototype_; }; +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + class OneofSubMessageHandlerData : public SubMessageHandlerData { + public: + OneofSubMessageHandlerData(const goog::FieldDescriptor* f, + const goog::internal::GeneratedMessageReflection* r, + const goog::Message* prototype) + : SubMessageHandlerData(f, r, prototype), + oneof_data_(f, r) {} + + bool SetOneofHas(goog::Message* m) const { + return oneof_data_.SetOneofHas(m, this); + } + + private: + OneofFieldData oneof_data_; + }; +#endif + static void SetSubMessageHandlers( const goog::FieldDescriptor* proto2_f, const goog::Message& m, const goog::internal::GeneratedMessageReflection* r, @@ -605,7 +833,15 @@ case goog::FieldDescriptor::cpptype: \ const goog::Message* field_prototype = GetFieldPrototype(m, proto2_f); scoped_ptr<SubMessageHandlerData> data( new SubMessageHandlerData(proto2_f, r, field_prototype)); - if (f->IsSequence()) { +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + if (proto2_f->containing_oneof()) { + assert(!f->IsSequence()); + CHKRET(h->SetStartSubMessageHandler( + f, UpbBind(StartOneofSubMessage, new OneofSubMessageHandlerData( + proto2_f, r, field_prototype)))); + } else +#endif + if (f->IsSequence()) { SetStartRepeatedSubmessageField(proto2_f, r, f, h); CHKRET(h->SetStartSubMessageHandler( f, UpbBind(StartRepeatedSubMessage, data.release()))); @@ -649,6 +885,18 @@ case goog::FieldDescriptor::cpptype: \ return submsg; } +#ifdef GOOGLE_PROTOBUF_HAS_ONEOF + static goog::Message* StartOneofSubMessage( + goog::Message* m, const OneofSubMessageHandlerData* data) { + const FieldOffset* ofs = data; + goog::Message** subm = ofs->GetFieldPointer<goog::Message*>(m); + if (data->SetOneofHas(m)) { + *subm = data->prototype()->New(); + } + return *subm; + } +#endif + // SubMessageExtension /////////////////////////////////////////////////////// class SubMessageExtensionHandlerData : public ExtensionFieldData { @@ -979,7 +1227,7 @@ case goog::FieldDescriptor::cpptype: \ }; namespace upb { -namespace google { +namespace googlepb { bool TrySetWriteHandlers(const goog::FieldDescriptor* proto2_f, const goog::Message& prototype, @@ -987,10 +1235,13 @@ bool TrySetWriteHandlers(const goog::FieldDescriptor* proto2_f, return me::GMR_Handlers::TrySet(proto2_f, prototype, upb_f, h); } -const goog::Message* GetFieldPrototype(const goog::Message& m, - const goog::FieldDescriptor* f) { +const goog::Message* GetProto2FieldPrototype(const goog::Message& m, + const goog::FieldDescriptor* f) { + if (f->cpp_type() != goog::FieldDescriptor::CPPTYPE_MESSAGE) { + return NULL; + } return me::GMR_Handlers::GetFieldPrototype(m, f); } -} // namespace google +} // namespace googlepb } // namespace upb diff --git a/upb/bindings/googlepb/proto2.h b/upb/bindings/googlepb/proto2.int.h index 516b7fd..5ce44c4 100644 --- a/upb/bindings/googlepb/proto2.h +++ b/upb/bindings/googlepb/proto2.int.h @@ -8,8 +8,7 @@ // message that uses GeneratedMessageReflection (which includes all messages // generated by the proto2 compiler as well as DynamicMessage). // -// This is a low-level interface; the high-level interface in google.h is -// more user-friendly. +// This is an internal-only interface. #ifndef UPB_GOOGLE_PROTO2_H_ #define UPB_GOOGLE_PROTO2_H_ @@ -32,7 +31,7 @@ class Handlers; } namespace upb { -namespace google { +namespace googlepb { // Sets field handlers in the given Handlers object for writing to a single // field (as described by "proto2_f" and "upb_f") into a message constructed @@ -46,16 +45,15 @@ bool TrySetWriteHandlers(const ::google::protobuf::FieldDescriptor* proto2_f, const ::google::protobuf::Message& prototype, const upb::FieldDef* upb_f, upb::Handlers* h); -// Returns a prototype for the given field in "m", if it is weak. The returned -// message could be the linked-in message type or OpaqueMessage, if the weak -// message is *not* linked in. Otherwise returns NULL. -const proto2::Message* GetFieldPrototype(const proto2::Message& m, - const proto2::FieldDescriptor* f); -const ::google::protobuf::Message* GetFieldPrototype( +// Returns a prototype for the given field in "m", if the given message uses +// GeneratedMessageReflection. Otherwise returns NULL. +const proto2::Message* GetProto2FieldPrototype( + const proto2::Message& m, const proto2::FieldDescriptor* f); +const ::google::protobuf::Message* GetProto2FieldPrototype( const ::google::protobuf::Message& m, const ::google::protobuf::FieldDescriptor* f); -} // namespace google +} // namespace googlepb } // namespace upb #endif // UPB_GOOGLE_PROTO2_H_ diff --git a/upb/bindings/lua/table.c b/upb/bindings/lua/table.c index 51ba324..febadf0 100644 --- a/upb/bindings/lua/table.c +++ b/upb/bindings/lua/table.c @@ -25,6 +25,7 @@ #include "lauxlib.h" #include "upb/bindings/lua/upb.h" #include "upb/def.h" +#include "upb/symtab.h" static void lupbtable_setnum(lua_State *L, int tab, const char *key, lua_Number val) { @@ -141,6 +142,12 @@ static int lupbtable_enumdef_ntoi(lua_State *L) { return 1; } +static int lupbtable_symtab_symtab(lua_State *L) { + const upb_symtab *s = lupb_symtab_check(L, 1); + lupbtable_pushstrtable(L, &s->symtab); + return 1; +} + static void lupbtable_setfieldi(lua_State *L, const char *field, int i) { lua_pushnumber(L, i); lua_setfield(L, -2, field); @@ -151,11 +158,15 @@ static const struct luaL_Reg lupbtable_toplevel_m[] = { {"msgdef_ntof", lupbtable_msgdef_ntof}, {"enumdef_iton", lupbtable_enumdef_iton}, {"enumdef_ntoi", lupbtable_enumdef_ntoi}, + {"symtab_symtab", lupbtable_symtab_symtab}, {NULL, NULL} }; int luaopen_upbtable(lua_State *L) { - lupb_newlib(L, "upb.table", lupbtable_toplevel_m); + static char module_key; + if (lupb_openlib(L, &module_key, "upb.table", lupbtable_toplevel_m)) { + return 1; + } // We define these here because they are not public. lupbtable_setfieldi(L, "CTYPE_PTR", UPB_CTYPE_PTR); diff --git a/upb/bindings/lua/upb.c b/upb/bindings/lua/upb.c index 022d689..dbeb937 100644 --- a/upb/bindings/lua/upb.c +++ b/upb/bindings/lua/upb.c @@ -6,6 +6,21 @@ * * A Lua extension for upb. Exposes only the core library * (sub-libraries are exposed in other extensions). + * + * 64-bit woes: Lua can only represent numbers of type lua_Number (which is + * double unless the user specifically overrides this). Doubles can represent + * the entire range of 64-bit integers, but lose precision once the integers are + * greater than 2^53. + * + * Lua 5.3 is adding support for integers, which will allow for 64-bit + * integers (which can be interpreted as signed or unsigned). + * + * LuaJIT supports 64-bit signed and unsigned boxed representations + * through its "cdata" mechanism, but this is not portable to regular Lua. + * + * Hopefully Lua 5.3 will come soon enough that we can either use Lua 5.3 + * integer support or LuaJIT 64-bit cdata for users that need the entire + * domain of [u]int64 values. */ #include <float.h> @@ -16,8 +31,15 @@ #include "upb/bindings/lua/upb.h" #include "upb/handlers.h" #include "upb/pb/glue.h" +#include "upb/shim/shim.h" + +static const char upb_lua[] = { +#include "upb/bindings/lua/upb.lua.h" +}; // Lua metatable types. +#define LUPB_MSG "lupb.msg" +#define LUPB_ARRAY "lupb.array" #define LUPB_MSGDEF "lupb.msgdef" #define LUPB_ENUMDEF "lupb.enumdef" #define LUPB_FIELDDEF "lupb.fielddef" @@ -26,6 +48,15 @@ // Other table constants. #define LUPB_OBJCACHE "lupb.objcache" +static void lupb_msgdef_init(lua_State *L); +static size_t lupb_msgdef_sizeof(); + +/* Lua compatibility code *****************************************************/ + +// Lua 5.1 and Lua 5.2 have slightly incompatible APIs. A little bit of +// compatibility code can help hide the difference. Not too many people still +// use Lua 5.1 but LuaJIT uses the Lua 5.1 API in some ways. + #if LUA_VERSION_NUM == 501 // Taken from Lua 5.2's source. @@ -43,6 +74,12 @@ void *luaL_testudata(lua_State *L, int ud, const char *tname) { return NULL; /* value is not a userdata with a metatable */ } +static void lupb_newlib(lua_State *L, const char *name, const luaL_Reg *funcs) { + luaL_register(L, name, funcs); +} + +#define lupb_setfuncs(L, l) luaL_register(L, NULL, l) + #elif LUA_VERSION_NUM == 502 int luaL_typerror(lua_State *L, int narg, const char *tname) { @@ -51,11 +88,72 @@ int luaL_typerror(lua_State *L, int narg, const char *tname) { return luaL_argerror(L, narg, msg); } +static void lupb_newlib(lua_State *L, const char *name, const luaL_Reg *funcs) { + // Lua 5.2 modules are not expected to set a global variable, so "name" is + // unused. + UPB_UNUSED(name); + + // Can't use luaL_newlib(), because funcs is not the actual array. + // Could (micro-)optimize this a bit to count funcs for initial table size. + lua_createtable(L, 0, 8); + luaL_setfuncs(L, funcs, 0); +} + +#define lupb_setfuncs(L, l) luaL_setfuncs(L, l, 0) + #else #error Only Lua 5.1 and 5.2 are supported #endif -static const char *chkname(lua_State *L, int narg) { +// Shims for upcoming Lua 5.3 functionality. +bool lua_isinteger(lua_State *L, int argn) { + UPB_UNUSED(L); + UPB_UNUSED(argn); + return false; +} + + +/* Utility functions **********************************************************/ + +// We store our module table in the registry, keyed by ptr. +// For more info about the motivation/rationale, see this thread: +// http://thread.gmane.org/gmane.comp.lang.lua.general/110632 +bool lupb_openlib(lua_State *L, void *ptr, const char *name, + const luaL_Reg *funcs) { + // Lookup cached module table. + lua_pushlightuserdata(L, ptr); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_isnil(L, -1)) { + return true; + } + + lupb_newlib(L, name, funcs); + + // Save module table in cache. + lua_pushlightuserdata(L, ptr); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + + return false; +} + +// Pushes a new userdata with the given metatable and ensures that it has a +// uservalue. +static void *newudata_with_userval(lua_State *L, size_t size, const char *type) { + void *ret = lua_newuserdata(L, size); + + // Set metatable. + luaL_getmetatable(L, type); + assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb. + lua_setmetatable(L, -2); + + lua_newtable(L); + lua_setuservalue(L, -2); + + return ret; +} + +const char *lupb_checkname(lua_State *L, int narg) { size_t len; const char *name = luaL_checklstring(L, narg, &len); if (strlen(name) != len) @@ -63,65 +161,110 @@ static const char *chkname(lua_State *L, int narg) { return name; } -static bool chkbool(lua_State *L, int narg, const char *type) { +bool lupb_checkbool(lua_State *L, int narg) { if (!lua_isboolean(L, narg)) { - luaL_error(L, "%s must be true or false", type); + luaL_error(L, "must be true or false"); } return lua_toboolean(L, narg); } -static bool streql(const char *a, const char *b) { return strcmp(a, b) == 0; } +// Unlike luaL_checkstring(), this does not allow implicit conversion to string. +void lupb_checkstring(lua_State *L, int narg) { + if (lua_type(L, narg) != LUA_TSTRING) + luaL_error(L, "Expected string"); +} + +// Unlike luaL_checkinteger, these do not implicitly convert from string or +// round an existing double value. We allow floating-point input, but only if +// the actual value is integral. +#define INTCHECK(type, ctype) \ + ctype lupb_check##type(lua_State *L, int narg) { \ + if (lua_isinteger(L, narg)) { \ + return lua_tointeger(L, narg); \ + } \ + \ + /* Prevent implicit conversion from string. */ \ + luaL_checktype(L, narg, LUA_TNUMBER); \ + double n = lua_tonumber(L, narg); \ + \ + ctype i = (ctype)n; \ + if ((double)i != n) { \ + /* double -> ctype truncated or rounded. */ \ + luaL_error(L, "number %f was not an integer or out of range for " #type, \ + n); \ + } \ + return i; \ + } \ + void lupb_push##type(lua_State *L, ctype val) { \ + /* TODO: push integer for Lua >= 5.3, 64-bit cdata for LuaJIT. */ \ + /* This is lossy for some [u]int64 values, which isn't great, but */ \ + /* crashing when we encounter these values seems worse. */ \ + lua_pushnumber(L, val); \ + } + +INTCHECK(int64, int64_t); +INTCHECK(int32, int32_t); +INTCHECK(uint64, uint64_t); +INTCHECK(uint32, uint32_t); -static uint32_t chkint32(lua_State *L, int narg, const char *name) { - lua_Number n = lua_tonumber(L, narg); - if (n > INT32_MAX || n < INT32_MIN || rint(n) != n) - luaL_error(L, "Invalid %s", name); - return n; +double lupb_checkdouble(lua_State *L, int narg) { + // If we were being really hard-nosed here, we'd check whether the input was + // an integer that has no precise double representation. But doubles aren't + // generally expected to be exact like integers are, and worse this could + // cause data-dependent runtime errors: one run of the program could work fine + // because the integer calculations happened to be exactly representable in + // double, while the next could crash because of subtly different input. + + luaL_checktype(L, narg, LUA_TNUMBER); // lua_tonumber() implicitly converts. + return lua_tonumber(L, narg); } -// Sets a fielddef default from the given Lua value. -static void lupb_setdefault(lua_State *L, int narg, upb_fielddef *f) { - if (upb_fielddef_type(f) == UPB_TYPE_BOOL) { - upb_fielddef_setdefaultbool(f, chkbool(L, narg, "bool default")); - } else { - // Numeric type. - lua_Number num = luaL_checknumber(L, narg); - switch (upb_fielddef_type(f)) { - case UPB_TYPE_INT32: - case UPB_TYPE_ENUM: - if (num > INT32_MAX || num < INT32_MIN || num != rint(num)) - luaL_error(L, "Cannot convert %f to 32-bit integer", num); - upb_fielddef_setdefaultint32(f, num); - break; - case UPB_TYPE_INT64: - if (num > INT64_MAX || num < INT64_MIN || num != rint(num)) - luaL_error(L, "Cannot convert %f to 64-bit integer", num); - upb_fielddef_setdefaultint64(f, num); - break; - case UPB_TYPE_UINT32: - if (num > UINT32_MAX || num < 0 || num != rint(num)) - luaL_error(L, "Cannot convert %f to unsigned 32-bit integer", num); - upb_fielddef_setdefaultuint32(f, num); - break; - case UPB_TYPE_UINT64: - if (num > UINT64_MAX || num < 0 || num != rint(num)) - luaL_error(L, "Cannot convert %f to unsigned 64-bit integer", num); - upb_fielddef_setdefaultuint64(f, num); - break; - case UPB_TYPE_DOUBLE: - if (num > DBL_MAX || num < -DBL_MAX) { - // This could happen if lua_Number was long double. - luaL_error(L, "Cannot convert %f to double", num); - } - upb_fielddef_setdefaultdouble(f, num); - break; - case UPB_TYPE_FLOAT: - if (num > FLT_MAX || num < -FLT_MAX) - luaL_error(L, "Cannot convert %f to float", num); - upb_fielddef_setdefaultfloat(f, num); - break; - default: luaL_error(L, "invalid type"); - } +float lupb_checkfloat(lua_State *L, int narg) { + // We don't worry about checking whether the input can be exactly converted to + // float -- see above. + + luaL_checktype(L, narg, LUA_TNUMBER); // lua_tonumber() implicitly converts. + return lua_tonumber(L, narg); +} + +void lupb_pushdouble(lua_State *L, double d) { + lua_pushnumber(L, d); +} + +void lupb_pushfloat(lua_State *L, float d) { + lua_pushnumber(L, d); +} + +static void lupb_checkval(lua_State *L, int narg, upb_fieldtype_t type) { + switch(type) { + case UPB_TYPE_INT32: + case UPB_TYPE_ENUM: + lupb_checkint32(L, narg); + break; + case UPB_TYPE_INT64: + lupb_checkint64(L, narg); + break; + case UPB_TYPE_UINT32: + lupb_checkuint32(L, narg); + break; + case UPB_TYPE_UINT64: + lupb_checkuint64(L, narg); + break; + case UPB_TYPE_DOUBLE: + lupb_checkdouble(L, narg); + break; + case UPB_TYPE_FLOAT: + lupb_checkfloat(L, narg); + break; + case UPB_TYPE_BOOL: + lupb_checkbool(L, narg); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + lupb_checkstring(L, narg); + break; + case UPB_TYPE_MESSAGE: + lupb_assert(L, false); } } @@ -132,6 +275,13 @@ void lupb_checkstatus(lua_State *L, upb_status *s) { } } +static upb_fieldtype_t lupb_checkfieldtype(lua_State *L, int narg) { + int type = luaL_checkint(L, narg); + if (!upb_fielddef_checktype(type)) + luaL_argerror(L, narg, "invalid field type"); + return type; +} + #define CHK(pred) do { \ upb_status status = UPB_STATUS_INIT; \ pred; \ @@ -139,21 +289,28 @@ void lupb_checkstatus(lua_State *L, upb_status *s) { } while (0) -/* refcounted *****************************************************************/ +/* lupb_refcounted ************************************************************/ -// All upb objects that use upb_refcounted share a common Lua userdata -// representation and a common scheme for caching Lua wrapper object. They do -// however have different metatables. Objects are cached in a weak table -// indexed by the C pointer of the object they are caching. +// All upb objects that use upb_refcounted have a userdata that begins with a +// pointer to that object. Each type has its own metatable. Objects are cached +// in a weak table indexed by the C pointer of the object they are caching. +// +// Note that we consistently use memcpy() to read to/from the object. This +// allows the userdata to use its own struct without violating aliasing, as +// long as it begins with a pointer. -typedef union { - const upb_refcounted *refcounted; - const upb_def *def; - upb_symtab *symtab; -} lupb_refcounted; +// Checks type; if it matches, pulls the pointer out of the wrapper. +void *lupb_refcounted_check(lua_State *L, int narg, const char *type) { + void *ud = luaL_checkudata(L, narg, type); + void *ret; + memcpy(&ret, ud, sizeof ret); + if (!ret) luaL_error(L, "called into dead object"); + return ret; +} -static bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, - const char *type, const void *owner) { +bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, + const char *type, const void *ref_donor, + size_t size) { if (obj == NULL) { lua_pushnil(L); return false; @@ -161,30 +318,44 @@ static bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, // Lookup our cache in the registry (we don't put our objects in the registry // directly because we need our cache to be a weak table). - lupb_refcounted *ud = NULL; lua_getfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE); assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb. lua_pushlightuserdata(L, (void*)obj); lua_rawget(L, -2); - // Stack: objcache, cached value. - bool create = lua_isnil(L, -1) || - // A corner case: it is possible for the value to be GC'd - // already, in which case we should evict this entry and create - // a new one. - ((lupb_refcounted*)lua_touserdata(L, -1))->refcounted == NULL; + // Stack is now: objcache, cached value. + + bool create = false; + + if (lua_isnil(L, -1)) { + create = true; + } else { + void *ud = lua_touserdata(L, -1); + lupb_assert(L, ud); + void *ud_obj; + memcpy(&ud_obj, ud, sizeof(void*)); + + // A corner case: it is possible for the value to be GC'd + // already, in which case we should evict this entry and create + // a new one. + if (ud_obj == NULL) { + create = true; + } + } + + void *ud = NULL; + if (create) { // Remove bad cached value and push new value. lua_pop(L, 1); - // We take advantage of the fact that all of our objects are currently a - // single pointer, and thus have the same layout. - // TODO: this probably violates aliasing. - ud = lua_newuserdata(L, sizeof(lupb_refcounted)); - ud->refcounted = obj; - upb_refcounted_donateref(obj, owner, ud); + // All of our userdata begin with a pointer to the obj. + ud = lua_newuserdata(L, size); + memcpy(ud, &obj, sizeof(void*)); + upb_refcounted_donateref(obj, ref_donor, ud); luaL_getmetatable(L, type); - assert(!lua_isnil(L, -1)); // Should have been created by luaopen_upb. + // Should have been created by luaopen_upb. + lupb_assert(L, !lua_isnil(L, -1)); lua_setmetatable(L, -2); // Set it in the cache. @@ -195,67 +366,111 @@ static bool lupb_refcounted_pushwrapper(lua_State *L, const upb_refcounted *obj, // Existing wrapper obj already has a ref. ud = lua_touserdata(L, -1); upb_refcounted_checkref(obj, ud); - if (owner) - upb_refcounted_unref(obj, owner); + if (ref_donor) + upb_refcounted_unref(obj, ref_donor); } + lua_insert(L, -2); lua_pop(L, 1); return create; } -static void lupb_refcounted_pushnewrapper(lua_State *L, upb_refcounted *obj, - const char *type, const void *owner) { - bool created = lupb_refcounted_pushwrapper(L, obj, type, owner); +void lupb_refcounted_pushnewrapper(lua_State *L, const upb_refcounted *obj, + const char *type, const void *ref_donor) { + bool created = + lupb_refcounted_pushwrapper(L, obj, type, ref_donor, sizeof(void *)); UPB_ASSERT_VAR(created, created == true); } +static int lupb_refcounted_gc(lua_State *L) { + void *ud = lua_touserdata(L, 1); + upb_refcounted *obj; + memcpy(&obj, ud, sizeof obj); + upb_refcounted_unref(obj, ud); + + // Zero out pointer so we can detect a call into a GC'd object. + void *nullp = NULL; + memcpy(ud, &nullp, sizeof nullp); + + return 0; +} + +static const struct luaL_Reg lupb_refcounted_mm[] = { + {"__gc", lupb_refcounted_gc}, + {NULL, NULL} +}; + /* lupb_def *******************************************************************/ static const upb_def *lupb_def_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_testudata(L, narg, LUPB_MSGDEF); - if (!r) r = luaL_testudata(L, narg, LUPB_ENUMDEF); - if (!r) r = luaL_testudata(L, narg, LUPB_FIELDDEF); - if (!r) luaL_typerror(L, narg, "upb def"); - if (!r->refcounted) luaL_error(L, "called into dead def"); - return r->def; + void *ud = luaL_testudata(L, narg, LUPB_MSGDEF); + if (!ud) ud = luaL_testudata(L, narg, LUPB_ENUMDEF); + if (!ud) ud = luaL_testudata(L, narg, LUPB_FIELDDEF); + if (!ud) luaL_typerror(L, narg, "upb def"); + + upb_def *ret; + memcpy(&ret, ud, sizeof ret); + if (!ret) luaL_error(L, "called into dead object"); + return ret; } static upb_def *lupb_def_checkmutable(lua_State *L, int narg) { const upb_def *def = lupb_def_check(L, narg); if (upb_def_isfrozen(def)) - luaL_typerror(L, narg, "not allowed on frozen value"); + luaL_error(L, "not allowed on frozen value"); return (upb_def*)def; } -bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, const void *owner) { +bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, + const void *ref_donor) { if (def == NULL) { lua_pushnil(L); return false; } const char *type = NULL; - switch (def->type) { - case UPB_DEF_MSG: type = LUPB_MSGDEF; break; + size_t size = sizeof(void*); + + switch (upb_def_type(def)) { + case UPB_DEF_MSG: { + type = LUPB_MSGDEF; + size = lupb_msgdef_sizeof(); + break; + } case UPB_DEF_ENUM: type = LUPB_ENUMDEF; break; case UPB_DEF_FIELD: type = LUPB_FIELDDEF; break; default: luaL_error(L, "unknown deftype %d", def->type); } - return lupb_refcounted_pushwrapper(L, UPB_UPCAST(def), type, owner); + + bool created = + lupb_refcounted_pushwrapper(L, UPB_UPCAST(def), type, ref_donor, size); + + if (created && upb_def_type(def) == UPB_DEF_MSG) { + lupb_msgdef_init(L); + } + + return created; } void lupb_def_pushnewrapper(lua_State *L, const upb_def *def, - const void *owner) { - bool created = lupb_def_pushwrapper(L, def, owner); + const void *ref_donor) { + bool created = lupb_def_pushwrapper(L, def, ref_donor); UPB_ASSERT_VAR(created, created == true); } static int lupb_def_type(lua_State *L) { const upb_def *def = lupb_def_check(L, 1); - lua_pushnumber(L, upb_def_type(def)); + lua_pushinteger(L, upb_def_type(def)); return 1; } +static int lupb_def_freeze(lua_State *L) { + upb_def *def = lupb_def_checkmutable(L, 1); + CHK(upb_def_freeze(&def, 1, &status)); + return 0; +} + static int lupb_def_isfrozen(lua_State *L) { const upb_def *def = lupb_def_check(L, 1); lua_pushboolean(L, upb_def_isfrozen(def)); @@ -269,234 +484,49 @@ static int lupb_def_fullname(lua_State *L) { } static int lupb_def_setfullname(lua_State *L) { - CHK(upb_def_setfullname(lupb_def_checkmutable(L, 1), chkname(L, 2), &status)); + const char *name = lupb_checkname(L, 2); + CHK(upb_def_setfullname(lupb_def_checkmutable(L, 1), name, &status)); return 0; } #define LUPB_COMMON_DEF_METHODS \ {"def_type", lupb_def_type}, \ {"full_name", lupb_def_fullname}, \ + {"freeze", lupb_def_freeze}, \ {"is_frozen", lupb_def_isfrozen}, \ {"set_full_name", lupb_def_setfullname}, \ /* lupb_fielddef **************************************************************/ -static const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_FIELDDEF); - if (!r) luaL_typerror(L, narg, "upb fielddef"); - if (!r->refcounted) luaL_error(L, "called into dead fielddef"); - return upb_downcast_fielddef(r->def); +const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg) { + return lupb_refcounted_check(L, narg, LUPB_FIELDDEF); } static upb_fielddef *lupb_fielddef_checkmutable(lua_State *L, int narg) { const upb_fielddef *f = lupb_fielddef_check(L, narg); if (upb_fielddef_isfrozen(f)) - luaL_typerror(L, narg, "not allowed on frozen value"); + luaL_error(L, "not allowed on frozen value"); return (upb_fielddef*)f; } -// Setter functions; these are called by both the constructor and the individual -// setter API calls like field:set_type(). - -static void lupb_fielddef_dosetdefault(lua_State *L, upb_fielddef *f, - int narg) { - int type = lua_type(L, narg); - upb_fieldtype_t upbtype = upb_fielddef_type(f); - if (type == LUA_TSTRING) { - if (!upb_fielddef_isstring(f) && upbtype != UPB_TYPE_ENUM) - luaL_argerror(L, narg, "field does not expect a string default"); - size_t len; - const char *str = lua_tolstring(L, narg, &len); - CHK(upb_fielddef_setdefaultstr(f, str, len, &status)); - } else { - lupb_setdefault(L, narg, f); - } -} - -static void lupb_fielddef_dosetisextension(lua_State *L, upb_fielddef *f, - int narg) { - CHK(upb_fielddef_setisextension(f, chkbool(L, narg, "is_extension"))); -} - -static void lupb_fielddef_dosetlabel(lua_State *L, upb_fielddef *f, int narg) { - int label = luaL_checkint(L, narg); - if (!upb_fielddef_checklabel(label)) - luaL_argerror(L, narg, "invalid field label"); - upb_fielddef_setlabel(f, label); -} - -static void lupb_fielddef_dosetlazy(lua_State *L, upb_fielddef *f, int narg) { - upb_fielddef_setlazy(f, chkbool(L, narg, "lazy")); -} - -static void lupb_fielddef_dosetname(lua_State *L, upb_fielddef *f, int narg) { - CHK(upb_fielddef_setname(f, chkname(L, narg), &status)); -} - -static void lupb_fielddef_dosetnumber(lua_State *L, upb_fielddef *f, int narg) { - CHK(upb_fielddef_setnumber(f, luaL_checkint(L, narg), &status)); -} - -static void lupb_fielddef_dosetsubdef(lua_State *L, upb_fielddef *f, int narg) { - const upb_def *def = NULL; - if (!lua_isnil(L, narg)) - def = lupb_def_check(L, narg); - CHK(upb_fielddef_setsubdef(f, def, &status)); -} - -static void lupb_fielddef_dosetsubdefname(lua_State *L, upb_fielddef *f, - int narg) { - const char *name = NULL; - if (!lua_isnil(L, narg)) - name = chkname(L, narg); - CHK(upb_fielddef_setsubdefname(f, name, &status)); -} - -static void lupb_fielddef_dosetcontainingtypename(lua_State *L, upb_fielddef *f, - int narg) { - const char *name = NULL; - if (!lua_isnil(L, narg)) - name = chkname(L, narg); - CHK(upb_fielddef_setcontainingtypename(f, name, &status)); -} - -static void lupb_fielddef_dosettype(lua_State *L, upb_fielddef *f, int narg) { - int type = luaL_checkint(L, narg); - if (!upb_fielddef_checktype(type)) - luaL_argerror(L, narg, "invalid field type"); - upb_fielddef_settype(f, type); -} - -static void lupb_fielddef_dosetintfmt(lua_State *L, upb_fielddef *f, int narg) { - int32_t intfmt = luaL_checknumber(L, narg); - if (!upb_fielddef_checkintfmt(intfmt)) - luaL_argerror(L, narg, "invalid intfmt"); - upb_fielddef_setintfmt(f, intfmt); -} - -static void lupb_fielddef_dosettagdelim(lua_State *L, upb_fielddef *f, - int narg) { - CHK(upb_fielddef_settagdelim(f, chkbool(L, narg, "tagdelim"))); -} - -// Setter API calls. These use the setter functions above. - -static int lupb_fielddef_setcontainingtypename(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetcontainingtypename(L, f, 2); - return 0; -} - -static int lupb_fielddef_setdefault(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetdefault(L, f, 2); - return 0; -} - -static int lupb_fielddef_setisextension(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetisextension(L, f, 2); - return 0; -} - -static int lupb_fielddef_setlabel(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetlabel(L, f, 2); - return 0; -} - -static int lupb_fielddef_setlazy(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetlazy(L, f, 2); - return 0; -} - -static int lupb_fielddef_setname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetname(L, f, 2); - return 0; -} - -static int lupb_fielddef_setnumber(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetnumber(L, f, 2); - return 0; -} - -static int lupb_fielddef_setsubdef(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetsubdef(L, f, 2); - return 0; -} - -static int lupb_fielddef_setsubdefname(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetsubdefname(L, f, 2); - return 0; -} - -static int lupb_fielddef_settype(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosettype(L, f, 2); - return 0; -} - -static int lupb_fielddef_setintfmt(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosetintfmt(L, f, 2); - return 0; -} - -static int lupb_fielddef_settagdelim(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lupb_fielddef_dosettagdelim(L, f, 2); - return 0; -} - -// Constructor and other methods. - static int lupb_fielddef_new(lua_State *L) { upb_fielddef *f = upb_fielddef_new(&f); - int narg = lua_gettop(L); - lupb_def_pushnewrapper(L, UPB_UPCAST(f), &f); + return 1; +} - if (narg == 0) return 1; - - // User can specify initialization values like so: - // upb.FieldDef{label=upb.LABEL_REQUIRED, name="my_field", number=5, - // type=upb.TYPE_INT32, default_value=12, type_name="Foo"} - luaL_checktype(L, 1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - luaL_checktype(L, -2, LUA_TSTRING); - const char *key = lua_tostring(L, -2); - int v = -1; - if (streql(key, "name")) lupb_fielddef_dosetname(L, f, v); - else if (streql(key, "number")) lupb_fielddef_dosetnumber(L, f, v); - else if (streql(key, "type")) lupb_fielddef_dosettype(L, f, v); - else if (streql(key, "label")) lupb_fielddef_dosetlabel(L, f, v); - else if (streql(key, "lazy")) lupb_fielddef_dosetlazy(L, f, v); - else if (streql(key, "is_extension")) - lupb_fielddef_dosetisextension(L, f, v); - else if (streql(key, "containing_type_name")) - lupb_fielddef_dosetcontainingtypename(L, f, v); - else if (streql(key, "default_value")) ; // Defer to second pass. - else if (streql(key, "subdef")) ; // Defer to second pass. - else if (streql(key, "subdef_name")) ; // Defer to second pass. - else luaL_error(L, "Cannot set fielddef member '%s'", key); - } +// Getters - // Have to do these in a second pass because these depend on the type, so we - // have to make sure the type is set if the user specified one. - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - const char *key = lua_tostring(L, -2); - int v = -1; - if (streql(key, "default_value")) lupb_fielddef_dosetdefault(L, f, v); - else if (streql(key, "subdef")) lupb_fielddef_dosetsubdef(L, f, v); - else if (streql(key, "subdef_name")) lupb_fielddef_dosetsubdefname(L, f, v); - } +static int lupb_fielddef_containingtype(lua_State *L) { + const upb_fielddef *f = lupb_fielddef_check(L, 1); + lupb_def_pushwrapper(L, UPB_UPCAST(upb_fielddef_containingtype(f)), NULL); + return 1; +} +static int lupb_fielddef_containingtypename(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + lua_pushstring(L, upb_fielddef_containingtypename(f)); return 1; } @@ -505,13 +535,13 @@ static int lupb_fielddef_default(lua_State *L) { switch (upb_fielddef_type(f)) { case UPB_TYPE_INT32: int32: - lua_pushnumber(L, upb_fielddef_defaultint32(f)); break; + lupb_pushint32(L, upb_fielddef_defaultint32(f)); break; case UPB_TYPE_INT64: - lua_pushnumber(L, upb_fielddef_defaultint64(f)); break; + lupb_pushint64(L, upb_fielddef_defaultint64(f)); break; case UPB_TYPE_UINT32: - lua_pushnumber(L, upb_fielddef_defaultuint32(f)); break; + lupb_pushuint32(L, upb_fielddef_defaultuint32(f)); break; case UPB_TYPE_UINT64: - lua_pushnumber(L, upb_fielddef_defaultuint64(f)); break; + lupb_pushuint64(L, upb_fielddef_defaultuint64(f)); break; case UPB_TYPE_DOUBLE: lua_pushnumber(L, upb_fielddef_defaultdouble(f)); break; case UPB_TYPE_FLOAT: @@ -519,11 +549,17 @@ static int lupb_fielddef_default(lua_State *L) { case UPB_TYPE_BOOL: lua_pushboolean(L, upb_fielddef_defaultbool(f)); break; case UPB_TYPE_ENUM: - if (!upb_fielddef_default_is_symbolic(f)) + if (upb_fielddef_enumhasdefaultstr(f)) { + goto str; + } else if (upb_fielddef_enumhasdefaultint32(f)) { goto int32; - // Fallthrough. + } else { + lua_pushnil(L); + } + break; case UPB_TYPE_STRING: - case UPB_TYPE_BYTES: { + case UPB_TYPE_BYTES: + str: { size_t len; const char *data = upb_fielddef_defaultstr(f, &len); lua_pushlstring(L, data, len); @@ -539,64 +575,68 @@ static int lupb_fielddef_getsel(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); upb_selector_t sel; if (upb_handlers_getselector(f, luaL_checknumber(L, 2), &sel)) { - lua_pushnumber(L, sel); + lua_pushinteger(L, sel); return 1; } else { return 0; } } -static int lupb_fielddef_label(lua_State *L) { +static int lupb_fielddef_hassubdef(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushnumber(L, upb_fielddef_label(f)); + lua_pushboolean(L, upb_fielddef_hassubdef(f)); return 1; } -static int lupb_fielddef_lazy(lua_State *L) { +static int lupb_fielddef_index(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushboolean(L, upb_fielddef_lazy(f)); + lua_pushinteger(L, upb_fielddef_index(f)); return 1; } -static int lupb_fielddef_name(lua_State *L) { +static int lupb_fielddef_intfmt(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushstring(L, upb_fielddef_name(f)); + lua_pushinteger(L, upb_fielddef_intfmt(f)); return 1; } -static int lupb_fielddef_number(lua_State *L) { +static int lupb_fielddef_isextension(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - int32_t num = upb_fielddef_number(f); - if (num) - lua_pushnumber(L, num); - else - lua_pushnil(L); + lua_pushboolean(L, upb_fielddef_isextension(f)); return 1; } -static int lupb_fielddef_selectorbase(lua_State *L) { +static int lupb_fielddef_istagdelim(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - if (!upb_fielddef_isfrozen(f)) - luaL_error(L, "_selectorbase is only defined for frozen fielddefs"); - lua_pushnumber(L, f->selector_base); + lua_pushboolean(L, upb_fielddef_istagdelim(f)); return 1; } -static int lupb_fielddef_hassubdef(lua_State *L) { +static int lupb_fielddef_label(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushboolean(L, upb_fielddef_hassubdef(f)); + lua_pushinteger(L, upb_fielddef_label(f)); return 1; } -static int lupb_fielddef_containingtype(lua_State *L) { +static int lupb_fielddef_lazy(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); - lupb_def_pushwrapper(L, UPB_UPCAST(upb_fielddef_containingtype(f)), NULL); + lua_pushboolean(L, upb_fielddef_lazy(f)); return 1; } -static int lupb_fielddef_containingtypename(lua_State *L) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); - lua_pushstring(L, upb_fielddef_containingtypename(f)); +static int lupb_fielddef_name(lua_State *L) { + const upb_fielddef *f = lupb_fielddef_check(L, 1); + lua_pushstring(L, upb_fielddef_name(f)); + return 1; +} + +static int lupb_fielddef_number(lua_State *L) { + const upb_fielddef *f = lupb_fielddef_check(L, 1); + int32_t num = upb_fielddef_number(f); + if (num) + lua_pushinteger(L, num); + else + lua_pushnil(L); return 1; } @@ -620,43 +660,147 @@ static int lupb_fielddef_subdefname(lua_State *L) { static int lupb_fielddef_type(lua_State *L) { const upb_fielddef *f = lupb_fielddef_check(L, 1); if (upb_fielddef_typeisset(f)) - lua_pushnumber(L, upb_fielddef_type(f)); + lua_pushinteger(L, upb_fielddef_type(f)); else lua_pushnil(L); return 1; } -static int lupb_fielddef_index(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushnumber(L, upb_fielddef_index(f)); - return 1; +// Setters + +static int lupb_fielddef_setcontainingtypename(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + const char *name = NULL; + if (!lua_isnil(L, 2)) + name = lupb_checkname(L, 2); + CHK(upb_fielddef_setcontainingtypename(f, name, &status)); + return 0; } -static int lupb_fielddef_intfmt(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushnumber(L, upb_fielddef_intfmt(f)); - return 1; +static int lupb_fielddef_setdefault(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + + switch (upb_fielddef_type(f)) { + case UPB_TYPE_INT32: + upb_fielddef_setdefaultint32(f, lupb_checkint32(L, 2)); + break; + case UPB_TYPE_INT64: + upb_fielddef_setdefaultint64(f, lupb_checkint64(L, 2)); + break; + case UPB_TYPE_UINT32: + upb_fielddef_setdefaultuint32(f, lupb_checkuint32(L, 2)); + break; + case UPB_TYPE_UINT64: + upb_fielddef_setdefaultuint64(f, lupb_checkuint64(L, 2)); + break; + case UPB_TYPE_DOUBLE: + upb_fielddef_setdefaultdouble(f, lupb_checkdouble(L, 2)); + break; + case UPB_TYPE_FLOAT: + upb_fielddef_setdefaultfloat(f, lupb_checkfloat(L, 2)); + break; + case UPB_TYPE_BOOL: + upb_fielddef_setdefaultbool(f, lupb_checkbool(L, 2)); + break; + case UPB_TYPE_MESSAGE: + return luaL_error(L, "Message types cannot have defaults."); + case UPB_TYPE_ENUM: + if (lua_type(L, 2) != LUA_TSTRING) { + upb_fielddef_setdefaultint32(f, lupb_checkint32(L, 2)); + break; + } + // Else fall through and set string default. + case UPB_TYPE_BYTES: + case UPB_TYPE_STRING: { + size_t len; + const char *str = lua_tolstring(L, 2, &len); + CHK(upb_fielddef_setdefaultstr(f, str, len, &status)); + } + } + return 0; } -static int lupb_fielddef_isextension(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushboolean(L, upb_fielddef_isextension(f)); - return 1; +static int lupb_fielddef_setisextension(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + CHK(upb_fielddef_setisextension(f, lupb_checkbool(L, 2))); + return 0; } -static int lupb_fielddef_istagdelim(lua_State *L) { - const upb_fielddef *f = lupb_fielddef_check(L, 1); - lua_pushboolean(L, upb_fielddef_istagdelim(f)); - return 1; +static int lupb_fielddef_setlabel(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + int label = luaL_checkint(L, 2); + if (!upb_fielddef_checklabel(label)) + luaL_argerror(L, 2, "invalid field label"); + upb_fielddef_setlabel(f, label); + return 0; +} + +static int lupb_fielddef_setlazy(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + upb_fielddef_setlazy(f, lupb_checkbool(L, 2)); + return 0; +} + +static int lupb_fielddef_setname(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + CHK(upb_fielddef_setname(f, lupb_checkname(L, 2), &status)); + return 0; +} + +static int lupb_fielddef_setnumber(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + CHK(upb_fielddef_setnumber(f, luaL_checkint(L, 2), &status)); + return 0; +} + +static int lupb_fielddef_setsubdef(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + const upb_def *def = NULL; + if (!lua_isnil(L, 2)) + def = lupb_def_check(L, 2); + CHK(upb_fielddef_setsubdef(f, def, &status)); + return 0; +} + +static int lupb_fielddef_setsubdefname(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + const char *name = NULL; + if (!lua_isnil(L, 2)) + name = lupb_checkname(L, 2); + CHK(upb_fielddef_setsubdefname(f, name, &status)); + return 0; +} + +static int lupb_fielddef_settype(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + upb_fielddef_settype(f, lupb_checkfieldtype(L, 2)); + return 0; +} + +static int lupb_fielddef_setintfmt(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + int32_t intfmt = luaL_checknumber(L, 2); + if (!upb_fielddef_checkintfmt(intfmt)) + luaL_argerror(L, 2, "invalid intfmt"); + upb_fielddef_setintfmt(f, intfmt); + return 0; } -static int lupb_fielddef_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_FIELDDEF); - upb_def_unref(r->def, r); - r->refcounted = NULL; +static int lupb_fielddef_settagdelim(lua_State *L) { + upb_fielddef *f = lupb_fielddef_checkmutable(L, 1); + bool is_tag_delim = lupb_checkbool(L, 2); + CHK(upb_fielddef_settagdelim(f, is_tag_delim)); return 0; } +static int lupb_fielddef_selectorbase(lua_State *L) { + const upb_fielddef *f = lupb_fielddef_check(L, 1); + if (!upb_fielddef_isfrozen(f)) + luaL_error(L, "_selectorbase is only defined for frozen fielddefs"); + lua_pushinteger(L, f->selector_base); + return 1; +} + static const struct luaL_Reg lupb_fielddef_m[] = { LUPB_COMMON_DEF_METHODS @@ -696,82 +840,64 @@ static const struct luaL_Reg lupb_fielddef_m[] = { {NULL, NULL} }; -static const struct luaL_Reg lupb_fielddef_mm[] = { - {"__gc", lupb_fielddef_gc}, - {NULL, NULL} -}; - /* lupb_msgdef ****************************************************************/ +typedef struct { + const upb_msgdef *md; + + // These members are initialized lazily the first time a message is created + // for this def. + uint16_t *field_offsets; + size_t msg_size; + size_t hasbits_size; + lua_State *L; +} lupb_msgdef; + +static size_t lupb_msgdef_sizeof() { + return sizeof(lupb_msgdef); +} + const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_MSGDEF); - if (!r) luaL_typerror(L, narg, LUPB_MSGDEF); - if (!r->refcounted) luaL_error(L, "called into dead msgdef"); - return upb_downcast_msgdef(r->def); + return lupb_refcounted_check(L, narg, LUPB_MSGDEF); +} + +lupb_msgdef *lupb_msgdef_check2(lua_State *L, int narg) { + return luaL_checkudata(L, narg, LUPB_MSGDEF); } static upb_msgdef *lupb_msgdef_checkmutable(lua_State *L, int narg) { const upb_msgdef *m = lupb_msgdef_check(L, narg); if (upb_msgdef_isfrozen(m)) - luaL_typerror(L, narg, "not allowed on frozen value"); + luaL_error(L, "not allowed on frozen value"); return (upb_msgdef*)m; } -static int lupb_msgdef_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_MSGDEF); - upb_def_unref(r->def, r); - r->refcounted = NULL; - return 0; -} - static int lupb_msgdef_new(lua_State *L) { - int narg = lua_gettop(L); upb_msgdef *md = upb_msgdef_new(&md); lupb_def_pushnewrapper(L, UPB_UPCAST(md), &md); - - if (narg == 0) return 1; - - // User can specify initialization values like so: - // upb.MessageDef{full_name="MyMessage", extstart=8000, fields={...}} - luaL_checktype(L, 1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - luaL_checktype(L, -2, LUA_TSTRING); - const char *key = lua_tostring(L, -2); - - if (streql(key, "full_name")) { // full_name="MyMessage" - CHK(upb_def_setfullname(UPB_UPCAST(md), chkname(L, -1), &status)); - } else if (streql(key, "fields")) { // fields={...} - // Iterate over the list of fields. - luaL_checktype(L, -1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - upb_fielddef *f = lupb_fielddef_checkmutable(L, -1); - CHK(upb_msgdef_addfield(md, f, NULL, &status)); - } - } else { - // TODO: extrange= - luaL_error(L, "Unknown initializer key '%s'", key); - } - } return 1; } +// Unlike other refcounted types we need a custom __gc so that we free our field +// offsets. +static int lupb_msgdef_gc(lua_State *L) { + lupb_refcounted_gc(L); + lupb_msgdef *lmd = luaL_checkudata(L, -1, LUPB_MSGDEF); + free(lmd->field_offsets); + return 0; +} + +static void lupb_msgdef_init(lua_State *L) { + lupb_msgdef *lmd = luaL_checkudata(L, -1, LUPB_MSGDEF); + lmd->L = L; + lmd->field_offsets = NULL; +} + static int lupb_msgdef_add(lua_State *L) { upb_msgdef *m = lupb_msgdef_checkmutable(L, 1); - luaL_checktype(L, 2, LUA_TTABLE); - int n = lua_rawlen(L, 2); - // TODO: add upb interface that lets us avoid this malloc/free. - upb_fielddef **fields = malloc(n * sizeof(upb_fielddef*)); - for (int i = 0; i < n; i++) { - lua_rawgeti(L, -1, i + 1); - fields[i] = lupb_fielddef_checkmutable(L, -1); - lua_pop(L, 1); - } - - upb_status status = UPB_STATUS_INIT; - upb_msgdef_addfields(m, fields, n, NULL, &status); - free(fields); - lupb_checkstatus(L, &status); + upb_fielddef *f = lupb_fielddef_checkmutable(L, 2); + CHK(upb_msgdef_addfield(m, f, NULL, &status)); return 0; } @@ -823,7 +949,9 @@ static int lupb_msgdef_fields(lua_State *L) { const upb_msgdef *m = lupb_msgdef_check(L, 1); upb_msg_iter *i = lua_newuserdata(L, sizeof(upb_msg_iter)); upb_msg_begin(i, m); - lua_pushcclosure(L, &lupb_msgiter_next, 1); + // Need to guarantee that the msgdef outlives the iter. + lua_pushvalue(L, 1); + lua_pushcclosure(L, &lupb_msgiter_next, 2); return 1; } @@ -850,65 +978,27 @@ static const struct luaL_Reg lupb_msgdef_m[] = { /* lupb_enumdef ***************************************************************/ const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_ENUMDEF); - if (!r) luaL_typerror(L, narg, LUPB_ENUMDEF); - if (!r->refcounted) luaL_error(L, "called into dead enumdef"); - return upb_downcast_enumdef(r->def); + return lupb_refcounted_check(L, narg, LUPB_ENUMDEF); } static upb_enumdef *lupb_enumdef_checkmutable(lua_State *L, int narg) { const upb_enumdef *f = lupb_enumdef_check(L, narg); if (upb_enumdef_isfrozen(f)) - luaL_typerror(L, narg, "not allowed on frozen value"); + luaL_error(L, "not allowed on frozen value"); return (upb_enumdef*)f; } -static int lupb_enumdef_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_ENUMDEF); - upb_def_unref(r->def, r); - r->refcounted = NULL; - return 0; -} - static int lupb_enumdef_new(lua_State *L) { - int narg = lua_gettop(L); upb_enumdef *e = upb_enumdef_new(&e); lupb_def_pushnewrapper(L, UPB_UPCAST(e), &e); - - if (narg == 0) return 1; - - // User can specify initialization values like so: - // upb.EnumDef{full_name="MyEnum", - // values={ - // {"FOO_VALUE_1", 1}, - // {"FOO_VALUE_2", 2} - // } - // } - luaL_checktype(L, 1, LUA_TTABLE); - for (lua_pushnil(L); lua_next(L, 1); lua_pop(L, 1)) { - luaL_checktype(L, -2, LUA_TSTRING); - const char *key = lua_tostring(L, -2); - if (streql(key, "values")) { - for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { - lua_rawgeti(L, -1, 1); - luaL_checktype(L, -1, LUA_TSTRING); - const char *name = lua_tostring(L, -1); - lua_rawgeti(L, -2, 2); - CHK(upb_enumdef_addval(e, name, chkint32(L, -1, "value"), &status)); - lua_pop(L, 2); // The key/val we got from lua_rawgeti() - } - } else if (streql(key, "full_name")) { - CHK(upb_def_setfullname(UPB_UPCAST(e), chkname(L, -1), &status)); - } else { - luaL_error(L, "Unknown initializer key '%s'", key); - } - } return 1; } static int lupb_enumdef_add(lua_State *L) { upb_enumdef *e = lupb_enumdef_checkmutable(L, 1); - CHK(upb_enumdef_addval(e, chkname(L, 2), chkint32(L, 3, "value"), &status)); + const char *name = lupb_checkname(L, 2); + int32_t val = lupb_checkint32(L, 3); + CHK(upb_enumdef_addval(e, name, val, &status)); return 0; } @@ -923,11 +1013,13 @@ static int lupb_enumdef_value(lua_State *L) { int type = lua_type(L, 2); if (type == LUA_TNUMBER) { // Pushes "nil" for a NULL pointer. - lua_pushstring(L, upb_enumdef_iton(e, chkint32(L, 2, "value"))); + int32_t key = lupb_checkint32(L, 2); + lua_pushstring(L, upb_enumdef_iton(e, key)); } else if (type == LUA_TSTRING) { + const char *key = lua_tostring(L, 2); int32_t num; - if (upb_enumdef_ntoi(e, lua_tostring(L, 2), &num)) { - lua_pushnumber(L, num); + if (upb_enumdef_ntoi(e, key, &num)) { + lua_pushinteger(L, num); } else { lua_pushnil(L); } @@ -943,7 +1035,7 @@ static int lupb_enumiter_next(lua_State *L) { upb_enum_iter *i = lua_touserdata(L, lua_upvalueindex(1)); if (upb_enum_done(i)) return 0; lua_pushstring(L, upb_enum_iter_name(i)); - lua_pushnumber(L, upb_enum_iter_number(i)); + lua_pushinteger(L, upb_enum_iter_number(i)); upb_enum_next(i); return 2; } @@ -952,12 +1044,13 @@ static int lupb_enumdef_values(lua_State *L) { const upb_enumdef *e = lupb_enumdef_check(L, 1); upb_enum_iter *i = lua_newuserdata(L, sizeof(upb_enum_iter)); upb_enum_begin(i, e); - lua_pushcclosure(L, &lupb_enumiter_next, 1); + // Need to guarantee that the enumdef outlives the iter. + lua_pushvalue(L, 1); + lua_pushcclosure(L, &lupb_enumiter_next, 2); return 1; } static const struct luaL_Reg lupb_enumdef_mm[] = { - {"__gc", lupb_enumdef_gc}, {"__len", lupb_enumdef_len}, {NULL, NULL} }; @@ -976,83 +1069,95 @@ static const struct luaL_Reg lupb_enumdef_m[] = { // Inherits a ref on the symtab. // Checks that narg is a proper lupb_symtab object. If it is, leaves its // metatable on the stack for cache lookups/updates. -upb_symtab *lupb_symtab_check(lua_State *L, int narg) { - lupb_refcounted *r = luaL_checkudata(L, narg, LUPB_SYMTAB); - if (!r) luaL_typerror(L, narg, LUPB_SYMTAB); - if (!r->refcounted) luaL_error(L, "called into dead symtab"); - return r->symtab; +const upb_symtab *lupb_symtab_check(lua_State *L, int narg) { + return lupb_refcounted_check(L, narg, LUPB_SYMTAB); } -// narg is a lua table containing a list of defs to add. -void lupb_symtab_doadd(lua_State *L, upb_symtab *s, int narg) { - luaL_checktype(L, narg, LUA_TTABLE); - // Iterate over table twice. First iteration to count entries and - // check constraints. - int n = 0; - for (lua_pushnil(L); lua_next(L, narg); lua_pop(L, 1)) { - lupb_def_check(L, -1); - ++n; - } +static upb_symtab *lupb_symtab_checkmutable(lua_State *L, int narg) { + const upb_symtab *s = lupb_symtab_check(L, narg); + if (upb_symtab_isfrozen(s)) + luaL_error(L, "not allowed on frozen value"); + return (upb_symtab*)s; +} - // Second iteration to build deflist and layout. - upb_def **defs = malloc(n * sizeof(*defs)); - n = 0; - for (lua_pushnil(L); lua_next(L, narg); lua_pop(L, 1)) { - upb_def *def = lupb_def_checkmutable(L, -1); - defs[n++] = def; - } +void lupb_symtab_pushwrapper(lua_State *L, const upb_symtab *s, + const void *ref_donor) { + lupb_refcounted_pushwrapper(L, UPB_UPCAST(s), LUPB_SYMTAB, ref_donor, + sizeof(void *)); +} - upb_status status = UPB_STATUS_INIT; - upb_symtab_add(s, defs, n, NULL, &status); - free(defs); - lupb_checkstatus(L, &status); +void lupb_symtab_pushnewrapper(lua_State *L, const upb_symtab *s, + const void *ref_donor) { + lupb_refcounted_pushnewrapper(L, UPB_UPCAST(s), LUPB_SYMTAB, ref_donor); } static int lupb_symtab_new(lua_State *L) { - int narg = lua_gettop(L); upb_symtab *s = upb_symtab_new(&s); - lupb_refcounted_pushnewrapper(L, UPB_UPCAST(s), LUPB_SYMTAB, &s); - if (narg > 0) lupb_symtab_doadd(L, s, 1); + lupb_symtab_pushnewrapper(L, s, &s); return 1; } -static int lupb_symtab_add(lua_State *L) { - lupb_symtab_doadd(L, lupb_symtab_check(L, 1), 2); +static int lupb_symtab_freeze(lua_State *L) { + upb_symtab_freeze(lupb_symtab_checkmutable(L, 1)); return 0; } -static int lupb_symtab_gc(lua_State *L) { - lupb_refcounted *r = luaL_checkudata(L, 1, LUPB_SYMTAB); - upb_symtab_unref(r->symtab, r); - r->refcounted = NULL; +static int lupb_symtab_isfrozen(lua_State *L) { + lua_pushboolean(L, upb_symtab_isfrozen(lupb_symtab_check(L, 1))); + return 1; +} + +static int lupb_symtab_add(lua_State *L) { + upb_symtab *s = lupb_symtab_checkmutable(L, 1); + luaL_checktype(L, 2, LUA_TTABLE); + // Iterate over table twice. First iteration to count entries and + // check constraints. + int n = 0; + for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { + lupb_def_checkmutable(L, -1); + ++n; + } + + // Second iteration to build deflist. + // Allocate list with lua_newuserdata() so it is anchored as a GC root in + // case any Lua functions longjmp(). + upb_def **defs = lua_newuserdata(L, n * sizeof(*defs)); + n = 0; + for (lua_pushnil(L); lua_next(L, 2); lua_pop(L, 1)) { + upb_def *def = lupb_def_checkmutable(L, -1); + defs[n++] = def; + } + + CHK(upb_symtab_add(s, defs, n, NULL, &status)); return 0; } static int lupb_symtab_lookup(lua_State *L) { - upb_symtab *s = lupb_symtab_check(L, 1); + const upb_symtab *s = lupb_symtab_check(L, 1); for (int i = 2; i <= lua_gettop(L); i++) { - const upb_def *def = - upb_symtab_lookup(s, luaL_checkstring(L, i), &def); - lupb_def_pushwrapper(L, def, &def); + const upb_def *def = upb_symtab_lookup(s, luaL_checkstring(L, i)); + lupb_def_pushwrapper(L, def, NULL); lua_replace(L, i); } return lua_gettop(L) - 1; } -static int lupb_symtab_getdefs(lua_State *L) { - upb_symtab *s = lupb_symtab_check(L, 1); - upb_deftype_t type = luaL_checkint(L, 2); - int count; - const upb_def **defs = upb_symtab_getdefs(s, type, &defs, &count); +static int lupb_symtabiter_next(lua_State *L) { + upb_symtab_iter *i = lua_touserdata(L, lua_upvalueindex(1)); + if (upb_symtab_done(i)) return 0; + lupb_def_pushwrapper(L, upb_symtab_iter_def(i), NULL); + upb_symtab_next(i); + return 1; +} - // Create the table in which we will return the defs. - lua_createtable(L, count, 0); - for (int i = 0; i < count; i++) { - const upb_def *def = defs[i]; - lupb_def_pushwrapper(L, def, &defs); - lua_rawseti(L, -2, i + 1); - } - free(defs); +static int lupb_symtab_defs(lua_State *L) { + const upb_symtab *s = lupb_symtab_check(L, 1); + upb_deftype_t type = lua_gettop(L) > 1 ? luaL_checkint(L, 2) : UPB_DEF_ANY; + upb_symtab_iter *i = lua_newuserdata(L, sizeof(upb_symtab_iter)); + upb_symtab_begin(i, s, type); + // Need to guarantee that the symtab outlives the iter. + lua_pushvalue(L, 1); + lua_pushcclosure(L, &lupb_symtabiter_next, 2); return 1; } @@ -1061,7 +1166,7 @@ static int lupb_symtab_getdefs(lua_State *L) { // the descriptor.proto schema and the protobuf binary format. static int lupb_symtab_load_descriptor(lua_State *L) { size_t len; - upb_symtab *s = lupb_symtab_check(L, 1); + upb_symtab *s = lupb_symtab_checkmutable(L, 1); const char *str = luaL_checklstring(L, 2, &len); CHK(upb_load_descriptor_into_symtab(s, str, len, &status)); return 0; @@ -1069,67 +1174,598 @@ static int lupb_symtab_load_descriptor(lua_State *L) { static const struct luaL_Reg lupb_symtab_m[] = { {"add", lupb_symtab_add}, - {"getdefs", lupb_symtab_getdefs}, + {"defs", lupb_symtab_defs}, + {"freeze", lupb_symtab_freeze}, + {"is_frozen", lupb_symtab_isfrozen}, {"lookup", lupb_symtab_lookup}, {"load_descriptor", lupb_symtab_load_descriptor}, {NULL, NULL} }; -static const struct luaL_Reg lupb_symtab_mm[] = { - {"__gc", lupb_symtab_gc}, + +/* lupb_array *****************************************************************/ + +// A lupb_array provides a strongly-typed array. +// +// For the moment we store all values in the userdata's environment table / +// userval, for simplicity. Later we may wish to move the data into raw +// memory as both a space and time optimization. +// +// Compared to regular Lua tables: +// +// - we only allow integer indices. +// - all entries must match the type of the table. +// - we do not allow "holes" in the array; you can only assign to an existing +// index or one past the end (which will grow the array by one). + +typedef struct { + uint32_t size; + upb_fieldtype_t type; + const upb_msgdef *msgdef; // Only when type == UPB_TYPE_MESSAGE +} lupb_array; + +static lupb_array *lupb_array_check(lua_State *L, int narg) { + return luaL_checkudata(L, narg, LUPB_ARRAY); +} + +static uint32_t lupb_array_checkindex(lua_State *L, int narg, uint32_t max) { + uint32_t n = lupb_checkuint32(L, narg); + if (n == 0 || n > max) { // Lua uses 1-based indexing. :( + luaL_error(L, "Invalid array index."); + } + return n; +} + +static int lupb_array_new(lua_State *L) { + lupb_array *array = newudata_with_userval(L, sizeof(*array), LUPB_ARRAY); + array->size = 0; + + if (lua_type(L, 1) == LUA_TNUMBER) { + array->type = lupb_checkfieldtype(L, 1); + if (array->type == UPB_TYPE_MESSAGE) { + return luaL_error( + L, "For message arrays construct with the specific message type."); + } + } else { + array->type = UPB_TYPE_MESSAGE; + array->msgdef = lupb_msgdef_check(L, 1); + + // Store a reference to this msgdef in the environment table to ensure it + // outlives this array. + lua_getuservalue(L, -1); + lua_pushvalue(L, 1); + lua_rawseti(L, -2, 0); + lua_pop(L, 1); // Pop userval. + } + + return 1; +} + +static int lupb_array_newindex(lua_State *L) { + lupb_array *array = lupb_array_check(L, 1); + uint32_t n = lupb_array_checkindex(L, 2, array->size + 1); + + if (n == array->size + 1) { + array->size++; + } + + if (array->type == UPB_TYPE_MESSAGE) { + if (array->msgdef != lupb_msg_checkdef(L, 3)) { + return luaL_error(L, "Tried to assign wrong message type."); + } + } else { + lupb_checkval(L, 3, array->type); + } + + // Write value to userval table. + lua_getuservalue(L, 1); + lua_pushvalue(L, 3); + lua_rawseti(L, -2, n); + + return 0; // 1 for chained assignments? +} + +static int lupb_array_index(lua_State *L) { + lupb_array *array = lupb_array_check(L, 1); + uint32_t n = lupb_array_checkindex(L, 2, array->size); + + lua_getuservalue(L, 1); + lua_rawgeti(L, -1, n); + return 1; +} + +static int lupb_array_len(lua_State *L) { + lupb_array *array = lupb_array_check(L, 1); + lua_pushnumber(L, array->size); + return 1; +} + +static const struct luaL_Reg lupb_array_mm[] = { + {"__index", lupb_array_index}, + {"__len", lupb_array_len}, + {"__newindex", lupb_array_newindex}, + {NULL, NULL} +}; + +/* lupb_msg **************************************************************/ + +// A lupb_msg is a userdata where: +// +// - the userdata's memory contains hasbits and primitive fields. +// - the userdata's environment table / uservalue contains references to string +// fields, submessage fields, and array fields. + +typedef struct { + const lupb_msgdef *lmd; + char data[]; +} lupb_msg; + +#define MSGDEF_INDEX 0 + +static bool in_userval(const upb_fielddef *f) { + return upb_fielddef_isseq(f) || upb_fielddef_issubmsg(f) || + upb_fielddef_isstring(f); +} + +static size_t lupb_sizeof(lua_State *L, const upb_fielddef *f) { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + return 1; + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + case UPB_TYPE_FLOAT: + return 4; + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + case UPB_TYPE_DOUBLE: + return 8; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + case UPB_TYPE_MESSAGE: + lupb_assert(L, false); + return 0; + } +} + +static int div_round_up(size_t n, size_t d) { + int ret = n / d; + // If there was a positive remainder, then the result was rounded down and we + // need to compensate by adding one. + if (n % d > 0) ++ret; + return ret; +} + +static size_t align_up(size_t val, size_t align) { + return val % align == 0 ? val : val + align - (val % align); +} + +// If we always read/write as a consistent type to each value, this shouldn't +// violate aliasing. +#define DEREF(msg, ofs, type) *(type*)(&msg->data[ofs]) + +lupb_msg *lupb_msg_check(lua_State *L, int narg) { + lupb_msg *msg = luaL_checkudata(L, narg, LUPB_MSG); + if (!msg->lmd) luaL_error(L, "called into dead msg"); + return msg; +} + +const upb_msgdef *lupb_msg_checkdef(lua_State *L, int narg) { + return lupb_msg_check(L, narg)->lmd->md; +} + +static const upb_fielddef *lupb_msg_checkfield(lua_State *L, + const lupb_msgdef *lmd, + int fieldarg) { + const char *fieldname = luaL_checkstring(L, fieldarg); + const upb_fielddef *f = upb_msgdef_ntof(lmd->md, fieldname); + + if (!f) { + const char *msg = lua_pushfstring(L, "no such field: %s", fieldname); + luaL_argerror(L, fieldarg, msg); + return NULL; // Never reached. + } + + return f; +} + +// Assigns offsets for storing data in instances of messages for this type, if +// they have not already been assigned. "narg" should be the stack location of +// a Lua msgdef object. It should be frozen (if it is not, we will throw an +// error). It should not throw errors in any other case, since we may have +// values on our stack that would leak if we longjmp'd across them. +// +// TODO(haberman): (if we want to avoid this and be robust against even lua +// errors due to OOM, we should stop using upb_handlers_newfrozen() and +// implement it ourselves with a Lua table as cache, since that would get +// cleaned up properly on error). +static lupb_msgdef *lupb_msg_assignoffsets(lua_State *L, int narg) { + lupb_msgdef *lmd = lupb_msgdef_check2(L, narg); + if (!upb_msgdef_isfrozen(lmd->md)) + luaL_error(L, "msgdef must be frozen"); + + if (lmd->field_offsets) { + // Already assigned. + return lmd; + } + + int n = upb_msgdef_numfields(lmd->md); + uint16_t *offsets = malloc(sizeof(*offsets) * n); + + // Offset with the raw data part; starts with hasbits. + size_t hasbits_size = div_round_up(n, 8); + size_t data_ofs = hasbits_size; + // Index within the userval. + // Starts at one to not collide with MSGDEF_INDEX. + size_t userval_idx = 1; + + // Assign offsets. + upb_msg_iter i; + for (upb_msg_begin(&i, lmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + if (in_userval(f)) { + offsets[upb_fielddef_index(f)] = userval_idx++; + } else { + size_t size = lupb_sizeof(L, f); + data_ofs = align_up(data_ofs, size); + offsets[upb_fielddef_index(f)] = data_ofs; + data_ofs += size; + } + } + + lmd->field_offsets = offsets; + lmd->msg_size = sizeof(lupb_msg) + data_ofs; + lmd->hasbits_size = hasbits_size; + + // Now recursively assign offsets for all submessages, and also add them to + // the uservalue to ensure that all the lupb_msgdef objects for our + // submessages outlive us. This is particularly important if/when we build + // handlers to populate this msgdef. + + lua_pushvalue(L, narg); + lua_newtable(L); // This will be our userval. + + int idx = 1; + for (upb_msg_begin(&i, lmd->md); !upb_msg_done(&i); upb_msg_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + if (upb_fielddef_type(f) == UPB_TYPE_MESSAGE) { + bool created = lupb_def_pushwrapper(L, upb_fielddef_subdef(f), NULL); + UPB_ASSERT_VAR(created, !created); + lupb_msg_assignoffsets(L, -1); + lua_rawseti(L, -2, idx++); // Append to uservalue. + } + } + + lua_setuservalue(L, -2); + lua_pop(L, 1); // copy of msgdef + + return lmd; +} + +void lupb_msg_pushnew(lua_State *L, int narg) { + lupb_msgdef *lmd = lupb_msg_assignoffsets(L, narg); + + // Add passed-in MessageDef to a table which will become the msg's userval. + lua_pushvalue(L, narg); + lua_newtable(L); + lua_pushvalue(L, narg); + lua_rawseti(L, -2, MSGDEF_INDEX); + + lupb_msg *msg = newudata_with_userval(L, lmd->msg_size, LUPB_MSG); + memset(msg, 0, lmd->msg_size); + + // Create a msg->msgdef reference, both: + // 1. a pointer in the userdata itself (for easy access) and + msg->lmd = lmd; + + // 2. a reference in Lua-space from the msg's uservalue to the messagedef + // wrapper object (so the msgdef wrapper object will always outlive us, + // GC-wise). + lua_pushvalue(L, -2); // Push the table from before. + lua_setuservalue(L, -2); // Pop table, now msg is at top again. + lua_remove(L, -2); // Remove table, so new message is only new value. +} + +static int lupb_msg_new(lua_State *L) { + lupb_msg_pushnew(L, 1); + return 1; +} + +static bool lupb_msg_has(const lupb_msg *msg, const upb_fielddef *f) { + uint16_t idx = upb_fielddef_index(f); + return msg->data[idx / 8] & (1 << (idx % 8)); +} + +static void lupb_msg_set(lupb_msg *msg, const upb_fielddef *f) { + uint16_t idx = upb_fielddef_index(f); + msg->data[idx / 8] |= (1 << (idx % 8)); +} + +static int lupb_msg_index(lua_State *L) { + lupb_msg *msg = lupb_msg_check(L, 1); + const upb_fielddef *f = lupb_msg_checkfield(L, msg->lmd, 2); + + if (!upb_fielddef_isseq(f) && !lupb_msg_has(msg, f)) { + lua_pushnil(L); + return 1; + } + + int ofs = msg->lmd->field_offsets[upb_fielddef_index(f)]; + + if (in_userval(f)) { + lua_getuservalue(L, 1); + lua_pushinteger(L, ofs); + lua_rawget(L, -2); + } else { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_FLOAT: + lupb_pushfloat(L, DEREF(msg, ofs, float)); + break; + case UPB_TYPE_DOUBLE: + lupb_pushdouble(L, DEREF(msg, ofs, double)); + break; + case UPB_TYPE_BOOL: + lua_pushboolean(L, DEREF(msg, ofs, bool)); + break; + case UPB_TYPE_ENUM: + case UPB_TYPE_INT32: + lupb_pushint32(L, DEREF(msg, ofs, int32_t)); + break; + case UPB_TYPE_UINT32: + lupb_pushuint32(L, DEREF(msg, ofs, uint32_t)); + break; + case UPB_TYPE_INT64: + if (LUA_VERSION_NUM < 503) { + // Check value? Lua < 5.3.0 has no native integer support, lua_Number + // is probably double which can't exactly represent large int64s. + } + lupb_pushint64(L, DEREF(msg, ofs, int64_t)); + break; + case UPB_TYPE_UINT64: + if (LUA_VERSION_NUM < 503) { + // Check value? Lua < 5.3.0 has no native integer support, lua_Number + // is probably double which can't exactly represent large uint64s. + } + lupb_pushuint64(L, DEREF(msg, ofs, uint64_t)); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + case UPB_TYPE_MESSAGE: + lupb_assert(L, false); + break; + } + } + + return 1; +} + +int lupb_msg_newindex(lua_State *L) { + lupb_msg *msg = lupb_msg_check(L, 1); + const upb_fielddef *f = lupb_msg_checkfield(L, msg->lmd, 2); + + lupb_msg_set(msg, f); + + int ofs = msg->lmd->field_offsets[upb_fielddef_index(f)]; + + if (in_userval(f)) { + // Type-check and then store in the userval. + if (upb_fielddef_isseq(f)) { + lupb_array *array = lupb_array_check(L, 3); + if (array->type != upb_fielddef_type(f) || + (array->type == UPB_TYPE_MESSAGE && + array->msgdef != upb_fielddef_msgsubdef(f))) { + return luaL_error(L, "Array type mismatch"); + } + } else if (upb_fielddef_isstring(f)) { + lupb_checkstring(L, 3); + } else { + if (lupb_msg_checkdef(L, 3) != upb_fielddef_msgsubdef(f)) { + return luaL_error(L, "Message type mismatch"); + } + } + lua_getuservalue(L, 1); + lua_pushvalue(L, 3); + lua_rawseti(L, -2, ofs); + } else { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_FLOAT: + DEREF(msg, ofs, float) = lupb_checkfloat(L, 3); + break; + case UPB_TYPE_DOUBLE: + DEREF(msg, ofs, double) = lupb_checkdouble(L, 3); + break; + case UPB_TYPE_ENUM: + case UPB_TYPE_INT32: + DEREF(msg, ofs, int32_t) = lupb_checkint32(L, 3); + break; + case UPB_TYPE_UINT32: + DEREF(msg, ofs, uint32_t) = lupb_checkuint32(L, 3); + break; + case UPB_TYPE_INT64: + DEREF(msg, ofs, int64_t) = lupb_checkint64(L, 3); + break; + case UPB_TYPE_UINT64: + DEREF(msg, ofs, uint64_t) = lupb_checkuint64(L, 3); + break; + case UPB_TYPE_BOOL: + DEREF(msg, ofs, bool) = lupb_checkbool(L, 3); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: + case UPB_TYPE_MESSAGE: + lupb_assert(L, false); + } + } + + return 0; // 1 for chained assignments? +} + +static const struct luaL_Reg lupb_msg_mm[] = { + {"__index", lupb_msg_index}, + {"__newindex", lupb_msg_newindex}, {NULL, NULL} }; +/* lupb_msg populating handlers ***********************************************/ + +// NOTE: doesn't support repeated or submessage fields yet. Coming soon. + +typedef struct { + uint32_t ofs; + uint32_t hasbit; +} lupb_handlerdata; + +static void lupb_sethasbit(lupb_msg *msg, uint32_t hasbit) { + msg->data[hasbit / 8] |= 1 << (hasbit % 8); +} + +static size_t strhandler(void *closure, const void *hd, const char *str, + size_t len, const upb_bufhandle *handle) { + lupb_msg *msg = closure; + const lupb_handlerdata *data = hd; + lua_State *L = msg->lmd->L; + lua_pushlstring(L, str, len); + lua_rawseti(L, -2, data->ofs); + lupb_sethasbit(msg, data->hasbit); + return len; +} + +const void *newhandlerdata(upb_handlers *h, uint32_t ofs, uint32_t hasbit) { + lupb_handlerdata *data = malloc(sizeof(*data)); + data->ofs = ofs; + data->hasbit = hasbit; + upb_handlers_addcleanup(h, data, free); + return data; +} + +void callback(const void *closure, upb_handlers *h) { + lua_State *L = (lua_State*)closure; + lupb_def_pushwrapper(L, UPB_UPCAST(upb_handlers_msgdef(h)), NULL); + lupb_msgdef *lmd = lupb_msg_assignoffsets(L, -1); + upb_msg_iter i; + upb_msg_begin(&i, upb_handlers_msgdef(h)); + for (; !upb_msg_done(&i); upb_msg_next(&i)) { + upb_fielddef *f = upb_msg_iter_field(&i); + int hasbit = upb_fielddef_index(f); + uint16_t ofs = lmd->field_offsets[upb_fielddef_index(f)]; + if (upb_fielddef_isseq(f)) { + luaL_error(L, "Doesn't support repeated fields yet."); + } else { + switch (upb_fielddef_type(f)) { + case UPB_TYPE_BOOL: + case UPB_TYPE_INT32: + case UPB_TYPE_UINT32: + case UPB_TYPE_ENUM: + case UPB_TYPE_FLOAT: + case UPB_TYPE_INT64: + case UPB_TYPE_UINT64: + case UPB_TYPE_DOUBLE: + hasbit += offsetof(lupb_msg, data) * 8; + ofs += offsetof(lupb_msg, data); + upb_shim_set(h, f, ofs, hasbit); + break; + case UPB_TYPE_STRING: + case UPB_TYPE_BYTES: { + upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr_sethandlerdata(&attr, newhandlerdata(h, ofs, hasbit)); + // XXX: does't currently handle split buffers. + upb_handlers_setstring(h, f, strhandler, &attr); + upb_handlerattr_uninit(&attr); + break; + } + case UPB_TYPE_MESSAGE: + luaL_error(L, "Doesn't support submessages yet."); + break; + } + } + } + lua_pop(L, 1); // msgdef wrapper +} + +const upb_handlers *lupb_msg_newwritehandlers(lua_State *L, int narg, + const void *owner) { + lupb_msgdef *lmd = lupb_msg_assignoffsets(L, narg); + return upb_handlers_newfrozen(lmd->md, owner, callback, L); +} + + /* lupb toplevel **************************************************************/ -static int lupb_def_freeze(lua_State *L) { +static int lupb_freeze(lua_State *L) { int n = lua_gettop(L); - upb_def **defs = malloc(n * sizeof(upb_def*)); + // Scratch memory; lua_newuserdata() anchors it as a GC root in case any Lua + // functions fail. + upb_def **defs = lua_newuserdata(L, n * sizeof(upb_def*)); for (int i = 0; i < n; i++) { // Could allow an array of defs here also. defs[i] = lupb_def_checkmutable(L, i + 1); } - upb_status s = UPB_STATUS_INIT; - upb_def_freeze(defs, n, &s); - free(defs); - lupb_checkstatus(L, &s); + CHK(upb_def_freeze(defs, n, &status)); return 0; } static const struct luaL_Reg lupb_toplevel_m[] = { + {"Array", lupb_array_new}, {"EnumDef", lupb_enumdef_new}, {"FieldDef", lupb_fielddef_new}, + {"Message", lupb_msg_new}, {"MessageDef", lupb_msgdef_new}, {"SymbolTable", lupb_symtab_new}, - {"freeze", lupb_def_freeze}, + {"freeze", lupb_freeze}, {NULL, NULL} }; -// Register the given type with the given methods and metamethods. -static void lupb_register_type(lua_State *L, const char *name, - const luaL_Reg *m, const luaL_Reg *mm) { +void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, + const luaL_Reg *mm, bool refcount_gc) { luaL_newmetatable(L, name); - lupb_setfuncs(L, mm); // Register all mm in the metatable. - lua_createtable(L, 0, 0); - // Methods go in the mt's __index method. This implies that you can't - // implement __index. - lupb_setfuncs(L, m); - lua_setfield(L, -2, "__index"); + + if (mm) { + lupb_setfuncs(L, mm); + } + + if (refcount_gc) { + lupb_setfuncs(L, lupb_refcounted_mm); + } + + if (m) { + // Methods go in the mt's __index method. This implies that you can't + // implement __index and also have methods. + lua_getfield(L, -1, "__index"); + lupb_assert(L, lua_isnil(L, -1)); + lua_pop(L, 1); + + lua_createtable(L, 0, 0); + lupb_setfuncs(L, m); + lua_setfield(L, -2, "__index"); + } + lua_pop(L, 1); // The mt. } static void lupb_setfieldi(lua_State *L, const char *field, int i) { - lua_pushnumber(L, i); + lua_pushinteger(L, i); lua_setfield(L, -2, field); } int luaopen_upb(lua_State *L) { - lupb_register_type(L, LUPB_MSGDEF, lupb_msgdef_m, lupb_msgdef_mm); - lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm); - lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, lupb_fielddef_mm); - lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, lupb_symtab_mm); + static char module_key; + if (lupb_openlib(L, &module_key, "upb", lupb_toplevel_m)) { + return 1; + } + + // Non-refcounted types. + lupb_register_type(L, LUPB_ARRAY, NULL, lupb_array_mm, false); + lupb_register_type(L, LUPB_MSG, NULL, lupb_msg_mm, false); + + // Refcounted types. + lupb_register_type(L, LUPB_ENUMDEF, lupb_enumdef_m, lupb_enumdef_mm, true); + lupb_register_type(L, LUPB_FIELDDEF, lupb_fielddef_m, NULL, true); + lupb_register_type(L, LUPB_SYMTAB, lupb_symtab_m, NULL, true); + + // Refcounted but with custom __gc. + lupb_register_type(L, LUPB_MSGDEF, lupb_msgdef_m, lupb_msgdef_mm, false); // Create our object cache. lua_newtable(L); @@ -1139,26 +1775,6 @@ int luaopen_upb(lua_State *L) { lua_setmetatable(L, -2); lua_setfield(L, LUA_REGISTRYINDEX, LUPB_OBJCACHE); - lupb_newlib(L, "upb", lupb_toplevel_m); - - // Define a couple functions as Lua source (kept here instead of a separate - // Lua file so that upb.so is self-contained) - const char *lua_source = - "return function(upb)\n" - " upb.build_defs = function(defs)\n" - " local symtab = upb.SymbolTable(defs)\n" - " return symtab:getdefs(upb.DEF_ANY)\n" - " end\n" - "end"; - - if (luaL_dostring(L, lua_source) != 0) - lua_error(L); - - // Call the chunk that will define the extra functions on upb, passing our - // package dictionary as the argument. - lua_pushvalue(L, -2); - lua_call(L, 1, 0); - // Register constants. lupb_setfieldi(L, "LABEL_OPTIONAL", UPB_LABEL_OPTIONAL); lupb_setfieldi(L, "LABEL_REQUIRED", UPB_LABEL_REQUIRED); @@ -1220,8 +1836,14 @@ int luaopen_upb(lua_State *L) { lupb_setfieldi(L, "HANDLER_STARTSEQ", UPB_HANDLER_STARTSEQ); lupb_setfieldi(L, "HANDLER_ENDSEQ", UPB_HANDLER_ENDSEQ); + // Call the chunk that will define the extra functions on upb, passing our + // package dictionary as the argument. + if (luaL_loadbuffer(L, upb_lua, sizeof(upb_lua), "upb.lua") || + lua_pcall(L, 0, LUA_MULTRET, 0)) { + lua_error(L); + } + lua_pushvalue(L, -2); + lua_call(L, 1, 0); + return 1; // Return package table. } - -// Alternate names so that the library can be loaded as upb5_1 etc. -int LUPB_OPENFUNC(upb)(lua_State *L) { return luaopen_upb(L); } diff --git a/upb/bindings/lua/upb.h b/upb/bindings/lua/upb.h index e6b4f2f..99fe8fe 100644 --- a/upb/bindings/lua/upb.h +++ b/upb/bindings/lua/upb.h @@ -10,36 +10,120 @@ #ifndef UPB_LUA_UPB_H_ #define UPB_LUA_UPB_H_ +#include "lauxlib.h" #include "upb/def.h" +#include "upb/handlers.h" +#include "upb/symtab.h" // Lua 5.1/5.2 compatibility code. #if LUA_VERSION_NUM == 501 #define lua_rawlen lua_objlen -#define lupb_newlib(L, name, l) luaL_register(L, name, l) -#define lupb_setfuncs(L, l) luaL_register(L, NULL, l) -#define LUPB_OPENFUNC(mod) luaopen_ ## mod ## upb5_1 + +// Lua >= 5.2's getuservalue/setuservalue functions do not exist in prior +// versions but the older function lua_getfenv() can provide 100% of its +// capabilities (the reverse is not true). +#define lua_getuservalue(L, index) lua_getfenv(L, index) +#define lua_setuservalue(L, index) lua_setfenv(L, index) void *luaL_testudata(lua_State *L, int ud, const char *tname); #elif LUA_VERSION_NUM == 502 -// Lua 5.2 modules are not expected to set a global variable, so "name" is -// unused. -#define lupb_newlib(L, name, l) luaL_newlib(L, l) -#define lupb_setfuncs(L, l) luaL_setfuncs(L, l, 0) int luaL_typerror(lua_State *L, int narg, const char *tname); -#define LUPB_OPENFUNC(mod) luaopen_ ## mod ## upb5_2 #else #error Only Lua 5.1 and 5.2 are supported #endif +#define lupb_assert(L, predicate) \ + if (!(predicate)) \ + luaL_error(L, "internal error: %s, %s:%d ", #predicate, __FILE__, __LINE__); + +// Function for initializing the core library. This function is idempotent, +// and should be called at least once before calling any of the functions that +// construct core upb types. +int luaopen_upb(lua_State *L); + +// Gets or creates a package table for a C module that is uniquely identified by +// "ptr". The easiest way to supply a unique "ptr" is to pass the address of a +// static variable private in the module's .c file. +// +// If this module has already been registered in this lua_State, pushes it and +// returns true. +// +// Otherwise, creates a new module table for this module with the given name, +// pushes it, and registers the given top-level functions in it. It also sets +// it as a global variable, but only if the current version of Lua expects that +// (ie Lua 5.1/LuaJIT). +// +// If "false" is returned, the caller is guaranteed that this lib has not been +// registered in this Lua state before (regardless of any funny business the +// user might have done to the global state), so the caller can safely perform +// one-time initialization. +bool lupb_openlib(lua_State *L, void *ptr, const char *name, + const luaL_Reg *funcs); + +// Custom check/push functions. Unlike the Lua equivalents, they are pinned to +// specific types (instead of lua_Number, etc), and do not allow any implicit +// conversion or data loss. +int64_t lupb_checkint64(lua_State *L, int narg); +int32_t lupb_checkint32(lua_State *L, int narg); +uint64_t lupb_checkuint64(lua_State *L, int narg); +uint32_t lupb_checkuint32(lua_State *L, int narg); +double lupb_checkdouble(lua_State *L, int narg); +float lupb_checkfloat(lua_State *L, int narg); +bool lupb_checkbool(lua_State *L, int narg); +const char *lupb_checkname(lua_State *L, int narg); + +void lupb_pushint64(lua_State *L, int64_t val); +void lupb_pushint32(lua_State *L, int32_t val); +void lupb_pushuint64(lua_State *L, uint64_t val); +void lupb_pushuint32(lua_State *L, uint32_t val); +void lupb_pushdouble(lua_State *L, double val); +void lupb_pushfloat(lua_State *L, float val); +void lupb_pushbool(lua_State *L, bool val); + +// Functions for getting/pushing wrappers to various types defined in the +// core library. +void *lupb_refcounted_check(lua_State *L, int narg, const char *type); +const upb_msgdef *lupb_msg_checkdef(lua_State *L, int narg); const upb_msgdef *lupb_msgdef_check(lua_State *L, int narg); const upb_enumdef *lupb_enumdef_check(lua_State *L, int narg); -const char *lupb_checkname(lua_State *L, int narg); -bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, const void *owner); +const upb_fielddef *lupb_fielddef_check(lua_State *L, int narg); +const upb_symtab *lupb_symtab_check(lua_State *L, int narg); + +void lupb_refcounted_pushnewrapper(lua_State *L, const upb_refcounted *obj, + const char *type, const void *ref_donor); +bool lupb_def_pushwrapper(lua_State *L, const upb_def *def, + const void *ref_donor); void lupb_def_pushnewrapper(lua_State *L, const upb_def *def, - const void *owner); + const void *ref_donor); +void lupb_symtab_pushwrapper(lua_State *L, const upb_symtab *s, + const void *ref_donor); +void lupb_symtab_pushnewrapper(lua_State *L, const upb_symtab *s, + const void *ref_donor); + +// For constructing a new message. narg is the Lua value for the MessageDef +// object. +void lupb_msg_pushnew(lua_State *L, int narg); + +// Builds and returns a handlers object for populating a lupb_msg described by +// the MessageDef at "narg". +// +// TODO(haberman): factor this so it doesn't have to take a lua_State. We +// should be able to generate message handlers for a upb_msgdef that can be used +// across many Lua states, so we can shared JIT code across lua_States. +const upb_handlers *lupb_msg_newwritehandlers(lua_State *L, int narg, + const void *owner); + +// Registers a type with the given name, methods, and metamethods. +// If "refcount_gc" is true, adds a __gc metamethod that does an unref. +// Refcounted types must be allocated with lupb_refcounted_push[new]wrapper. +void lupb_register_type(lua_State *L, const char *name, const luaL_Reg *m, + const luaL_Reg *mm, bool refcount_gc); + +// Checks the given upb_status and throws a Lua error if it is not ok. +void lupb_checkstatus(lua_State *L, upb_status *s); #endif // UPB_LUA_UPB_H_ diff --git a/upb/bindings/lua/upb.lua b/upb/bindings/lua/upb.lua new file mode 100644 index 0000000..bda9dfe --- /dev/null +++ b/upb/bindings/lua/upb.lua @@ -0,0 +1,146 @@ +-- +-- upb - a minimalist implementation of protocol buffers. +-- +-- Copyright (c) 2009 Google Inc. See LICENSE for details. +-- Author: Josh Haberman <jhaberman@gmail.com> +-- +-- Pure-Lua support functions that are part of the "upb" module. +-- This file is embedded and packaged into the "upb" C module binary -- it +-- should not be installed or used directly! + +return function(upb) + -- A convenience function for building/linking/freezing defs + -- while maintaining their original order. + -- + -- Sample usage: + -- local m1, m2 = upb.build_defs{ + -- upb.MessageDef{full_name = "M1", fields = { + -- upb.FieldDef{ + -- name = "m2", + -- number = 1, + -- type = upb.TYPE_MESSAGE, + -- subdef_name = ".M2" + -- }, + -- } + -- }, + -- upb.MessageDef{full_name = "M2"} + -- } + upb.build_defs = function(defs) + upb.SymbolTable(defs) + -- Lua 5.2 puts unpack in the table library. + return (unpack or table.unpack)(defs) + end + + local ipairs_iter = function(array, last_index) + local next_index = last_index + 1 + if next_index > #array then + return nil + end + return next_index, array[next_index] + end + + -- For iterating over the indexes and values of a upb.Array. + -- + -- for i, val in upb.ipairs(array) do + -- -- ... + -- end + upb.ipairs = function(array) + return ipairs_iter, array, 0 + end + + local set_named = function(obj, init) + for k, v in pairs(init) do + local func = obj["set_" .. k] + if not func then + error("Cannot set member: " .. k) + end + func(obj, v) + end + end + + -- Capture references to the functions we're wrapping. + local RealFieldDef = upb.FieldDef + local RealEnumDef = upb.EnumDef + local RealMessageDef = upb.MessageDef + local RealSymbolTable = upb.SymbolTable + + -- FieldDef constructor; a wrapper around the real constructor that can + -- set initial properties. + -- + -- User can specify initialization values like so: + -- upb.FieldDef{label=upb.LABEL_REQUIRED, name="my_field", number=5, + -- type=upb.TYPE_INT32, default_value=12, type_name="Foo"} + upb.FieldDef = function(init) + local f = RealFieldDef() + + if init then + -- Other members are often dependent on type, so set that first. + if init.type then + f:set_type(init.type) + init.type = nil + end + + set_named(f, init) + end + + return f + end + + + -- MessageDef constructor; a wrapper around the real constructor that can + -- set initial properties. + -- + -- User can specify initialization values like so: + -- upb.MessageDef{full_name="MyMessage", extstart=8000, fields={...}} + upb.MessageDef = function(init) + local m = RealMessageDef() + + if init then + for _, f in pairs(init.fields or {}) do + m:add(f) + end + init.fields = nil + + set_named(m, init) + end + + return m + end + + -- EnumDef constructor; a wrapper around the real constructor that can + -- set initial properties. + -- + -- User can specify initialization values like so: + -- upb.EnumDef{full_name="MyEnum", + -- values={ + -- {"FOO_VALUE_1", 1}, + -- {"FOO_VALUE_2", 2} + -- } + -- } + upb.EnumDef = function(init) + local e = RealEnumDef() + + if init then + for _, val in pairs(init.values or {}) do + e:add(val[1], val[2]) + end + init.values = nil + + set_named(e, init) + end + + return e + end + + -- SymbolTable constructor; a wrapper around the real constructor that can + -- add an initial set of defs. + upb.SymbolTable = function(defs) + local s = RealSymbolTable() + + if defs then + s:add(defs) + end + + return s + end +end diff --git a/upb/bindings/lua/upb.pb.c b/upb/bindings/lua/upb.pb.c new file mode 100644 index 0000000..c9f1f47 --- /dev/null +++ b/upb/bindings/lua/upb.pb.c @@ -0,0 +1,106 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2014 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * A Lua extension for upb.pb. + * + * Exposes all the types defined in upb/pb/{*}.h + * Also defines a few convenience functions on top. + */ + +#include "upb/bindings/lua/upb.h" +#include "upb/pb/decoder.h" + +#define LUPB_PBDECODERMETHOD "lupb.pb.decodermethod" + +#define MSGDEF_INDEX 1 + +static upb_pbdecodermethod *lupb_pbdecodermethod_check(lua_State *L, int narg) { + return lupb_refcounted_check(L, narg, LUPB_PBDECODERMETHOD); +} + +static int lupb_pbdecodermethod_new(lua_State *L) { + const upb_handlers *handlers = lupb_msg_newwritehandlers(L, 1, &handlers); + + upb_pbdecodermethodopts opts; + upb_pbdecodermethodopts_init(&opts, handlers); + + const upb_pbdecodermethod *m = upb_pbdecodermethod_new(&opts, &m); + upb_handlers_unref(handlers, &handlers); + lupb_refcounted_pushnewrapper(L, UPB_UPCAST(m), LUPB_PBDECODERMETHOD, &m); + + // We need to keep a pointer to the MessageDef (in Lua space) so we can + // construct new messages in parse(). + lua_newtable(L); + lua_pushvalue(L, 1); + lua_rawseti(L, -2, MSGDEF_INDEX); + lua_setuservalue(L, -2); + + return 1; // The DecoderMethod wrapper. +} + +// Unlike most of our exposed Lua functions, this does not correspond to an +// actual method on the underlying DecoderMethod. But it's convenient, and +// important to implement in C because we can do stack allocation and +// initialization of our runtime structures like the Decoder and Sink. +static int lupb_pbdecodermethod_parse(lua_State *L) { + size_t len; + const upb_pbdecodermethod *method = lupb_pbdecodermethod_check(L, 1); + const char *pb = lua_tolstring(L, 2, &len); + + const upb_handlers *handlers = upb_pbdecodermethod_desthandlers(method); + + lua_getuservalue(L, 1); + lua_rawgeti(L, -1, MSGDEF_INDEX); + lupb_assert(L, !lua_isnil(L, -1)); + lupb_msg_pushnew(L, -1); // Push new message. + void *msg = lua_touserdata(L, -1); + + // Handlers need this. + lua_getuservalue(L, -1); + + upb_pbdecoder decoder; + upb_status status = UPB_STATUS_INIT; + upb_pbdecoder_init(&decoder, method, &status); + upb_sink sink; + upb_sink_reset(&sink, handlers, msg); + upb_pbdecoder_resetoutput(&decoder, &sink); + upb_bufsrc_putbuf(pb, len, upb_pbdecoder_input(&decoder)); + // TODO: Our need to call uninit isn't longjmp-safe; what if the decode + // triggers a Lua error? uninit is only needed if the decoder + // dynamically-allocated a growing stack -- ditch this feature and live with + // the compile-time limit? Or have a custom allocation function that + // allocates Lua GC-rooted memory? + upb_pbdecoder_uninit(&decoder); + lupb_checkstatus(L, &status); + + lua_pop(L, 1); // Uservalue. + + return 1; +} + +static const struct luaL_Reg lupb_pbdecodermethod_m[] = { + {"parse", lupb_pbdecodermethod_parse}, + {NULL, NULL} +}; + +static const struct luaL_Reg toplevel_m[] = { + {"DecoderMethod", lupb_pbdecodermethod_new}, + {NULL, NULL} +}; + +int luaopen_upb_pb(lua_State *L) { + luaopen_upb(L); + + static char module_key; + if (lupb_openlib(L, &module_key, "upb.pb", toplevel_m)) { + return 1; + } + + lupb_register_type(L, LUPB_PBDECODERMETHOD, lupb_pbdecodermethod_m, NULL, + true); + + return 1; +} diff --git a/upb/bindings/lua/upb/descriptor.c b/upb/bindings/lua/upb/descriptor.c new file mode 100644 index 0000000..9915e11 --- /dev/null +++ b/upb/bindings/lua/upb/descriptor.c @@ -0,0 +1,20 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2009 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * A Lua extension for upb/descriptor. + */ + +#include "upb/bindings/lua/upb.h" + +static const struct luaL_Reg toplevel_m[] = { + {NULL, NULL} +}; + +int luaopen_upb_descriptor(lua_State *L) { + lupb_newlib(L, "upb.descriptor", toplevel_m); + + return 1; // Return package table. +} diff --git a/upb/bindings/stdc++/string.h b/upb/bindings/stdc++/string.h index 668f3e3..5137486 100644 --- a/upb/bindings/stdc++/string.h +++ b/upb/bindings/stdc++/string.h @@ -6,6 +6,8 @@ #ifndef UPB_STDCPP_H_ #define UPB_STDCPP_H_ +#include "upb/sink.h" + namespace upb { template <class T> @@ -141,41 +141,86 @@ static bool upb_validate_field(upb_fielddef *f, upb_status *s) { upb_status_seterrmsg(s, "fielddef must have name and number set"); return false; } + if (!f->type_is_set_) { upb_status_seterrmsg(s, "fielddef type was not initialized"); return false; } + if (upb_fielddef_lazy(f) && upb_fielddef_descriptortype(f) != UPB_DESCRIPTOR_TYPE_MESSAGE) { upb_status_seterrmsg(s, "only length-delimited submessage fields may be lazy"); return false; } + if (upb_fielddef_hassubdef(f)) { if (f->subdef_is_symbolic) { - upb_status_seterrf(s, - "field '%s' has not been resolved", upb_fielddef_name(f)); + upb_status_seterrf(s, "field '%s.%s' has not been resolved", + msgdef_name(f->msg.def), upb_fielddef_name(f)); return false; } const upb_def *subdef = upb_fielddef_subdef(f); if (subdef == NULL) { + upb_status_seterrf(s, "field %s.%s is missing required subdef", + msgdef_name(f->msg.def), upb_fielddef_name(f)); + return false; + } + + if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) { upb_status_seterrf(s, - "field %s.%s is missing required subdef", - msgdef_name(f->msg.def), upb_fielddef_name(f)); + "subdef of field %s.%s is not frozen or being frozen", + msgdef_name(f->msg.def), upb_fielddef_name(f)); return false; - } else if (!upb_def_isfrozen(subdef) && !subdef->came_from_user) { + } + } + + if (upb_fielddef_type(f) == UPB_TYPE_ENUM) { + bool has_default_name = upb_fielddef_enumhasdefaultstr(f); + bool has_default_number = upb_fielddef_enumhasdefaultint32(f); + + // Previously verified by upb_validate_enumdef(). + assert(upb_enumdef_numvals(upb_fielddef_enumsubdef(f)) > 0); + + // We've already validated that we have an associated enumdef and that it + // has at least one member, so at least one of these should be true. + // Because if the user didn't set anything, we'll pick up the enum's + // default, but if the user *did* set something we should at least pick up + // the one they set (int32 or string). + assert(has_default_name || has_default_number); + + if (!has_default_name) { upb_status_seterrf(s, - "subdef of field %s.%s is not frozen or being frozen", - msgdef_name(f->msg.def), upb_fielddef_name(f)); + "enum default for field %s.%s (%d) is not in the enum", + msgdef_name(f->msg.def), upb_fielddef_name(f), + upb_fielddef_defaultint32(f)); return false; - } else if (upb_fielddef_default_is_symbolic(f)) { + } + + if (!has_default_number) { upb_status_seterrf(s, - "enum field %s.%s has not been resolved", - msgdef_name(f->msg.def), upb_fielddef_name(f)); + "enum default for field %s.%s (%s) is not in the enum", + msgdef_name(f->msg.def), upb_fielddef_name(f), + upb_fielddef_defaultstr(f, NULL)); return false; } + + // Lift the effective numeric default into the field's default slot, in case + // we were only getting it "by reference" from the enumdef. + upb_fielddef_setdefaultint32(f, upb_fielddef_defaultint32(f)); } + + return true; +} + +static bool upb_validate_enumdef(const upb_enumdef *e, upb_status *s) { + if (upb_enumdef_numvals(e) == 0) { + upb_status_seterrf(s, "enum %s has no members (must have at least one)", + upb_enumdef_fullname(e)); + return false; + } + return true; } @@ -231,10 +276,12 @@ static bool assign_msg_indices(upb_msgdef *m, upb_status *s) { m->selector_count = selector; free(fields); - return false; + return true; } bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { + upb_status_clear(s); + // First perform validation, in two passes so we can check that we have a // transitive closure without needing to search. for (int i = 0; i < n; i++) { @@ -246,6 +293,10 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { } else if (def->type == UPB_DEF_FIELD) { upb_status_seterrmsg(s, "standalone fielddefs can not be frozen"); goto err; + } else if (def->type == UPB_DEF_ENUM) { + if (!upb_validate_enumdef(upb_dyncast_enumdef(def), s)) { + goto err; + } } else { // Set now to detect transitive closure in the second pass. def->came_from_user = true; @@ -259,7 +310,9 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { upb_enumdef *e = upb_dyncast_enumdef_mutable(defs[i]); if (m) { upb_inttable_compact(&m->itof); - assign_msg_indices(m, s); + if (!assign_msg_indices(m, s)) { + goto err; + } } else if (e) { upb_inttable_compact(&e->iton); } @@ -269,13 +322,16 @@ bool upb_def_freeze(upb_def *const* defs, int n, upb_status *s) { int maxdepth = UPB_MAX_MESSAGE_DEPTH * 2; // Validation all passed; freeze the defs. - return upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth); + bool ret = + upb_refcounted_freeze((upb_refcounted * const *)defs, n, s, maxdepth); + assert(!(s && ret != upb_ok(s))); + return ret; err: for (int i = 0; i < n; i++) { defs[i]->came_from_user = false; } - assert(!upb_ok(s)); + assert(!(s && upb_ok(s))); return false; } @@ -348,6 +404,11 @@ void upb_enumdef_checkref(const upb_enumdef *e, const void *owner) { upb_def_checkref(UPB_UPCAST(e), owner); } +bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status) { + upb_def *d = UPB_UPCAST(e); + return upb_def_freeze(&d, 1, status); +} + const char *upb_enumdef_fullname(const upb_enumdef *e) { return upb_def_fullname(UPB_UPCAST(e)); } @@ -376,14 +437,26 @@ bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, upb_strtable_remove(&e->ntoi, name, NULL); return false; } + if (upb_enumdef_numvals(e) == 1) { + bool ok = upb_enumdef_setdefault(e, num, NULL); + UPB_ASSERT_VAR(ok, ok); + } return true; } -int32_t upb_enumdef_default(const upb_enumdef *e) { return e->defaultval; } +int32_t upb_enumdef_default(const upb_enumdef *e) { + assert(upb_enumdef_iton(e, e->defaultval)); + return e->defaultval; +} -void upb_enumdef_setdefault(upb_enumdef *e, int32_t val) { +bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s) { assert(!upb_enumdef_isfrozen(e)); + if (!upb_enumdef_iton(e, val)) { + upb_status_seterrf(s, "number '%d' is not in the enum.", val); + return false; + } e->defaultval = val; + return true; } int upb_enumdef_numvals(const upb_enumdef *e) { @@ -427,7 +500,7 @@ int32_t upb_enum_iter_number(upb_enum_iter *iter) { static void upb_fielddef_init_default(upb_fielddef *f); static void upb_fielddef_uninit_default(upb_fielddef *f) { - if (f->type_is_set_ && f->default_is_string) + if (f->type_is_set_ && f->default_is_string && f->defaultval.bytes) freestr(f->defaultval.bytes); } @@ -451,6 +524,57 @@ static void freefield(upb_refcounted *r) { free(f); } +static const char *enumdefaultstr(const upb_fielddef *f) { + assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); + const upb_enumdef *e = upb_fielddef_enumsubdef(f); + if (f->default_is_string && f->defaultval.bytes) { + // Default was explicitly set as a string. + str_t *s = f->defaultval.bytes; + return s->str; + } else if (e) { + if (!f->default_is_string) { + // Default was explicitly set as an integer; look it up in enumdef. + const char *name = upb_enumdef_iton(e, f->defaultval.sint); + if (name) { + return name; + } + } else { + // Default is completely unset; pull enumdef default. + if (upb_enumdef_numvals(e) > 0) { + const char *name = upb_enumdef_iton(e, upb_enumdef_default(e)); + assert(name); + return name; + } + } + } + return NULL; +} + +static bool enumdefaultint32(const upb_fielddef *f, int32_t *val) { + assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); + const upb_enumdef *e = upb_fielddef_enumsubdef(f); + if (!f->default_is_string) { + // Default was explicitly set as an integer. + *val = f->defaultval.sint; + return true; + } else if (e) { + if (f->defaultval.bytes) { + // Default was explicitly set as a str; try to lookup corresponding int. + str_t *s = f->defaultval.bytes; + if (upb_enumdef_ntoi(e, s->str, val)) { + return true; + } + } else { + // Default is unset; try to pull in enumdef default. + if (upb_enumdef_numvals(e) > 0) { + *val = upb_enumdef_default(e); + return true; + } + } + } + return false; +} + upb_fielddef *upb_fielddef_new(const void *owner) { static const struct upb_refcounted_vtbl vtbl = {visitfield, freefield}; upb_fielddef *f = malloc(sizeof(*f)); @@ -490,10 +614,11 @@ upb_fielddef *upb_fielddef_dup(const upb_fielddef *f, const void *owner) { upb_fielddef_setlabel(newf, upb_fielddef_label(f)); upb_fielddef_setnumber(newf, upb_fielddef_number(f), NULL); upb_fielddef_setname(newf, upb_fielddef_name(f), NULL); - if (f->default_is_string) { + if (f->default_is_string && f->defaultval.bytes) { str_t *s = f->defaultval.bytes; upb_fielddef_setdefaultstr(newf, s->str, s->len, NULL); } else { + newf->default_is_string = f->default_is_string; newf->defaultval = f->defaultval; } @@ -627,8 +752,15 @@ int64_t upb_fielddef_defaultint64(const upb_fielddef *f) { } int32_t upb_fielddef_defaultint32(const upb_fielddef *f) { - chkdefaulttype(f, UPB_TYPE_INT32); - return f->defaultval.sint; + if (f->type_is_set_ && upb_fielddef_type(f) == UPB_TYPE_ENUM) { + int32_t val; + bool ok = enumdefaultint32(f, &val); + UPB_ASSERT_VAR(ok, ok); + return val; + } else { + chkdefaulttype(f, UPB_TYPE_INT32); + return f->defaultval.sint; + } } uint64_t upb_fielddef_defaultuint64(const upb_fielddef *f) { @@ -661,11 +793,21 @@ const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len) { assert(upb_fielddef_type(f) == UPB_TYPE_STRING || upb_fielddef_type(f) == UPB_TYPE_BYTES || upb_fielddef_type(f) == UPB_TYPE_ENUM); + + if (upb_fielddef_type(f) == UPB_TYPE_ENUM) { + const char *ret = enumdefaultstr(f); + assert(ret); + // Enum defaults can't have embedded NULLs. + if (len) *len = strlen(ret); + return ret; + } + if (f->default_is_string) { str_t *str = f->defaultval.bytes; if (len) *len = str->len; return str->str; } + return NULL; } @@ -675,8 +817,7 @@ static void upb_fielddef_init_default(upb_fielddef *f) { case UPB_TYPE_DOUBLE: f->defaultval.dbl = 0; break; case UPB_TYPE_FLOAT: f->defaultval.flt = 0; break; case UPB_TYPE_INT32: - case UPB_TYPE_INT64: - case UPB_TYPE_ENUM: f->defaultval.sint = 0; break; + case UPB_TYPE_INT64: f->defaultval.sint = 0; break; case UPB_TYPE_UINT64: case UPB_TYPE_UINT32: case UPB_TYPE_BOOL: f->defaultval.uint = 0; break; @@ -686,6 +827,11 @@ static void upb_fielddef_init_default(upb_fielddef *f) { f->default_is_string = true; break; case UPB_TYPE_MESSAGE: break; + case UPB_TYPE_ENUM: + // This is our special sentinel that indicates "not set" for an enum. + f->default_is_string = true; + f->defaultval.bytes = NULL; + break; } } @@ -708,8 +854,13 @@ upb_def *upb_fielddef_subdef_mutable(upb_fielddef *f) { } const char *upb_fielddef_subdefname(const upb_fielddef *f) { - assert(!upb_fielddef_isfrozen(f)); - return f->subdef_is_symbolic ? f->sub.name : NULL; + if (f->subdef_is_symbolic) { + return f->sub.name; + } else if (f->sub.def) { + return upb_def_fullname(f->sub.def); + } else { + return NULL; + } } bool upb_fielddef_setnumber(upb_fielddef *f, uint32_t number, upb_status *s) { @@ -871,8 +1022,8 @@ static bool checksetdefault(upb_fielddef *f, upb_fieldtype_t type) { } if (f->default_is_string) { str_t *s = f->defaultval.bytes; - assert(s); - freestr(s); + assert(s || type == UPB_TYPE_ENUM); + if (s) freestr(s); } f->default_is_string = false; return true; @@ -924,8 +1075,8 @@ bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, if (f->default_is_string) { str_t *s = f->defaultval.bytes; - assert(s); - freestr(s); + assert(s || f->type_ == UPB_TYPE_ENUM); + if (s) freestr(s); } else { assert(f->type_ == UPB_TYPE_ENUM); } @@ -942,33 +1093,15 @@ void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str, upb_fielddef_setdefaultstr(f, str, str ? strlen(str) : 0, s); } -bool upb_fielddef_default_is_symbolic(const upb_fielddef *f) { - return f->type_is_set_ && - f->default_is_string && - f->type_ == UPB_TYPE_ENUM; +bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f) { + assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); + int32_t val; + return enumdefaultint32(f, &val); } -bool upb_fielddef_resolveenumdefault(upb_fielddef *f, upb_status *s) { - if (!upb_fielddef_default_is_symbolic(f)) return true; - - str_t *str = f->defaultval.bytes; - const upb_enumdef *e = upb_downcast_enumdef(upb_fielddef_subdef(f)); - assert(str); // Points to either a real default or the empty string. - assert(e); - if (str->len == 0) { - // The "default default" for an enum is the first defined value. - f->defaultval.sint = e->defaultval; - } else { - int32_t val = 0; - if (!upb_enumdef_ntoi(e, str->str, &val)) { - upb_status_seterrf(s, "enum default not found in enum (%s)", str->str); - return false; - } - f->defaultval.sint = val; - } - f->default_is_string = false; - freestr(str); - return true; +bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f) { + assert(f->type_is_set_ && f->type_ == UPB_TYPE_ENUM); + return enumdefaultstr(f) != NULL; } static bool upb_subdef_typecheck(upb_fielddef *f, const upb_def *subdef, @@ -1139,6 +1272,11 @@ void upb_msgdef_checkref(const upb_msgdef *m, const void *owner) { upb_def_checkref(UPB_UPCAST(m), owner); } +bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status) { + upb_def *d = UPB_UPCAST(m); + return upb_def_freeze(&d, 1, status); +} + const char *upb_msgdef_fullname(const upb_msgdef *m) { return upb_def_fullname(UPB_UPCAST(m)); } @@ -1148,8 +1286,8 @@ bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, return upb_def_setfullname(UPB_UPCAST(m), fullname, s); } -bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n, - const void *ref_donor, upb_status *s) { +bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, + upb_status *s) { // TODO: extensions need to have a separate namespace, because proto2 allows a // top-level extension (ie. one not in any package) to have the same name as a // field from the message. @@ -1162,41 +1300,29 @@ bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *fields, int n, // it is an extension. // Check constraints for all fields before performing any action. - for (int i = 0; i < n; i++) { - upb_fielddef *f = fields[i]; - // TODO(haberman): handle the case where two fields of the input duplicate - // name or number. - if (upb_fielddef_containingtype(f) != NULL) { - upb_status_seterrmsg(s, "fielddef already belongs to a message"); - return false; - } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { - upb_status_seterrmsg(s, "field name or number were not set"); - return false; - } else if(upb_msgdef_itof(m, upb_fielddef_number(f)) || - upb_msgdef_ntof(m, upb_fielddef_name(f))) { - upb_status_seterrmsg(s, "duplicate field name or number"); - return false; - } + if (upb_fielddef_containingtype(f) != NULL) { + upb_status_seterrmsg(s, "fielddef already belongs to a message"); + return false; + } else if (upb_fielddef_name(f) == NULL || upb_fielddef_number(f) == 0) { + upb_status_seterrmsg(s, "field name or number were not set"); + return false; + } else if(upb_msgdef_itof(m, upb_fielddef_number(f)) || + upb_msgdef_ntof(m, upb_fielddef_name(f))) { + upb_status_seterrmsg(s, "duplicate field name or number"); + return false; } // Constraint checks ok, perform the action. - for (int i = 0; i < n; i++) { - upb_fielddef *f = fields[i]; - release_containingtype(f); - f->msg.def = m; - f->msg_is_symbolic = false; - upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); - upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); - upb_ref2(f, m); - upb_ref2(m, f); - if (ref_donor) upb_fielddef_unref(f, ref_donor); - } - return true; -} + release_containingtype(f); + f->msg.def = m; + f->msg_is_symbolic = false; + upb_inttable_insert(&m->itof, upb_fielddef_number(f), upb_value_ptr(f)); + upb_strtable_insert(&m->ntof, upb_fielddef_name(f), upb_value_ptr(f)); + upb_ref2(f, m); + upb_ref2(m, f); + if (ref_donor) upb_fielddef_unref(f, ref_donor); -bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, - upb_status *s) { - return upb_msgdef_addfields(m, &f, 1, ref_donor, s); + return true; } const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) { @@ -1234,3 +1360,7 @@ bool upb_msg_done(const upb_msg_iter *iter) { return upb_inttable_done(iter); } upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter) { return (upb_fielddef*)upb_value_getptr(upb_inttable_iter_value(iter)); } + +void upb_msg_iter_setdone(upb_msg_iter *iter) { + upb_inttable_iter_setdone(iter); +} @@ -264,8 +264,6 @@ class upb::FieldDef /* : public upb::Def */ { // Functionality from upb::Def. const char* full_name() const; - bool set_full_name(const char* fullname, upb::Status* s); - bool set_full_name(const std::string& fullname, upb::Status* s); bool type_is_set() const; // Whether set_[descriptor_]type() has been called. Type type() const; // Requires that type_is_set() == true. @@ -278,15 +276,10 @@ class upb::FieldDef /* : public upb::Def */ { // indicates whether this field should have lazy parsing handlers that yield // the unparsed string for the submessage. // - // When we freeze, we ensure that this can only be true for length-delimited - // message fields. Prior to freezing this can be true or false with no - // restrictions. - // // TODO(haberman): I think we want to move this into a FieldOptions container // when we add support for custom options (the FieldOptions struct will // contain both regular FieldOptions like "lazy" *and* custom options). bool lazy() const; - void set_lazy(bool lazy); // An integer that can be used as an index into an array of fields for // whatever message this field belongs to. Guaranteed to be less than @@ -305,11 +298,6 @@ class upb::FieldDef /* : public upb::Def */ { const MessageDef* containing_type() const; const char* containing_type_name(); - // This may only be called if containing_type() == NULL (ie. the field has not - // been added to a message yet). - bool set_containing_type_name(const char *name, Status* status); - bool set_containing_type_name(const std::string& name, Status* status); - // The field's type according to the enum in descriptor.proto. This is not // the same as UPB_TYPE_*, because it distinguishes between (for example) // INT32 and SINT32, whereas our "type" enum does not. This return of @@ -318,26 +306,6 @@ class upb::FieldDef /* : public upb::Def */ { // appropriately. DescriptorType descriptor_type() const; - // "type" or "descriptor_type" MUST be set explicitly before the fielddef is - // finalized. These setters require that the enum value is valid; if the - // value did not come directly from an enum constant, the caller should - // validate it first with the functions above (CheckFieldType(), etc). - void set_type(Type type); - void set_label(Label label); - void set_descriptor_type(DescriptorType type); - void set_is_extension(bool is_extension); - - // "number" and "name" must be set before the FieldDef is added to a - // MessageDef, and may not be set after that. - // - // "name" is the same as full_name()/set_full_name(), but since fielddefs - // most often use simple, non-qualified names, we provide this accessor - // also. Generally only extensions will want to think of this name as - // fully-qualified. - bool set_number(uint32_t number, upb::Status* s); - bool set_name(const char* name, upb::Status* s); - bool set_name(const std::string& name, upb::Status* s); - // Convenient field type tests. bool IsSubMessage() const; bool IsString() const; @@ -347,12 +315,10 @@ class upb::FieldDef /* : public upb::Def */ { // How integers are encoded. Only meaningful for integer types. // Defaults to UPB_INTFMT_VARIABLE, and is reset when "type" changes. IntegerFormat integer_format() const; - void set_integer_format(IntegerFormat format); // Whether a submessage field is tag-delimited or not (if false, then // length-delimited). May only be set when type() == UPB_TYPE_MESSAGE. bool is_tag_delimited() const; - bool set_tag_delimited(bool tag_delimited, upb::Status* s); // Returns the non-string default value for this fielddef, which may either // be something the client set explicitly or the "default default" (0 for @@ -368,11 +334,87 @@ class upb::FieldDef /* : public upb::Def */ { float default_float() const; double default_double() const; - // Returns the default for UPB_TYPE_STRING, UPB_TYPE_BYTES, and UPB_TYPE_ENUM - // fields that haven't yet been resolved, The resulting string is always - // NULL-terminated. If non-NULL, the length will be stored in *len. + // The resulting string is always NULL-terminated. If non-NULL, the length + // will be stored in *len. const char *default_string(size_t* len) const; + // For frozen UPB_TYPE_ENUM fields, enum defaults can always be read as either + // string or int32, and both of these methods will always return true. + // + // For mutable UPB_TYPE_ENUM fields, the story is a bit more complicated. + // Enum defaults are unusual. They can be specified either as string or int32, + // but to be valid the enum must have that value as a member. And if no + // default is specified, the "default default" comes from the EnumDef. + // + // We allow reading the default as either an int32 or a string, but only if + // we have a meaningful value to report. We have a meaningful value if it was + // set explicitly, or if we could get the "default default" from the EnumDef. + // Also if you explicitly set the name and we find the number in the EnumDef + bool EnumHasStringDefault() const; + bool EnumHasInt32Default() const; + + // Submessage and enum fields must reference a "subdef", which is the + // upb::MessageDef or upb::EnumDef that defines their type. Note that when + // the FieldDef is mutable it may not have a subdef *yet*, but this function + // still returns true to indicate that the field's type requires a subdef. + bool HasSubDef() const; + + // Returns the enum or submessage def for this field, if any. The field's + // type must match (ie. you may only call enum_subdef() for fields where + // type() == UPB_TYPE_ENUM). Returns NULL if the subdef has not been set or + // is currently set symbolically. + const EnumDef* enum_subdef() const; + const MessageDef* message_subdef() const; + + // Returns the generic subdef for this field. Requires that HasSubDef() (ie. + // only works for UPB_TYPE_ENUM and UPB_TYPE_MESSAGE fields). + const Def* subdef() const; + + // Returns the symbolic name of the subdef. If the subdef is currently set + // unresolved (ie. set symbolically) returns the symbolic name. If it has + // been resolved to a specific subdef, returns the name from that subdef. + const char* subdef_name() const; + + ////////////////////////////////////////////////////////////////////////////// + // Setters (non-const methods), only valid for mutable FieldDefs! + ////////////////////////////////////////////////////////////////////////////// + + bool set_full_name(const char* fullname, upb::Status* s); + bool set_full_name(const std::string& fullname, upb::Status* s); + + // This may only be called if containing_type() == NULL (ie. the field has not + // been added to a message yet). + bool set_containing_type_name(const char *name, Status* status); + bool set_containing_type_name(const std::string& name, Status* status); + + // When we freeze, we ensure that this can only be true for length-delimited + // message fields. Prior to freezing this can be true or false with no + // restrictions. + void set_lazy(bool lazy); + + // "type" or "descriptor_type" MUST be set explicitly before the fielddef is + // finalized. These setters require that the enum value is valid; if the + // value did not come directly from an enum constant, the caller should + // validate it first with the functions above (CheckFieldType(), etc). + void set_type(Type type); + void set_label(Label label); + void set_descriptor_type(DescriptorType type); + void set_is_extension(bool is_extension); + + // "number" and "name" must be set before the FieldDef is added to a + // MessageDef, and may not be set after that. + // + // "name" is the same as full_name()/set_full_name(), but since fielddefs + // most often use simple, non-qualified names, we provide this accessor + // also. Generally only extensions will want to think of this name as + // fully-qualified. + bool set_number(uint32_t number, upb::Status* s); + bool set_name(const char* name, upb::Status* s); + bool set_name(const std::string& name, upb::Status* s); + + void set_integer_format(IntegerFormat format); + bool set_tag_delimited(bool tag_delimited, upb::Status* s); + // Sets default value for the field. The call must exactly match the type // of the field. Enum fields may use either setint32 or setstring to set // the default numerically or symbolically, respectively, but symbolic @@ -390,38 +432,6 @@ class upb::FieldDef /* : public upb::Def */ { bool set_default_string(const std::string &str, Status *s); void set_default_cstr(const char *str, Status *s); - // The results of this function are only meaningful for mutable enum fields, - // which can have a default specified either as an integer or as a string. - // If this returns true, the default should be retrieved as default_int32(), - // otherwise it should be retrieved with default_string(). - bool IsDefaultSymbolic() const; - - // If this is an enum field with a symbolic default, resolves the default and - // returns true if resolution was successful or if this field didn't need to - // be resolved (because it is not an enum with a symbolic default). - bool ResolveEnumDefault(Status* s); - - // Submessage and enum fields must reference a "subdef", which is the - // upb_msgdef or upb_enumdef that defines their type. Note that when the - // fielddef is mutable it may not have a subdef *yet*, but this function - // still returns true to indicate that the field's type requires a subdef. - bool HasSubDef() const; - - // Returns the enum or submessage def or symbolic name for this field, if - // any. Requires that upb_hassubdef(f). Returns NULL if the subdef has not - // been set or if you ask for a subdef when the subdef is currently set - // symbolically (or vice-versa). To access the subdef's name for a linked - // fielddef, use upb_def_fullname(upb_fielddef_subdef(f)). - // - // Caller does *not* own a ref on the returned def or string. - // upb_fielddef_subdefename() is non-const because frozen defs will never - // have a symbolic reference (they must be resolved before the msgdef can be - // frozen). - const Def* subdef() const; - const EnumDef* enum_subdef() const; - const MessageDef* message_subdef() const; - const char* subdef_name() const; - // Before a fielddef is frozen, its subdef may be set either directly (with a // upb::Def*) or symbolically. Symbolic refs must be resolved before the // containing msgdef can be frozen (see upb_resolve() above). upb always @@ -530,7 +540,8 @@ bool upb_fielddef_defaultbool(const upb_fielddef *f); float upb_fielddef_defaultfloat(const upb_fielddef *f); double upb_fielddef_defaultdouble(const upb_fielddef *f); const char *upb_fielddef_defaultstr(const upb_fielddef *f, size_t *len); -bool upb_fielddef_default_is_symbolic(const upb_fielddef *f); +bool upb_fielddef_enumhasdefaultint32(const upb_fielddef *f); +bool upb_fielddef_enumhasdefaultstr(const upb_fielddef *f); bool upb_fielddef_hassubdef(const upb_fielddef *f); const upb_def *upb_fielddef_subdef(const upb_fielddef *f); const upb_msgdef *upb_fielddef_msgsubdef(const upb_fielddef *f); @@ -559,7 +570,6 @@ bool upb_fielddef_setdefaultstr(upb_fielddef *f, const void *str, size_t len, upb_status *s); void upb_fielddef_setdefaultcstr(upb_fielddef *f, const char *str, upb_status *s); -bool upb_fielddef_resolveenumdefault(upb_fielddef *f, upb_status *s); bool upb_fielddef_setsubdef(upb_fielddef *f, const upb_def *subdef, upb_status *s); bool upb_fielddef_setmsgsubdef(upb_fielddef *f, const upb_msgdef *subdef, @@ -607,6 +617,7 @@ class upb::MessageDef /* : public upb::Def */ { // Call to freeze this MessageDef. // WARNING: this will fail if this message has any unfrozen submessages! + // Messages with cycles must be frozen as a batch using upb::Def::Freeze(). bool Freeze(Status* s); // The number of fields that belong to the MessageDef. @@ -639,9 +650,8 @@ class upb::MessageDef /* : public upb::Def */ { // Iteration over fields. The order is undefined. class iterator : public std::iterator<std::forward_iterator_tag, FieldDef*> { public: - iterator(); - iterator(const iterator& other); explicit iterator(MessageDef* md); + static iterator end(MessageDef* md); void operator++(); FieldDef* operator*() const; @@ -655,9 +665,8 @@ class upb::MessageDef /* : public upb::Def */ { class const_iterator : public std::iterator<std::forward_iterator_tag, const FieldDef*> { public: - const_iterator(); - const_iterator(const const_iterator& other); explicit const_iterator(const MessageDef* md); + static const_iterator end(const MessageDef* md); void operator++(); const FieldDef* operator*() const; @@ -710,14 +719,13 @@ void upb_msgdef_unref(const upb_msgdef *m, const void *owner); void upb_msgdef_donateref(const upb_msgdef *m, const void *from, const void *to); void upb_msgdef_checkref(const upb_msgdef *m, const void *owner); +bool upb_msgdef_freeze(upb_msgdef *m, upb_status *status); // From upb_def. const char *upb_msgdef_fullname(const upb_msgdef *m); bool upb_msgdef_setfullname(upb_msgdef *m, const char *fullname, upb_status *s); upb_msgdef *upb_msgdef_dup(const upb_msgdef *m, const void *owner); -bool upb_msgdef_addfields(upb_msgdef *m, upb_fielddef *const *f, int n, - const void *ref_donor, upb_status *s); bool upb_msgdef_addfield(upb_msgdef *m, upb_fielddef *f, const void *ref_donor, upb_status *s); const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i); @@ -739,7 +747,7 @@ void upb_msg_begin(upb_msg_iter *iter, const upb_msgdef *m); void upb_msg_next(upb_msg_iter *iter); bool upb_msg_done(const upb_msg_iter *iter); upb_fielddef *upb_msg_iter_field(const upb_msg_iter *iter); -void upb_msg_iter_copy(upb_msg_iter *to, const upb_msg_iter *from); +void upb_msg_iter_setdone(upb_msg_iter *iter); #ifdef __cplusplus } // extern "C #endif @@ -774,8 +782,14 @@ class upb::EnumDef /* : public upb::Def */ { bool Freeze(Status* s); // The value that is used as the default when no field default is specified. + // If not set explicitly, the first value that was added will be used. + // The default value must be a member of the enum. + // Requires that value_count() > 0. int32_t default_value() const; - void set_default_value(int32_t val); + + // Sets the default value. If this value is not valid, returns false and an + // error message in status. + bool set_default_value(int32_t val, Status* status); // Returns the number of values currently defined in the enum. Note that // multiple names can refer to the same number, so this may be greater than @@ -801,6 +815,8 @@ class upb::EnumDef /* : public upb::Def */ { // Iteration over name/value pairs. The order is undefined. // Adding an enum val invalidates any iterators. + // + // TODO: make compatible with range-for, with elements as pairs? class Iterator { public: explicit Iterator(const EnumDef*); @@ -843,6 +859,7 @@ void upb_enumdef_ref(const upb_enumdef *e, const void *owner); void upb_enumdef_donateref(const upb_enumdef *m, const void *from, const void *to); void upb_enumdef_checkref(const upb_enumdef *e, const void *owner); +bool upb_enumdef_freeze(upb_enumdef *e, upb_status *status); // From upb_def. const char *upb_enumdef_fullname(const upb_enumdef *e); @@ -850,7 +867,7 @@ bool upb_enumdef_setfullname(upb_enumdef *e, const char *fullname, upb_status *s); int32_t upb_enumdef_default(const upb_enumdef *e); -void upb_enumdef_setdefault(upb_enumdef *e, int32_t val); +bool upb_enumdef_setdefault(upb_enumdef *e, int32_t val, upb_status *s); int upb_enumdef_numvals(const upb_enumdef *e); bool upb_enumdef_addval(upb_enumdef *e, const char *name, int32_t num, upb_status *status); @@ -1188,12 +1205,6 @@ inline bool FieldDef::set_default_string(const std::string& str, Status* s) { inline void FieldDef::set_default_cstr(const char* str, Status* s) { return upb_fielddef_setdefaultcstr(this, str, s); } -inline bool FieldDef::IsDefaultSymbolic() const { - return upb_fielddef_default_is_symbolic(this); -} -inline bool FieldDef::ResolveEnumDefault(Status* s) { - return upb_fielddef_resolveenumdefault(this, s); -} inline bool FieldDef::HasSubDef() const { return upb_fielddef_hassubdef(this); } inline const Def* FieldDef::subdef() const { return upb_fielddef_subdef(this); } inline const MessageDef *FieldDef::message_subdef() const { @@ -1248,8 +1259,7 @@ inline bool MessageDef::set_full_name(const std::string& fullname, Status* s) { return upb_msgdef_setfullname(this, upb_safecstr(fullname), s); } inline bool MessageDef::Freeze(Status* status) { - upb::Def* e = upb::upcast(this); - return upb_def_freeze(&e, 1, status); + return upb_msgdef_freeze(this, status); } inline int MessageDef::field_count() const { return upb_msgdef_numfields(this); @@ -1276,20 +1286,22 @@ inline MessageDef* MessageDef::Dup(const void *owner) const { return upb_msgdef_dup(this, owner); } inline MessageDef::iterator MessageDef::begin() { return iterator(this); } -inline MessageDef::iterator MessageDef::end() { return iterator(); } +inline MessageDef::iterator MessageDef::end() { return iterator::end(this); } inline MessageDef::const_iterator MessageDef::begin() const { return const_iterator(this); } inline MessageDef::const_iterator MessageDef::end() const { - return const_iterator(); + return const_iterator::end(this); } -inline MessageDef::iterator::iterator() { - upb_inttable_iter_setdone(&iter_); -} inline MessageDef::iterator::iterator(MessageDef* md) { upb_msg_begin(&iter_, md); } +inline MessageDef::iterator MessageDef::iterator::end(MessageDef* md) { + MessageDef::iterator iter(md); + upb_msg_iter_setdone(&iter.iter_); + return iter; +} inline FieldDef* MessageDef::iterator::operator*() const { return upb_msg_iter_field(&iter_); } @@ -1301,12 +1313,15 @@ inline bool MessageDef::iterator::operator!=(const iterator &other) const { return !(*this == other); } -inline MessageDef::const_iterator::const_iterator() { - upb_inttable_iter_setdone(&iter_); -} inline MessageDef::const_iterator::const_iterator(const MessageDef* md) { upb_msg_begin(&iter_, md); } +inline MessageDef::const_iterator MessageDef::const_iterator::end( + const MessageDef *md) { + MessageDef::const_iterator iter(md); + upb_msg_iter_setdone(&iter.iter_); + return iter; +} inline const FieldDef* MessageDef::const_iterator::operator*() const { return upb_msg_iter_field(&iter_); } @@ -1349,14 +1364,13 @@ inline bool EnumDef::set_full_name(const std::string& fullname, Status* s) { return upb_enumdef_setfullname(this, upb_safecstr(fullname), s); } inline bool EnumDef::Freeze(Status* status) { - upb::Def* e = upb::upcast(this); - return upb_def_freeze(&e, 1, status); + return upb_enumdef_freeze(this, status); } inline int32_t EnumDef::default_value() const { return upb_enumdef_default(this); } -inline void EnumDef::set_default_value(int32_t val) { - upb_enumdef_setdefault(this, val); +inline bool EnumDef::set_default_value(int32_t val, Status* status) { + return upb_enumdef_setdefault(this, val, status); } inline int EnumDef::value_count() const { return upb_enumdef_numvals(this); } inline bool EnumDef::AddValue(const char* name, int32_t num, Status* status) { diff --git a/upb/descriptor/descriptor.upb.c b/upb/descriptor/descriptor.upb.c index fa2f447..31503b1 100755 --- a/upb/descriptor/descriptor.upb.c +++ b/upb/descriptor/descriptor.upb.c @@ -3,294 +3,295 @@ // regenerated. #include "upb/def.h" +#include "upb/symtab.h" -const upb_msgdef google_protobuf_msgs[20]; -const upb_fielddef google_protobuf_fields[81]; -const upb_enumdef google_protobuf_enums[4]; -const upb_tabent google_protobuf_strentries[204]; -const upb_tabent google_protobuf_intentries[14]; -const _upb_value google_protobuf_arrays[232]; +static const upb_msgdef msgs[20]; +static const upb_fielddef fields[81]; +static const upb_enumdef enums[4]; +static const upb_tabent strentries[236]; +static const upb_tabent intentries[14]; +static const _upb_value arrays[232]; #ifdef UPB_DEBUG_REFS -static upb_inttable reftables[210]; +static upb_inttable reftables[212]; #endif -const upb_msgdef google_protobuf_msgs[20] = { - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 27, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[0], 8, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[0]),&reftables[0], &reftables[1]), - UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[8], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[16]),&reftables[2], &reftables[3]), - UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[11], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[20]),&reftables[4], &reftables[5]), - UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[0], &google_protobuf_arrays[15], 8, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[24]),&reftables[6], &reftables[7]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[23], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[28]),&reftables[8], &reftables[9]), - UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[2], &google_protobuf_arrays[27], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[32]),&reftables[10], &reftables[11]), - UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 19, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[31], 9, 8), UPB_STRTABLE_INIT(8, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[36]),&reftables[12], &reftables[13]), - UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 14, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[4], &google_protobuf_arrays[40], 32, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[52]),&reftables[14], &reftables[15]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 39, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[72], 12, 11), UPB_STRTABLE_INIT(11, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[68]),&reftables[16], &reftables[17]), - UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[84], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[84]),&reftables[18], &reftables[19]), - UPB_MSGDEF_INIT("google.protobuf.FileOptions", 21, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[6], &google_protobuf_arrays[86], 64, 9), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[88]),&reftables[20], &reftables[21]), - UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[8], &google_protobuf_arrays[150], 16, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[104]),&reftables[22], &reftables[23]), - UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 13, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[166], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &google_protobuf_strentries[108]),&reftables[24], &reftables[25]), - UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[10], &google_protobuf_arrays[171], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[116]),&reftables[26], &reftables[27]), - UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[175], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[120]),&reftables[28], &reftables[29]), - UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &google_protobuf_intentries[12], &google_protobuf_arrays[179], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[124]),&reftables[30], &reftables[31]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[183], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[128]),&reftables[32], &reftables[33]), - UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 14, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[185], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &google_protobuf_strentries[132]),&reftables[34], &reftables[35]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[190], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &google_protobuf_strentries[140]),&reftables[36], &reftables[37]), - UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &google_protobuf_arrays[199], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &google_protobuf_strentries[156]),&reftables[38], &reftables[39]), +static const upb_msgdef msgs[20] = { + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto", 27, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[0], 8, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[0]),&reftables[0], &reftables[1]), + UPB_MSGDEF_INIT("google.protobuf.DescriptorProto.ExtensionRange", 4, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[8], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[16]),&reftables[2], &reftables[3]), + UPB_MSGDEF_INIT("google.protobuf.EnumDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[11], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[20]),&reftables[4], &reftables[5]), + UPB_MSGDEF_INIT("google.protobuf.EnumOptions", 7, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[0], &arrays[15], 8, 1), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[24]),&reftables[6], &reftables[7]), + UPB_MSGDEF_INIT("google.protobuf.EnumValueDescriptorProto", 8, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[23], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[28]),&reftables[8], &reftables[9]), + UPB_MSGDEF_INIT("google.protobuf.EnumValueOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[2], &arrays[27], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[32]),&reftables[10], &reftables[11]), + UPB_MSGDEF_INIT("google.protobuf.FieldDescriptorProto", 19, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[31], 9, 8), UPB_STRTABLE_INIT(8, 15, UPB_CTYPE_PTR, 4, &strentries[36]),&reftables[12], &reftables[13]), + UPB_MSGDEF_INIT("google.protobuf.FieldOptions", 14, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[4], &arrays[40], 32, 6), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[52]),&reftables[14], &reftables[15]), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorProto", 39, 6, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[72], 12, 11), UPB_STRTABLE_INIT(11, 15, UPB_CTYPE_PTR, 4, &strentries[68]),&reftables[16], &reftables[17]), + UPB_MSGDEF_INIT("google.protobuf.FileDescriptorSet", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[84], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[84]),&reftables[18], &reftables[19]), + UPB_MSGDEF_INIT("google.protobuf.FileOptions", 21, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[6], &arrays[86], 64, 9), UPB_STRTABLE_INIT(10, 15, UPB_CTYPE_PTR, 4, &strentries[88]),&reftables[20], &reftables[21]), + UPB_MSGDEF_INIT("google.protobuf.MessageOptions", 8, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[8], &arrays[150], 16, 2), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[104]),&reftables[22], &reftables[23]), + UPB_MSGDEF_INIT("google.protobuf.MethodDescriptorProto", 13, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[166], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &strentries[108]),&reftables[24], &reftables[25]), + UPB_MSGDEF_INIT("google.protobuf.MethodOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[10], &arrays[171], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[116]),&reftables[26], &reftables[27]), + UPB_MSGDEF_INIT("google.protobuf.ServiceDescriptorProto", 11, 2, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[175], 4, 3), UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_PTR, 2, &strentries[120]),&reftables[28], &reftables[29]), + UPB_MSGDEF_INIT("google.protobuf.ServiceOptions", 6, 1, UPB_INTTABLE_INIT(1, 1, UPB_CTYPE_PTR, 1, &intentries[12], &arrays[179], 4, 0), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[124]),&reftables[30], &reftables[31]), + UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo", 6, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[183], 2, 1), UPB_STRTABLE_INIT(1, 3, UPB_CTYPE_PTR, 2, &strentries[128]),&reftables[32], &reftables[33]), + UPB_MSGDEF_INIT("google.protobuf.SourceCodeInfo.Location", 14, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[185], 5, 4), UPB_STRTABLE_INIT(4, 7, UPB_CTYPE_PTR, 3, &strentries[132]),&reftables[34], &reftables[35]), + UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption", 18, 1, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[190], 9, 7), UPB_STRTABLE_INIT(7, 15, UPB_CTYPE_PTR, 4, &strentries[140]),&reftables[36], &reftables[37]), + UPB_MSGDEF_INIT("google.protobuf.UninterpretedOption.NamePart", 6, 0, UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_PTR, 0, NULL, &arrays[199], 3, 2), UPB_STRTABLE_INIT(2, 3, UPB_CTYPE_PTR, 2, &strentries[156]),&reftables[38], &reftables[39]), }; -const upb_fielddef google_protobuf_fields[81] = { - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "aggregate_value", 8, &google_protobuf_msgs[18], NULL, 15, 6, {0},&reftables[40], &reftables[41]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "allow_alias", 2, &google_protobuf_msgs[3], NULL, 6, 1, {0},&reftables[42], &reftables[43]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "cc_generic_services", 16, &google_protobuf_msgs[10], NULL, 17, 6, {0},&reftables[44], &reftables[45]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "ctype", 1, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_enums[2]), 6, 1, {0},&reftables[46], &reftables[47]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "default_value", 7, &google_protobuf_msgs[6], NULL, 16, 7, {0},&reftables[48], &reftables[49]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, "dependency", 3, &google_protobuf_msgs[8], NULL, 30, 8, {0},&reftables[50], &reftables[51]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "deprecated", 3, &google_protobuf_msgs[7], NULL, 8, 3, {0},&reftables[52], &reftables[53]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, "double_value", 6, &google_protobuf_msgs[18], NULL, 11, 4, {0},&reftables[54], &reftables[55]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "end", 2, &google_protobuf_msgs[1], NULL, 3, 1, {0},&reftables[56], &reftables[57]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "enum_type", 5, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[2]), 13, 1, {0},&reftables[58], &reftables[59]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "enum_type", 4, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[2]), 16, 2, {0},&reftables[60], &reftables[61]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "experimental_map_key", 9, &google_protobuf_msgs[7], NULL, 10, 5, {0},&reftables[62], &reftables[63]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "extendee", 2, &google_protobuf_msgs[6], NULL, 7, 2, {0},&reftables[64], &reftables[65]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "extension", 7, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[6]), 19, 3, {0},&reftables[66], &reftables[67]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "extension", 6, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 22, 4, {0},&reftables[68], &reftables[69]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "extension_range", 5, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[1]), 19, 3, {0},&reftables[70], &reftables[71]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "field", 2, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[6]), 10, 0, {0},&reftables[72], &reftables[73]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "file", 1, &google_protobuf_msgs[9], UPB_UPCAST(&google_protobuf_msgs[8]), 5, 0, {0},&reftables[74], &reftables[75]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "go_package", 11, &google_protobuf_msgs[10], NULL, 14, 5, {0},&reftables[76], &reftables[77]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "identifier_value", 3, &google_protobuf_msgs[18], NULL, 6, 1, {0},&reftables[78], &reftables[79]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "input_type", 2, &google_protobuf_msgs[12], NULL, 7, 2, {0},&reftables[80], &reftables[81]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, "is_extension", 2, &google_protobuf_msgs[19], NULL, 5, 1, {0},&reftables[82], &reftables[83]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "java_generate_equals_and_hash", 20, &google_protobuf_msgs[10], NULL, 20, 9, {0},&reftables[84], &reftables[85]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "java_generic_services", 17, &google_protobuf_msgs[10], NULL, 18, 7, {0},&reftables[86], &reftables[87]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "java_multiple_files", 10, &google_protobuf_msgs[10], NULL, 13, 4, {0},&reftables[88], &reftables[89]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "java_outer_classname", 8, &google_protobuf_msgs[10], NULL, 9, 2, {0},&reftables[90], &reftables[91]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "java_package", 1, &google_protobuf_msgs[10], NULL, 6, 1, {0},&reftables[92], &reftables[93]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "label", 4, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[0]), 11, 4, {0},&reftables[94], &reftables[95]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "lazy", 5, &google_protobuf_msgs[7], NULL, 9, 4, {0},&reftables[96], &reftables[97]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "leading_comments", 3, &google_protobuf_msgs[17], NULL, 8, 2, {0},&reftables[98], &reftables[99]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "location", 1, &google_protobuf_msgs[16], UPB_UPCAST(&google_protobuf_msgs[17]), 5, 0, {0},&reftables[100], &reftables[101]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "message_set_wire_format", 1, &google_protobuf_msgs[11], NULL, 6, 1, {0},&reftables[102], &reftables[103]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "message_type", 4, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[0]), 10, 0, {0},&reftables[104], &reftables[105]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "method", 2, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[12]), 6, 0, {0},&reftables[106], &reftables[107]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &google_protobuf_msgs[6], NULL, 4, 1, {0},&reftables[108], &reftables[109]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &google_protobuf_msgs[14], NULL, 8, 2, {0},&reftables[110], &reftables[111]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &google_protobuf_msgs[2], NULL, 8, 2, {0},&reftables[112], &reftables[113]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &google_protobuf_msgs[4], NULL, 4, 1, {0},&reftables[114], &reftables[115]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &google_protobuf_msgs[8], NULL, 22, 6, {0},&reftables[116], &reftables[117]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &google_protobuf_msgs[0], NULL, 24, 6, {0},&reftables[118], &reftables[119]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &google_protobuf_msgs[12], NULL, 4, 1, {0},&reftables[120], &reftables[121]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "name", 2, &google_protobuf_msgs[18], UPB_UPCAST(&google_protobuf_msgs[19]), 5, 0, {0},&reftables[122], &reftables[123]), - UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, "name_part", 1, &google_protobuf_msgs[19], NULL, 2, 0, {0},&reftables[124], &reftables[125]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, "negative_int_value", 5, &google_protobuf_msgs[18], NULL, 10, 3, {0},&reftables[126], &reftables[127]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "nested_type", 3, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[0]), 13, 1, {0},&reftables[128], &reftables[129]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "no_standard_descriptor_accessor", 2, &google_protobuf_msgs[11], NULL, 7, 2, {0},&reftables[130], &reftables[131]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "number", 3, &google_protobuf_msgs[6], NULL, 10, 3, {0},&reftables[132], &reftables[133]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "number", 2, &google_protobuf_msgs[4], NULL, 7, 2, {0},&reftables[134], &reftables[135]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "optimize_for", 9, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_enums[3]), 12, 3, {0},&reftables[136], &reftables[137]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 4, &google_protobuf_msgs[12], UPB_UPCAST(&google_protobuf_msgs[13]), 3, 0, {0},&reftables[138], &reftables[139]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 3, &google_protobuf_msgs[14], UPB_UPCAST(&google_protobuf_msgs[15]), 7, 1, {0},&reftables[140], &reftables[141]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 3, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[3]), 7, 1, {0},&reftables[142], &reftables[143]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 8, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[10]), 20, 4, {0},&reftables[144], &reftables[145]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 8, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_msgs[7]), 3, 0, {0},&reftables[146], &reftables[147]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 3, &google_protobuf_msgs[4], UPB_UPCAST(&google_protobuf_msgs[5]), 3, 0, {0},&reftables[148], &reftables[149]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 7, &google_protobuf_msgs[0], UPB_UPCAST(&google_protobuf_msgs[11]), 23, 5, {0},&reftables[150], &reftables[151]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "output_type", 3, &google_protobuf_msgs[12], NULL, 10, 3, {0},&reftables[152], &reftables[153]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "package", 2, &google_protobuf_msgs[8], NULL, 25, 7, {0},&reftables[154], &reftables[155]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "packed", 2, &google_protobuf_msgs[7], NULL, 7, 2, {0},&reftables[156], &reftables[157]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "path", 1, &google_protobuf_msgs[17], NULL, 4, 0, {0},&reftables[158], &reftables[159]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, "positive_int_value", 4, &google_protobuf_msgs[18], NULL, 9, 2, {0},&reftables[160], &reftables[161]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "public_dependency", 10, &google_protobuf_msgs[8], NULL, 35, 9, {0},&reftables[162], &reftables[163]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "py_generic_services", 18, &google_protobuf_msgs[10], NULL, 19, 8, {0},&reftables[164], &reftables[165]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "service", 6, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[14]), 16, 2, {0},&reftables[166], &reftables[167]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "source_code_info", 9, &google_protobuf_msgs[8], UPB_UPCAST(&google_protobuf_msgs[16]), 21, 5, {0},&reftables[168], &reftables[169]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "span", 2, &google_protobuf_msgs[17], NULL, 7, 1, {0},&reftables[170], &reftables[171]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "start", 1, &google_protobuf_msgs[1], NULL, 2, 0, {0},&reftables[172], &reftables[173]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, "string_value", 7, &google_protobuf_msgs[18], NULL, 12, 5, {0},&reftables[174], &reftables[175]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "trailing_comments", 4, &google_protobuf_msgs[17], NULL, 11, 3, {0},&reftables[176], &reftables[177]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "type", 5, &google_protobuf_msgs[6], UPB_UPCAST(&google_protobuf_enums[1]), 12, 5, {0},&reftables[178], &reftables[179]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "type_name", 6, &google_protobuf_msgs[6], NULL, 13, 6, {0},&reftables[180], &reftables[181]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[15], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[11], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[184], &reftables[185]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[13], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[186], &reftables[187]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[7], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[188], &reftables[189]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[3], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[190], &reftables[191]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[5], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[192], &reftables[193]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &google_protobuf_msgs[10], UPB_UPCAST(&google_protobuf_msgs[18]), 5, 0, {0},&reftables[194], &reftables[195]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "value", 2, &google_protobuf_msgs[2], UPB_UPCAST(&google_protobuf_msgs[4]), 6, 0, {0},&reftables[196], &reftables[197]), - UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "weak", 10, &google_protobuf_msgs[7], NULL, 13, 6, {0},&reftables[198], &reftables[199]), - UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "weak_dependency", 11, &google_protobuf_msgs[8], NULL, 38, 10, {0},&reftables[200], &reftables[201]), +static const upb_fielddef fields[81] = { + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "aggregate_value", 8, &msgs[18], NULL, 15, 6, {0},&reftables[40], &reftables[41]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "allow_alias", 2, &msgs[3], NULL, 6, 1, {0},&reftables[42], &reftables[43]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "cc_generic_services", 16, &msgs[10], NULL, 17, 6, {0},&reftables[44], &reftables[45]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "ctype", 1, &msgs[7], UPB_UPCAST(&enums[2]), 6, 1, {0},&reftables[46], &reftables[47]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "default_value", 7, &msgs[6], NULL, 16, 7, {0},&reftables[48], &reftables[49]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_STRING, 0, false, false, false, "dependency", 3, &msgs[8], NULL, 30, 8, {0},&reftables[50], &reftables[51]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "deprecated", 3, &msgs[7], NULL, 8, 3, {0},&reftables[52], &reftables[53]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_DOUBLE, 0, false, false, false, "double_value", 6, &msgs[18], NULL, 11, 4, {0},&reftables[54], &reftables[55]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "end", 2, &msgs[1], NULL, 3, 1, {0},&reftables[56], &reftables[57]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "enum_type", 4, &msgs[0], UPB_UPCAST(&msgs[2]), 16, 2, {0},&reftables[58], &reftables[59]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "enum_type", 5, &msgs[8], UPB_UPCAST(&msgs[2]), 13, 1, {0},&reftables[60], &reftables[61]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "experimental_map_key", 9, &msgs[7], NULL, 10, 5, {0},&reftables[62], &reftables[63]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "extendee", 2, &msgs[6], NULL, 7, 2, {0},&reftables[64], &reftables[65]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "extension", 7, &msgs[8], UPB_UPCAST(&msgs[6]), 19, 3, {0},&reftables[66], &reftables[67]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "extension", 6, &msgs[0], UPB_UPCAST(&msgs[6]), 22, 4, {0},&reftables[68], &reftables[69]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "extension_range", 5, &msgs[0], UPB_UPCAST(&msgs[1]), 19, 3, {0},&reftables[70], &reftables[71]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "field", 2, &msgs[0], UPB_UPCAST(&msgs[6]), 10, 0, {0},&reftables[72], &reftables[73]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "file", 1, &msgs[9], UPB_UPCAST(&msgs[8]), 5, 0, {0},&reftables[74], &reftables[75]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "go_package", 11, &msgs[10], NULL, 14, 5, {0},&reftables[76], &reftables[77]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "identifier_value", 3, &msgs[18], NULL, 6, 1, {0},&reftables[78], &reftables[79]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "input_type", 2, &msgs[12], NULL, 7, 2, {0},&reftables[80], &reftables[81]), + UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_BOOL, 0, false, false, false, "is_extension", 2, &msgs[19], NULL, 5, 1, {0},&reftables[82], &reftables[83]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "java_generate_equals_and_hash", 20, &msgs[10], NULL, 20, 9, {0},&reftables[84], &reftables[85]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "java_generic_services", 17, &msgs[10], NULL, 18, 7, {0},&reftables[86], &reftables[87]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "java_multiple_files", 10, &msgs[10], NULL, 13, 4, {0},&reftables[88], &reftables[89]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "java_outer_classname", 8, &msgs[10], NULL, 9, 2, {0},&reftables[90], &reftables[91]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "java_package", 1, &msgs[10], NULL, 6, 1, {0},&reftables[92], &reftables[93]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "label", 4, &msgs[6], UPB_UPCAST(&enums[0]), 11, 4, {0},&reftables[94], &reftables[95]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "lazy", 5, &msgs[7], NULL, 9, 4, {0},&reftables[96], &reftables[97]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "leading_comments", 3, &msgs[17], NULL, 8, 2, {0},&reftables[98], &reftables[99]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "location", 1, &msgs[16], UPB_UPCAST(&msgs[17]), 5, 0, {0},&reftables[100], &reftables[101]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "message_set_wire_format", 1, &msgs[11], NULL, 6, 1, {0},&reftables[102], &reftables[103]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "message_type", 4, &msgs[8], UPB_UPCAST(&msgs[0]), 10, 0, {0},&reftables[104], &reftables[105]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "method", 2, &msgs[14], UPB_UPCAST(&msgs[12]), 6, 0, {0},&reftables[106], &reftables[107]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &msgs[8], NULL, 22, 6, {0},&reftables[108], &reftables[109]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &msgs[14], NULL, 8, 2, {0},&reftables[110], &reftables[111]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "name", 2, &msgs[18], UPB_UPCAST(&msgs[19]), 5, 0, {0},&reftables[112], &reftables[113]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &msgs[4], NULL, 4, 1, {0},&reftables[114], &reftables[115]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &msgs[0], NULL, 24, 6, {0},&reftables[116], &reftables[117]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &msgs[12], NULL, 4, 1, {0},&reftables[118], &reftables[119]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &msgs[2], NULL, 8, 2, {0},&reftables[120], &reftables[121]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "name", 1, &msgs[6], NULL, 4, 1, {0},&reftables[122], &reftables[123]), + UPB_FIELDDEF_INIT(UPB_LABEL_REQUIRED, UPB_TYPE_STRING, 0, false, false, false, "name_part", 1, &msgs[19], NULL, 2, 0, {0},&reftables[124], &reftables[125]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT64, UPB_INTFMT_VARIABLE, false, false, false, "negative_int_value", 5, &msgs[18], NULL, 10, 3, {0},&reftables[126], &reftables[127]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "nested_type", 3, &msgs[0], UPB_UPCAST(&msgs[0]), 13, 1, {0},&reftables[128], &reftables[129]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "no_standard_descriptor_accessor", 2, &msgs[11], NULL, 7, 2, {0},&reftables[130], &reftables[131]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "number", 3, &msgs[6], NULL, 10, 3, {0},&reftables[132], &reftables[133]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "number", 2, &msgs[4], NULL, 7, 2, {0},&reftables[134], &reftables[135]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "optimize_for", 9, &msgs[10], UPB_UPCAST(&enums[3]), 12, 3, {0},&reftables[136], &reftables[137]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 7, &msgs[0], UPB_UPCAST(&msgs[11]), 23, 5, {0},&reftables[138], &reftables[139]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 3, &msgs[2], UPB_UPCAST(&msgs[3]), 7, 1, {0},&reftables[140], &reftables[141]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 8, &msgs[6], UPB_UPCAST(&msgs[7]), 3, 0, {0},&reftables[142], &reftables[143]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 3, &msgs[4], UPB_UPCAST(&msgs[5]), 3, 0, {0},&reftables[144], &reftables[145]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 8, &msgs[8], UPB_UPCAST(&msgs[10]), 20, 4, {0},&reftables[146], &reftables[147]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 3, &msgs[14], UPB_UPCAST(&msgs[15]), 7, 1, {0},&reftables[148], &reftables[149]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "options", 4, &msgs[12], UPB_UPCAST(&msgs[13]), 3, 0, {0},&reftables[150], &reftables[151]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "output_type", 3, &msgs[12], NULL, 10, 3, {0},&reftables[152], &reftables[153]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "package", 2, &msgs[8], NULL, 25, 7, {0},&reftables[154], &reftables[155]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "packed", 2, &msgs[7], NULL, 7, 2, {0},&reftables[156], &reftables[157]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "path", 1, &msgs[17], NULL, 4, 0, {0},&reftables[158], &reftables[159]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_UINT64, UPB_INTFMT_VARIABLE, false, false, false, "positive_int_value", 4, &msgs[18], NULL, 9, 2, {0},&reftables[160], &reftables[161]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "public_dependency", 10, &msgs[8], NULL, 35, 9, {0},&reftables[162], &reftables[163]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "py_generic_services", 18, &msgs[10], NULL, 19, 8, {0},&reftables[164], &reftables[165]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "service", 6, &msgs[8], UPB_UPCAST(&msgs[14]), 16, 2, {0},&reftables[166], &reftables[167]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_MESSAGE, 0, false, false, false, "source_code_info", 9, &msgs[8], UPB_UPCAST(&msgs[16]), 21, 5, {0},&reftables[168], &reftables[169]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "span", 2, &msgs[17], NULL, 7, 1, {0},&reftables[170], &reftables[171]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "start", 1, &msgs[1], NULL, 2, 0, {0},&reftables[172], &reftables[173]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BYTES, 0, false, false, false, "string_value", 7, &msgs[18], NULL, 12, 5, {0},&reftables[174], &reftables[175]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "trailing_comments", 4, &msgs[17], NULL, 11, 3, {0},&reftables[176], &reftables[177]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_ENUM, 0, false, false, false, "type", 5, &msgs[6], UPB_UPCAST(&enums[1]), 12, 5, {0},&reftables[178], &reftables[179]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_STRING, 0, false, false, false, "type_name", 6, &msgs[6], NULL, 13, 6, {0},&reftables[180], &reftables[181]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &msgs[5], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[182], &reftables[183]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &msgs[15], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[184], &reftables[185]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &msgs[3], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[186], &reftables[187]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &msgs[13], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[188], &reftables[189]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &msgs[10], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[190], &reftables[191]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &msgs[11], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[192], &reftables[193]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "uninterpreted_option", 999, &msgs[7], UPB_UPCAST(&msgs[18]), 5, 0, {0},&reftables[194], &reftables[195]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_MESSAGE, 0, false, false, false, "value", 2, &msgs[2], UPB_UPCAST(&msgs[4]), 6, 0, {0},&reftables[196], &reftables[197]), + UPB_FIELDDEF_INIT(UPB_LABEL_OPTIONAL, UPB_TYPE_BOOL, 0, false, false, false, "weak", 10, &msgs[7], NULL, 13, 6, {0},&reftables[198], &reftables[199]), + UPB_FIELDDEF_INIT(UPB_LABEL_REPEATED, UPB_TYPE_INT32, UPB_INTFMT_VARIABLE, false, false, false, "weak_dependency", 11, &msgs[8], NULL, 38, 10, {0},&reftables[200], &reftables[201]), }; -const upb_enumdef google_protobuf_enums[4] = { - UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &google_protobuf_strentries[160]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[202], 4, 3), 0, &reftables[202], &reftables[203]), - UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &google_protobuf_strentries[164]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[206], 19, 18), 0, &reftables[204], &reftables[205]), - UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &google_protobuf_strentries[196]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[225], 3, 3), 0, &reftables[206], &reftables[207]), - UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &google_protobuf_strentries[200]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &google_protobuf_arrays[228], 4, 3), 0, &reftables[208], &reftables[209]), +static const upb_enumdef enums[4] = { + UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Label", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[160]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[202], 4, 3), 0, &reftables[202], &reftables[203]), + UPB_ENUMDEF_INIT("google.protobuf.FieldDescriptorProto.Type", UPB_STRTABLE_INIT(18, 31, UPB_CTYPE_INT32, 5, &strentries[164]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[206], 19, 18), 0, &reftables[204], &reftables[205]), + UPB_ENUMDEF_INIT("google.protobuf.FieldOptions.CType", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[196]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[225], 3, 3), 0, &reftables[206], &reftables[207]), + UPB_ENUMDEF_INIT("google.protobuf.FileOptions.OptimizeMode", UPB_STRTABLE_INIT(3, 3, UPB_CTYPE_INT32, 2, &strentries[200]), UPB_INTTABLE_INIT(0, 0, UPB_CTYPE_CSTR, 0, NULL, &arrays[228], 4, 3), 0, &reftables[208], &reftables[209]), }; -const upb_tabent google_protobuf_strentries[204] = { - {UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[14]), NULL}, +static const upb_tabent strentries[236] = { + {UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&fields[14]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[39]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[38]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("field"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[16]), NULL}, - {UPB_TABKEY_STR("extension_range"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[15]), NULL}, + {UPB_TABKEY_STR("field"), UPB_VALUE_INIT_CONSTPTR(&fields[16]), NULL}, + {UPB_TABKEY_STR("extension_range"), UPB_VALUE_INIT_CONSTPTR(&fields[15]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("nested_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[44]), NULL}, + {UPB_TABKEY_STR("nested_type"), UPB_VALUE_INIT_CONSTPTR(&fields[44]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[55]), NULL}, - {UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[10]), &google_protobuf_strentries[14]}, - {UPB_TABKEY_STR("start"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[66]), NULL}, - {UPB_TABKEY_STR("end"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[8]), NULL}, + {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[49]), NULL}, + {UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&fields[9]), &strentries[14]}, + {UPB_TABKEY_STR("start"), UPB_VALUE_INIT_CONSTPTR(&fields[66]), NULL}, + {UPB_TABKEY_STR("end"), UPB_VALUE_INIT_CONSTPTR(&fields[8]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[78]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[51]), NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[36]), &google_protobuf_strentries[22]}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[75]), NULL}, + {UPB_TABKEY_STR("value"), UPB_VALUE_INIT_CONSTPTR(&fields[78]), NULL}, + {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[50]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[40]), &strentries[22]}, + {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[73]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("allow_alias"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[1]), NULL}, + {UPB_TABKEY_STR("allow_alias"), UPB_VALUE_INIT_CONSTPTR(&fields[1]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("number"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[47]), NULL}, + {UPB_TABKEY_STR("number"), UPB_VALUE_INIT_CONSTPTR(&fields[47]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[54]), NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[37]), &google_protobuf_strentries[30]}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[76]), NULL}, + {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[52]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[37]), &strentries[30]}, + {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[71]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("label"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[27]), NULL}, + {UPB_TABKEY_STR("label"), UPB_VALUE_INIT_CONSTPTR(&fields[27]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[34]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[41]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("number"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[46]), &google_protobuf_strentries[49]}, + {UPB_TABKEY_STR("number"), UPB_VALUE_INIT_CONSTPTR(&fields[46]), &strentries[49]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("type_name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[70]), NULL}, - {UPB_TABKEY_STR("extendee"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[12]), NULL}, - {UPB_TABKEY_STR("type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[69]), &google_protobuf_strentries[48]}, - {UPB_TABKEY_STR("default_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[4]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[53]), NULL}, - {UPB_TABKEY_STR("experimental_map_key"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[11]), &google_protobuf_strentries[67]}, + {UPB_TABKEY_STR("type_name"), UPB_VALUE_INIT_CONSTPTR(&fields[70]), NULL}, + {UPB_TABKEY_STR("extendee"), UPB_VALUE_INIT_CONSTPTR(&fields[12]), NULL}, + {UPB_TABKEY_STR("type"), UPB_VALUE_INIT_CONSTPTR(&fields[69]), &strentries[48]}, + {UPB_TABKEY_STR("default_value"), UPB_VALUE_INIT_CONSTPTR(&fields[4]), NULL}, + {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[51]), NULL}, + {UPB_TABKEY_STR("experimental_map_key"), UPB_VALUE_INIT_CONSTPTR(&fields[11]), &strentries[67]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("weak"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[79]), NULL}, + {UPB_TABKEY_STR("weak"), UPB_VALUE_INIT_CONSTPTR(&fields[79]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("packed"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[58]), NULL}, - {UPB_TABKEY_STR("lazy"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[28]), NULL}, + {UPB_TABKEY_STR("packed"), UPB_VALUE_INIT_CONSTPTR(&fields[58]), NULL}, + {UPB_TABKEY_STR("lazy"), UPB_VALUE_INIT_CONSTPTR(&fields[28]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("ctype"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[3]), NULL}, + {UPB_TABKEY_STR("ctype"), UPB_VALUE_INIT_CONSTPTR(&fields[3]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("deprecated"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[6]), NULL}, + {UPB_TABKEY_STR("deprecated"), UPB_VALUE_INIT_CONSTPTR(&fields[6]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[74]), NULL}, - {UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[13]), NULL}, - {UPB_TABKEY_STR("weak_dependency"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[80]), NULL}, + {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[77]), NULL}, + {UPB_TABKEY_STR("extension"), UPB_VALUE_INIT_CONSTPTR(&fields[13]), NULL}, + {UPB_TABKEY_STR("weak_dependency"), UPB_VALUE_INIT_CONSTPTR(&fields[80]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[38]), NULL}, - {UPB_TABKEY_STR("service"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[63]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[34]), NULL}, + {UPB_TABKEY_STR("service"), UPB_VALUE_INIT_CONSTPTR(&fields[63]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("source_code_info"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[64]), NULL}, + {UPB_TABKEY_STR("source_code_info"), UPB_VALUE_INIT_CONSTPTR(&fields[64]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("dependency"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[5]), NULL}, - {UPB_TABKEY_STR("message_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[32]), NULL}, - {UPB_TABKEY_STR("package"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[57]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[52]), &google_protobuf_strentries[82]}, - {UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[9]), NULL}, - {UPB_TABKEY_STR("public_dependency"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[61]), &google_protobuf_strentries[81]}, + {UPB_TABKEY_STR("dependency"), UPB_VALUE_INIT_CONSTPTR(&fields[5]), NULL}, + {UPB_TABKEY_STR("message_type"), UPB_VALUE_INIT_CONSTPTR(&fields[32]), NULL}, + {UPB_TABKEY_STR("package"), UPB_VALUE_INIT_CONSTPTR(&fields[57]), NULL}, + {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[53]), &strentries[82]}, + {UPB_TABKEY_STR("enum_type"), UPB_VALUE_INIT_CONSTPTR(&fields[10]), NULL}, + {UPB_TABKEY_STR("public_dependency"), UPB_VALUE_INIT_CONSTPTR(&fields[61]), &strentries[81]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("file"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[17]), NULL}, + {UPB_TABKEY_STR("file"), UPB_VALUE_INIT_CONSTPTR(&fields[17]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[77]), NULL}, + {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[75]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("cc_generic_services"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[2]), NULL}, + {UPB_TABKEY_STR("cc_generic_services"), UPB_VALUE_INIT_CONSTPTR(&fields[2]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("java_multiple_files"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[24]), NULL}, + {UPB_TABKEY_STR("java_multiple_files"), UPB_VALUE_INIT_CONSTPTR(&fields[24]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("java_generic_services"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[23]), &google_protobuf_strentries[102]}, - {UPB_TABKEY_STR("java_generate_equals_and_hash"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[22]), NULL}, + {UPB_TABKEY_STR("java_generic_services"), UPB_VALUE_INIT_CONSTPTR(&fields[23]), &strentries[102]}, + {UPB_TABKEY_STR("java_generate_equals_and_hash"), UPB_VALUE_INIT_CONSTPTR(&fields[22]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("go_package"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[18]), NULL}, - {UPB_TABKEY_STR("java_package"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[26]), NULL}, - {UPB_TABKEY_STR("optimize_for"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[48]), NULL}, - {UPB_TABKEY_STR("py_generic_services"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[62]), NULL}, - {UPB_TABKEY_STR("java_outer_classname"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[25]), NULL}, - {UPB_TABKEY_STR("message_set_wire_format"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[31]), &google_protobuf_strentries[106]}, + {UPB_TABKEY_STR("go_package"), UPB_VALUE_INIT_CONSTPTR(&fields[18]), NULL}, + {UPB_TABKEY_STR("java_package"), UPB_VALUE_INIT_CONSTPTR(&fields[26]), NULL}, + {UPB_TABKEY_STR("optimize_for"), UPB_VALUE_INIT_CONSTPTR(&fields[48]), NULL}, + {UPB_TABKEY_STR("py_generic_services"), UPB_VALUE_INIT_CONSTPTR(&fields[62]), NULL}, + {UPB_TABKEY_STR("java_outer_classname"), UPB_VALUE_INIT_CONSTPTR(&fields[25]), NULL}, + {UPB_TABKEY_STR("message_set_wire_format"), UPB_VALUE_INIT_CONSTPTR(&fields[31]), &strentries[106]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[72]), NULL}, - {UPB_TABKEY_STR("no_standard_descriptor_accessor"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[45]), NULL}, + {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[76]), NULL}, + {UPB_TABKEY_STR("no_standard_descriptor_accessor"), UPB_VALUE_INIT_CONSTPTR(&fields[45]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[40]), NULL}, - {UPB_TABKEY_STR("input_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[20]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[39]), NULL}, + {UPB_TABKEY_STR("input_type"), UPB_VALUE_INIT_CONSTPTR(&fields[20]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("output_type"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[56]), NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[49]), NULL}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[73]), NULL}, + {UPB_TABKEY_STR("output_type"), UPB_VALUE_INIT_CONSTPTR(&fields[56]), NULL}, + {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[55]), NULL}, + {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[74]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[50]), &google_protobuf_strentries[122]}, - {UPB_TABKEY_STR("method"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[33]), NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[35]), &google_protobuf_strentries[121]}, - {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[71]), NULL}, + {UPB_TABKEY_STR("options"), UPB_VALUE_INIT_CONSTPTR(&fields[54]), &strentries[122]}, + {UPB_TABKEY_STR("method"), UPB_VALUE_INIT_CONSTPTR(&fields[33]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[35]), &strentries[121]}, + {UPB_TABKEY_STR("uninterpreted_option"), UPB_VALUE_INIT_CONSTPTR(&fields[72]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("location"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[30]), NULL}, + {UPB_TABKEY_STR("location"), UPB_VALUE_INIT_CONSTPTR(&fields[30]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("span"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[65]), &google_protobuf_strentries[139]}, + {UPB_TABKEY_STR("span"), UPB_VALUE_INIT_CONSTPTR(&fields[65]), &strentries[139]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("trailing_comments"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[68]), NULL}, - {UPB_TABKEY_STR("leading_comments"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[29]), &google_protobuf_strentries[137]}, - {UPB_TABKEY_STR("path"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[59]), NULL}, - {UPB_TABKEY_STR("double_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[7]), NULL}, + {UPB_TABKEY_STR("trailing_comments"), UPB_VALUE_INIT_CONSTPTR(&fields[68]), NULL}, + {UPB_TABKEY_STR("leading_comments"), UPB_VALUE_INIT_CONSTPTR(&fields[29]), &strentries[137]}, + {UPB_TABKEY_STR("path"), UPB_VALUE_INIT_CONSTPTR(&fields[59]), NULL}, + {UPB_TABKEY_STR("double_value"), UPB_VALUE_INIT_CONSTPTR(&fields[7]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[41]), NULL}, + {UPB_TABKEY_STR("name"), UPB_VALUE_INIT_CONSTPTR(&fields[36]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("negative_int_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[43]), NULL}, - {UPB_TABKEY_STR("aggregate_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[0]), NULL}, + {UPB_TABKEY_STR("negative_int_value"), UPB_VALUE_INIT_CONSTPTR(&fields[43]), NULL}, + {UPB_TABKEY_STR("aggregate_value"), UPB_VALUE_INIT_CONSTPTR(&fields[0]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("positive_int_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[60]), NULL}, - {UPB_TABKEY_STR("identifier_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[19]), NULL}, - {UPB_TABKEY_STR("string_value"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[67]), &google_protobuf_strentries[154]}, + {UPB_TABKEY_STR("positive_int_value"), UPB_VALUE_INIT_CONSTPTR(&fields[60]), NULL}, + {UPB_TABKEY_STR("identifier_value"), UPB_VALUE_INIT_CONSTPTR(&fields[19]), NULL}, + {UPB_TABKEY_STR("string_value"), UPB_VALUE_INIT_CONSTPTR(&fields[67]), &strentries[154]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("is_extension"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[21]), NULL}, - {UPB_TABKEY_STR("name_part"), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[42]), NULL}, - {UPB_TABKEY_STR("LABEL_REQUIRED"), UPB_VALUE_INIT_INT32(2), &google_protobuf_strentries[162]}, + {UPB_TABKEY_STR("is_extension"), UPB_VALUE_INIT_CONSTPTR(&fields[21]), NULL}, + {UPB_TABKEY_STR("name_part"), UPB_VALUE_INIT_CONSTPTR(&fields[42]), NULL}, + {UPB_TABKEY_STR("LABEL_REQUIRED"), UPB_VALUE_INIT_INT32(2), &strentries[162]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_STR("LABEL_REPEATED"), UPB_VALUE_INIT_INT32(3), NULL}, {UPB_TABKEY_STR("LABEL_OPTIONAL"), UPB_VALUE_INIT_INT32(1), NULL}, @@ -300,17 +301,17 @@ const upb_tabent google_protobuf_strentries[204] = { {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_STR("TYPE_STRING"), UPB_VALUE_INIT_INT32(9), NULL}, - {UPB_TABKEY_STR("TYPE_FLOAT"), UPB_VALUE_INIT_INT32(2), &google_protobuf_strentries[193]}, + {UPB_TABKEY_STR("TYPE_FLOAT"), UPB_VALUE_INIT_INT32(2), &strentries[193]}, {UPB_TABKEY_STR("TYPE_DOUBLE"), UPB_VALUE_INIT_INT32(1), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_STR("TYPE_INT32"), UPB_VALUE_INIT_INT32(5), NULL}, {UPB_TABKEY_STR("TYPE_SFIXED32"), UPB_VALUE_INIT_INT32(15), NULL}, {UPB_TABKEY_STR("TYPE_FIXED32"), UPB_VALUE_INIT_INT32(7), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_MESSAGE"), UPB_VALUE_INIT_INT32(11), &google_protobuf_strentries[194]}, + {UPB_TABKEY_STR("TYPE_MESSAGE"), UPB_VALUE_INIT_INT32(11), &strentries[194]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_INT64"), UPB_VALUE_INIT_INT32(3), &google_protobuf_strentries[191]}, + {UPB_TABKEY_STR("TYPE_INT64"), UPB_VALUE_INIT_INT32(3), &strentries[191]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, @@ -318,7 +319,7 @@ const upb_tabent google_protobuf_strentries[204] = { {UPB_TABKEY_STR("TYPE_ENUM"), UPB_VALUE_INIT_INT32(14), NULL}, {UPB_TABKEY_STR("TYPE_UINT32"), UPB_VALUE_INIT_INT32(13), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_STR("TYPE_UINT64"), UPB_VALUE_INIT_INT32(4), &google_protobuf_strentries[190]}, + {UPB_TABKEY_STR("TYPE_UINT64"), UPB_VALUE_INIT_INT32(4), &strentries[190]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_STR("TYPE_SFIXED64"), UPB_VALUE_INIT_INT32(16), NULL}, {UPB_TABKEY_STR("TYPE_BYTES"), UPB_VALUE_INIT_INT32(12), NULL}, @@ -328,83 +329,115 @@ const upb_tabent google_protobuf_strentries[204] = { {UPB_TABKEY_STR("TYPE_SINT32"), UPB_VALUE_INIT_INT32(17), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_STR("CORD"), UPB_VALUE_INIT_INT32(1), NULL}, - {UPB_TABKEY_STR("STRING"), UPB_VALUE_INIT_INT32(0), &google_protobuf_strentries[197]}, + {UPB_TABKEY_STR("STRING"), UPB_VALUE_INIT_INT32(0), &strentries[197]}, {UPB_TABKEY_STR("STRING_PIECE"), UPB_VALUE_INIT_INT32(2), NULL}, {UPB_TABKEY_STR("CODE_SIZE"), UPB_VALUE_INIT_INT32(2), NULL}, - {UPB_TABKEY_STR("SPEED"), UPB_VALUE_INIT_INT32(1), &google_protobuf_strentries[203]}, + {UPB_TABKEY_STR("SPEED"), UPB_VALUE_INIT_INT32(1), &strentries[203]}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, {UPB_TABKEY_STR("LITE_RUNTIME"), UPB_VALUE_INIT_INT32(3), NULL}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_STR("google.protobuf.SourceCodeInfo.Location"), UPB_VALUE_INIT_CONSTPTR(&msgs[17]), NULL}, + {UPB_TABKEY_STR("google.protobuf.UninterpretedOption"), UPB_VALUE_INIT_CONSTPTR(&msgs[18]), NULL}, + {UPB_TABKEY_STR("google.protobuf.FileDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[8]), NULL}, + {UPB_TABKEY_STR("google.protobuf.MethodDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[12]), NULL}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_STR("google.protobuf.EnumValueOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[5]), NULL}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_STR("google.protobuf.DescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[0]), &strentries[228]}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_STR("google.protobuf.SourceCodeInfo"), UPB_VALUE_INIT_CONSTPTR(&msgs[16]), NULL}, + {UPB_TABKEY_STR("google.protobuf.FieldDescriptorProto.Type"), UPB_VALUE_INIT_CONSTPTR(&enums[1]), NULL}, + {UPB_TABKEY_STR("google.protobuf.DescriptorProto.ExtensionRange"), UPB_VALUE_INIT_CONSTPTR(&msgs[1]), NULL}, + {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, + {UPB_TABKEY_STR("google.protobuf.EnumValueDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[4]), NULL}, + {UPB_TABKEY_STR("google.protobuf.FieldOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[7]), NULL}, + {UPB_TABKEY_STR("google.protobuf.FileOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[10]), NULL}, + {UPB_TABKEY_STR("google.protobuf.EnumDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[2]), &strentries[233]}, + {UPB_TABKEY_STR("google.protobuf.FieldDescriptorProto.Label"), UPB_VALUE_INIT_CONSTPTR(&enums[0]), NULL}, + {UPB_TABKEY_STR("google.protobuf.ServiceDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[14]), NULL}, + {UPB_TABKEY_STR("google.protobuf.FieldOptions.CType"), UPB_VALUE_INIT_CONSTPTR(&enums[2]), &strentries[229]}, + {UPB_TABKEY_STR("google.protobuf.FileDescriptorSet"), UPB_VALUE_INIT_CONSTPTR(&msgs[9]), &strentries[235]}, + {UPB_TABKEY_STR("google.protobuf.EnumOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[3]), NULL}, + {UPB_TABKEY_STR("google.protobuf.FieldDescriptorProto"), UPB_VALUE_INIT_CONSTPTR(&msgs[6]), NULL}, + {UPB_TABKEY_STR("google.protobuf.FileOptions.OptimizeMode"), UPB_VALUE_INIT_CONSTPTR(&enums[3]), &strentries[221]}, + {UPB_TABKEY_STR("google.protobuf.ServiceOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[15]), NULL}, + {UPB_TABKEY_STR("google.protobuf.MessageOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[11]), NULL}, + {UPB_TABKEY_STR("google.protobuf.MethodOptions"), UPB_VALUE_INIT_CONSTPTR(&msgs[13]), &strentries[226]}, + {UPB_TABKEY_STR("google.protobuf.UninterpretedOption.NamePart"), UPB_VALUE_INIT_CONSTPTR(&msgs[19]), NULL}, }; -const upb_tabent google_protobuf_intentries[14] = { +static const upb_tabent intentries[14] = { {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[75]), NULL}, + {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[73]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[76]), NULL}, + {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[71]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[74]), NULL}, + {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[77]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[77]), NULL}, + {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[75]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[72]), NULL}, + {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[76]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[73]), NULL}, + {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[74]), NULL}, {UPB_TABKEY_NONE, UPB__VALUE_INIT_NONE, NULL}, - {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[71]), NULL}, + {UPB_TABKEY_NUM(999), UPB_VALUE_INIT_CONSTPTR(&fields[72]), NULL}, }; -const _upb_value google_protobuf_arrays[232] = { +static const _upb_value arrays[232] = { UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[39]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[16]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[44]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[10]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[15]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[14]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[55]), + UPB_VALUE_INIT_CONSTPTR(&fields[38]), + UPB_VALUE_INIT_CONSTPTR(&fields[16]), + UPB_VALUE_INIT_CONSTPTR(&fields[44]), + UPB_VALUE_INIT_CONSTPTR(&fields[9]), + UPB_VALUE_INIT_CONSTPTR(&fields[15]), + UPB_VALUE_INIT_CONSTPTR(&fields[14]), + UPB_VALUE_INIT_CONSTPTR(&fields[49]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[66]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[8]), + UPB_VALUE_INIT_CONSTPTR(&fields[66]), + UPB_VALUE_INIT_CONSTPTR(&fields[8]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[36]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[78]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[51]), + UPB_VALUE_INIT_CONSTPTR(&fields[40]), + UPB_VALUE_INIT_CONSTPTR(&fields[78]), + UPB_VALUE_INIT_CONSTPTR(&fields[50]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[1]), + UPB_VALUE_INIT_CONSTPTR(&fields[1]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[37]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[47]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[54]), + UPB_VALUE_INIT_CONSTPTR(&fields[37]), + UPB_VALUE_INIT_CONSTPTR(&fields[47]), + UPB_VALUE_INIT_CONSTPTR(&fields[52]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[34]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[12]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[46]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[27]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[69]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[70]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[4]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[53]), + UPB_VALUE_INIT_CONSTPTR(&fields[41]), + UPB_VALUE_INIT_CONSTPTR(&fields[12]), + UPB_VALUE_INIT_CONSTPTR(&fields[46]), + UPB_VALUE_INIT_CONSTPTR(&fields[27]), + UPB_VALUE_INIT_CONSTPTR(&fields[69]), + UPB_VALUE_INIT_CONSTPTR(&fields[70]), + UPB_VALUE_INIT_CONSTPTR(&fields[4]), + UPB_VALUE_INIT_CONSTPTR(&fields[51]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[3]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[58]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[6]), + UPB_VALUE_INIT_CONSTPTR(&fields[3]), + UPB_VALUE_INIT_CONSTPTR(&fields[58]), + UPB_VALUE_INIT_CONSTPTR(&fields[6]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[28]), + UPB_VALUE_INIT_CONSTPTR(&fields[28]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[11]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[79]), + UPB_VALUE_INIT_CONSTPTR(&fields[11]), + UPB_VALUE_INIT_CONSTPTR(&fields[79]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, @@ -427,40 +460,40 @@ const _upb_value google_protobuf_arrays[232] = { UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[38]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[57]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[5]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[32]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[9]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[63]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[13]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[52]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[64]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[61]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[80]), + UPB_VALUE_INIT_CONSTPTR(&fields[34]), + UPB_VALUE_INIT_CONSTPTR(&fields[57]), + UPB_VALUE_INIT_CONSTPTR(&fields[5]), + UPB_VALUE_INIT_CONSTPTR(&fields[32]), + UPB_VALUE_INIT_CONSTPTR(&fields[10]), + UPB_VALUE_INIT_CONSTPTR(&fields[63]), + UPB_VALUE_INIT_CONSTPTR(&fields[13]), + UPB_VALUE_INIT_CONSTPTR(&fields[53]), + UPB_VALUE_INIT_CONSTPTR(&fields[64]), + UPB_VALUE_INIT_CONSTPTR(&fields[61]), + UPB_VALUE_INIT_CONSTPTR(&fields[80]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[17]), + UPB_VALUE_INIT_CONSTPTR(&fields[17]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[26]), + UPB_VALUE_INIT_CONSTPTR(&fields[26]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[25]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[48]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[24]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[18]), + UPB_VALUE_INIT_CONSTPTR(&fields[25]), + UPB_VALUE_INIT_CONSTPTR(&fields[48]), + UPB_VALUE_INIT_CONSTPTR(&fields[24]), + UPB_VALUE_INIT_CONSTPTR(&fields[18]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[2]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[23]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[62]), + UPB_VALUE_INIT_CONSTPTR(&fields[2]), + UPB_VALUE_INIT_CONSTPTR(&fields[23]), + UPB_VALUE_INIT_CONSTPTR(&fields[62]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[22]), + UPB_VALUE_INIT_CONSTPTR(&fields[22]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, @@ -505,8 +538,8 @@ const _upb_value google_protobuf_arrays[232] = { UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[31]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[45]), + UPB_VALUE_INIT_CONSTPTR(&fields[31]), + UPB_VALUE_INIT_CONSTPTR(&fields[45]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, @@ -521,41 +554,41 @@ const _upb_value google_protobuf_arrays[232] = { UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[40]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[20]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[56]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[49]), + UPB_VALUE_INIT_CONSTPTR(&fields[39]), + UPB_VALUE_INIT_CONSTPTR(&fields[20]), + UPB_VALUE_INIT_CONSTPTR(&fields[56]), + UPB_VALUE_INIT_CONSTPTR(&fields[55]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[35]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[33]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[50]), + UPB_VALUE_INIT_CONSTPTR(&fields[35]), + UPB_VALUE_INIT_CONSTPTR(&fields[33]), + UPB_VALUE_INIT_CONSTPTR(&fields[54]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[30]), + UPB_VALUE_INIT_CONSTPTR(&fields[30]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[59]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[65]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[29]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[68]), + UPB_VALUE_INIT_CONSTPTR(&fields[59]), + UPB_VALUE_INIT_CONSTPTR(&fields[65]), + UPB_VALUE_INIT_CONSTPTR(&fields[29]), + UPB_VALUE_INIT_CONSTPTR(&fields[68]), UPB_ARRAY_EMPTYENT, UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[41]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[19]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[60]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[43]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[7]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[67]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[0]), + UPB_VALUE_INIT_CONSTPTR(&fields[36]), + UPB_VALUE_INIT_CONSTPTR(&fields[19]), + UPB_VALUE_INIT_CONSTPTR(&fields[60]), + UPB_VALUE_INIT_CONSTPTR(&fields[43]), + UPB_VALUE_INIT_CONSTPTR(&fields[7]), + UPB_VALUE_INIT_CONSTPTR(&fields[67]), + UPB_VALUE_INIT_CONSTPTR(&fields[0]), UPB_ARRAY_EMPTYENT, - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[42]), - UPB_VALUE_INIT_CONSTPTR(&google_protobuf_fields[21]), + UPB_VALUE_INIT_CONSTPTR(&fields[42]), + UPB_VALUE_INIT_CONSTPTR(&fields[21]), UPB_ARRAY_EMPTYENT, UPB_VALUE_INIT_CONSTPTR("LABEL_OPTIONAL"), UPB_VALUE_INIT_CONSTPTR("LABEL_REQUIRED"), @@ -588,8 +621,17 @@ const _upb_value google_protobuf_arrays[232] = { UPB_VALUE_INIT_CONSTPTR("LITE_RUNTIME"), }; +static const upb_symtab symtab = UPB_SYMTAB_INIT(UPB_STRTABLE_INIT(24, 31, UPB_CTYPE_PTR, 5, &strentries[204]), &reftables[210], &reftables[211]); + +const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner) { + upb_symtab_ref(&symtab, owner); + return &symtab; +} + #ifdef UPB_DEBUG_REFS -static upb_inttable reftables[210] = { +static upb_inttable reftables[212] = { + UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), + UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), UPB_EMPTY_INTTABLE_INIT(UPB_CTYPE_PTR), diff --git a/upb/descriptor/descriptor.upb.h b/upb/descriptor/descriptor.upb.h index 72256e7..14b7308 100755 --- a/upb/descriptor/descriptor.upb.h +++ b/upb/descriptor/descriptor.upb.h @@ -1,11 +1,18 @@ +// This file contains accessors for a set of compiled-in defs. +// Note that unlike Google's protobuf, it does *not* define +// generated classes or any other kind of data structure for +// actually storing protobufs. It only contains *defs* which +// let you reflect over a protobuf *schema*. +// // This file was generated by upbc (the upb compiler). // Do not edit -- your changes will be discarded when the file is // regenerated. -#ifndef GOOGLE_PROTOBUF_UPB_H_ -#define GOOGLE_PROTOBUF_UPB_H_ +#ifndef GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ +#define GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ #include "upb/def.h" +#include "upb/symtab.h" #ifdef __cplusplus extern "C" { @@ -52,338 +59,492 @@ typedef enum { GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZEMODE_LITE_RUNTIME = 3, } google_protobuf_FileOptions_OptimizeMode; -// Do not refer to these forward declarations; use the constants -// below. -extern const upb_msgdef google_protobuf_msgs[20]; -extern const upb_fielddef google_protobuf_fields[81]; -extern const upb_enumdef google_protobuf_enums[4]; - -// Constants for references to defs. -// We hide these behind macros to decouple users from the -// details of how we have statically defined them (ie. whether -// each def has its own symbol or lives in an array of defs). -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO &google_protobuf_msgs[0] -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE &google_protobuf_msgs[1] -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO &google_protobuf_msgs[2] -#define GOOGLE_PROTOBUF_ENUMOPTIONS &google_protobuf_msgs[3] -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO &google_protobuf_msgs[4] -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS &google_protobuf_msgs[5] -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO &google_protobuf_msgs[6] -#define GOOGLE_PROTOBUF_FIELDOPTIONS &google_protobuf_msgs[7] -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO &google_protobuf_msgs[8] -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET &google_protobuf_msgs[9] -#define GOOGLE_PROTOBUF_FILEOPTIONS &google_protobuf_msgs[10] -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS &google_protobuf_msgs[11] -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO &google_protobuf_msgs[12] -#define GOOGLE_PROTOBUF_METHODOPTIONS &google_protobuf_msgs[13] -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO &google_protobuf_msgs[14] -#define GOOGLE_PROTOBUF_SERVICEOPTIONS &google_protobuf_msgs[15] -#define GOOGLE_PROTOBUF_SOURCECODEINFO &google_protobuf_msgs[16] -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION &google_protobuf_msgs[17] -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION &google_protobuf_msgs[18] -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART &google_protobuf_msgs[19] - -// Selector definitions. -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 15 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSTR 18 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 16 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 14 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSTR 17 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 4 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_ENUM_TYPE_STRING 19 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_END_INT32 3 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSIONRANGE_START_INT32 2 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSEQ 21 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSTR 24 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_ENDSUBMSG 22 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSEQ 18 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSTR 21 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_ENDSUBMSG 19 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSEQ 17 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSTR 20 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STARTSUBMSG 5 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_RANGE_STRING 22 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSEQ 20 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSTR 23 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STARTSUBMSG 6 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_EXTENSION_STRING 25 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSEQ 9 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSTR 12 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_ENDSUBMSG 10 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSEQ 8 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSTR 11 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_FIELD_STRING 13 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_ENDSTR 26 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STARTSTR 25 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NAME_STRING 24 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSEQ 12 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSTR 15 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_ENDSUBMSG 13 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSEQ 11 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSTR 14 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STARTSUBMSG 3 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_NESTED_TYPE_STRING 16 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSTR 25 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_ENDSUBMSG 23 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSTR 24 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STARTSUBMSG 7 -#define GOOGLE_PROTOBUF_DESCRIPTORPROTO_OPTIONS_STRING 26 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_ENDSTR 10 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STARTSTR 9 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_NAME_STRING 8 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSTR 9 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSTR 8 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_OPTIONS_STRING 10 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSEQ 5 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSTR 8 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_ENDSUBMSG 6 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSEQ 4 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSTR 7 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO_VALUE_STRING 9 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_ALLOW_ALIAS_BOOL 6 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSTR 7 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSTR 6 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_ENUMOPTIONS_UNINTERPRETED_OPTION_STRING 8 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_ENDSTR 6 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STARTSTR 5 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NAME_STRING 4 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_NUMBER_INT32 7 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSTR 5 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSTR 4 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO_OPTIONS_STRING 6 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSTR 7 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSTR 6 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_ENUMVALUEOPTIONS_UNINTERPRETED_OPTION_STRING 8 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_ENDSTR 18 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STARTSTR 17 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_DEFAULT_VALUE_STRING 16 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_ENDSTR 9 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STARTSTR 8 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_EXTENDEE_STRING 7 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_LABEL_INT32 11 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_ENDSTR 6 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STARTSTR 5 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NAME_STRING 4 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_NUMBER_INT32 10 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSTR 5 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSTR 4 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_OPTIONS_STRING 6 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_INT32 12 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_ENDSTR 15 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STARTSTR 14 -#define GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO_TYPE_NAME_STRING 13 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_CTYPE_INT32 6 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_DEPRECATED_BOOL 8 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_ENDSTR 12 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STARTSTR 11 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_EXPERIMENTAL_MAP_KEY_STRING 10 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_LAZY_BOOL 9 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_PACKED_BOOL 7 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSTR 7 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSTR 6 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_UNINTERPRETED_OPTION_STRING 8 -#define GOOGLE_PROTOBUF_FIELDOPTIONS_WEAK_BOOL 13 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSEQ 29 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_ENDSTR 32 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSEQ 28 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STARTSTR 31 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_DEPENDENCY_STRING 30 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSEQ 12 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSTR 15 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_ENDSUBMSG 13 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSEQ 11 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSTR 14 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STARTSUBMSG 3 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_ENUM_TYPE_STRING 16 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSEQ 18 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSTR 21 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_ENDSUBMSG 19 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSEQ 17 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSTR 20 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STARTSUBMSG 5 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_EXTENSION_STRING 22 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSEQ 9 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSTR 12 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_ENDSUBMSG 10 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSEQ 8 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSTR 11 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_MESSAGE_TYPE_STRING 13 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_ENDSTR 24 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STARTSTR 23 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_NAME_STRING 22 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSTR 22 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 20 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSTR 21 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 6 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_OPTIONS_STRING 23 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_ENDSTR 27 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STARTSTR 26 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PACKAGE_STRING 25 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_ENDSEQ 34 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_INT32 35 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_PUBLIC_DEPENDENCY_STARTSEQ 33 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSEQ 15 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSTR 18 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_ENDSUBMSG 16 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSEQ 14 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSTR 17 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STARTSUBMSG 4 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SERVICE_STRING 19 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSTR 23 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_ENDSUBMSG 21 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSTR 22 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STARTSUBMSG 7 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_SOURCE_CODE_INFO_STRING 24 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_ENDSEQ 37 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_INT32 38 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO_WEAK_DEPENDENCY_STARTSEQ 36 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSEQ 4 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSTR 7 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSEQ 3 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSTR 6 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_FILEDESCRIPTORSET_FILE_STRING 8 -#define GOOGLE_PROTOBUF_FILEOPTIONS_CC_GENERIC_SERVICES_BOOL 17 -#define GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_ENDSTR 16 -#define GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STARTSTR 15 -#define GOOGLE_PROTOBUF_FILEOPTIONS_GO_PACKAGE_STRING 14 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERATE_EQUALS_AND_HASH_BOOL 20 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_GENERIC_SERVICES_BOOL 18 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_MULTIPLE_FILES_BOOL 13 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_ENDSTR 11 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STARTSTR 10 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_OUTER_CLASSNAME_STRING 9 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_ENDSTR 8 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STARTSTR 7 -#define GOOGLE_PROTOBUF_FILEOPTIONS_JAVA_PACKAGE_STRING 6 -#define GOOGLE_PROTOBUF_FILEOPTIONS_OPTIMIZE_FOR_INT32 12 -#define GOOGLE_PROTOBUF_FILEOPTIONS_PY_GENERIC_SERVICES_BOOL 19 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSTR 7 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSTR 6 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_FILEOPTIONS_UNINTERPRETED_OPTION_STRING 8 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_MESSAGE_SET_WIRE_FORMAT_BOOL 6 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_NO_STANDARD_DESCRIPTOR_ACCESSOR_BOOL 7 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSTR 7 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSTR 6 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_MESSAGEOPTIONS_UNINTERPRETED_OPTION_STRING 8 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_ENDSTR 9 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STARTSTR 8 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_INPUT_TYPE_STRING 7 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_ENDSTR 6 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STARTSTR 5 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_NAME_STRING 4 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSTR 5 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 3 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSTR 4 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OPTIONS_STRING 6 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_ENDSTR 12 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STARTSTR 11 -#define GOOGLE_PROTOBUF_METHODDESCRIPTORPROTO_OUTPUT_TYPE_STRING 10 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSTR 7 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSTR 6 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_METHODOPTIONS_UNINTERPRETED_OPTION_STRING 8 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSEQ 5 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSTR 8 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_ENDSUBMSG 6 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSEQ 4 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSTR 7 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_METHOD_STRING 9 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_ENDSTR 10 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STARTSTR 9 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_NAME_STRING 8 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSTR 9 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_ENDSUBMSG 7 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSTR 8 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STARTSUBMSG 3 -#define GOOGLE_PROTOBUF_SERVICEDESCRIPTORPROTO_OPTIONS_STRING 10 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSTR 7 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSTR 6 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_SERVICEOPTIONS_UNINTERPRETED_OPTION_STRING 8 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSEQ 4 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSTR 7 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_ENDSTR 10 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STARTSTR 9 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_LEADING_COMMENTS_STRING 8 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_ENDSEQ 3 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_INT32 4 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_PATH_STARTSEQ 2 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_ENDSEQ 6 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_INT32 7 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_SPAN_STARTSEQ 5 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSEQ 3 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSTR 6 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_STRING 8 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_ENDSTR 13 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STARTSTR 12 -#define GOOGLE_PROTOBUF_SOURCECODEINFO_LOCATION_TRAILING_COMMENTS_STRING 11 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_ENDSTR 17 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STARTSTR 16 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_AGGREGATE_VALUE_STRING 15 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_DOUBLE_VALUE_DOUBLE 11 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_ENDSTR 8 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STARTSTR 7 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_IDENTIFIER_VALUE_STRING 6 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_IS_EXTENSION_BOOL 5 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_ENDSTR 4 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STARTSTR 3 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAMEPART_NAME_PART_STRING 2 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSEQ 4 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSTR 7 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_ENDSUBMSG 5 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSEQ 3 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSTR 6 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STARTSUBMSG 2 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NAME_STRING 8 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_NEGATIVE_INT_VALUE_INT64 10 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_POSITIVE_INT_VALUE_UINT64 9 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_ENDSTR 14 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STARTSTR 13 -#define GOOGLE_PROTOBUF_UNINTERPRETEDOPTION_STRING_VALUE_STRING 12 +const upb_symtab *upbdefs_google_protobuf_descriptor(const void *owner); + +// MessageDefs +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.DescriptorProto.ExtensionRange"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_EnumValueOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.EnumValueOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FieldOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FieldOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileDescriptorSet(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileDescriptorSet"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_FileOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.FileOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MessageOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MessageOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_MethodOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.MethodOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceDescriptorProto(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceDescriptorProto"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_ServiceOptions(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.ServiceOptions"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_SourceCodeInfo_Location(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.SourceCodeInfo.Location"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption"); + assert(m); + return m; +} +UPB_INLINE const upb_msgdef *upbdefs_google_protobuf_UninterpretedOption_NamePart(const upb_symtab *s) { + const upb_msgdef *m = upb_symtab_lookupmsg(s, "google.protobuf.UninterpretedOption.NamePart"); + assert(m); + return m; +} + + +// EnumDefs +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Label(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Label"); + assert(e); + return e; +} +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldDescriptorProto_Type(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldDescriptorProto.Type"); + assert(e); + return e; +} +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FieldOptions_CType(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FieldOptions.CType"); + assert(e); + return e; +} +UPB_INLINE const upb_enumdef *upbdefs_google_protobuf_FileOptions_OptimizeMode(const upb_symtab *s) { + const upb_enumdef *e = upb_symtab_lookupenum(s, "google.protobuf.FileOptions.OptimizeMode"); + assert(e); + return e; +} + +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto_ExtensionRange(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_extension_range(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_field(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_nested_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_DescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_DescriptorProto(s), 7); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumDescriptorProto_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_allow_alias(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_EnumValueOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_default_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 7); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_extendee(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_label(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_number(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldDescriptorProto_type_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldDescriptorProto(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_ctype(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_deprecated(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_experimental_map_key(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 9); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_lazy(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_packed(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FieldOptions_weak(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FieldOptions(s), 10); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_enum_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 7); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_message_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_public_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 10); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_service(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_source_code_info(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 9); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorProto_weak_dependency(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorProto(s), 11); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileDescriptorSet_file(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileDescriptorSet(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_cc_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 16); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_go_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 11); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 20); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 17); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_multiple_files(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 10); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_outer_classname(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_java_package(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_optimize_for(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 9); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_py_generic_services(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 18); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_FileOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_FileOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_message_set_wire_format(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MessageOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MessageOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_input_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodDescriptorProto_output_type(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_MethodOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_MethodOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_method(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceDescriptorProto_options(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceDescriptorProto(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_ServiceOptions_uninterpreted_option(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_ServiceOptions(s), 999); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_path(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_span(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo_Location(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_SourceCodeInfo_location(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_SourceCodeInfo(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption_NamePart(s), 1); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_aggregate_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 8); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_double_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 6); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_identifier_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 3); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_name(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 2); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_negative_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 5); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_positive_int_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 4); } +UPB_INLINE const upb_fielddef *upbdefs_google_protobuf_UninterpretedOption_string_value(const upb_symtab *s) { return upb_msgdef_itof(upbdefs_google_protobuf_UninterpretedOption(s), 7); } #ifdef __cplusplus }; // extern "C" #endif -#endif // GOOGLE_PROTOBUF_UPB_H_ +#ifdef __cplusplus + +namespace upbdefs { +namespace google { +namespace protobuf { +namespace descriptor { +inline upb::reffed_ptr<const upb::SymbolTable> SymbolTable() { + const upb::SymbolTable* s = upbdefs_google_protobuf_descriptor(&s); + return upb::reffed_ptr<const upb::SymbolTable>(s, &s); +} +} // namespace descriptor +} // namespace protobuf +} // namespace google + +#define RETURN_REFFED(type, func) \ + const type* obj = func(upbdefs::google::protobuf::descriptor::SymbolTable().get()); \ + return upb::reffed_ptr<const type>(obj); + +namespace google { +namespace protobuf { +namespace DescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_enum_type) } +inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension) } +inline upb::reffed_ptr<const upb::FieldDef> extension_range() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_extension_range) } +inline upb::reffed_ptr<const upb::FieldDef> field() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_field) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> nested_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_nested_type) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_options) } +} // namespace DescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace DescriptorProto { +namespace ExtensionRange { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange) } +inline upb::reffed_ptr<const upb::FieldDef> end() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_end) } +inline upb::reffed_ptr<const upb::FieldDef> start() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_DescriptorProto_ExtensionRange_start) } +} // namespace ExtensionRange +} // namespace DescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace EnumDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumDescriptorProto_value) } +} // namespace EnumDescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace EnumOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumOptions) } +inline upb::reffed_ptr<const upb::FieldDef> allow_alias() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_allow_alias) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumOptions_uninterpreted_option) } +} // namespace EnumOptions +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace EnumValueDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_number) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueDescriptorProto_options) } +} // namespace EnumValueDescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace EnumValueOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_EnumValueOptions) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_EnumValueOptions_uninterpreted_option) } +} // namespace EnumValueOptions +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace FieldDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> default_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_default_value) } +inline upb::reffed_ptr<const upb::FieldDef> extendee() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_extendee) } +inline upb::reffed_ptr<const upb::FieldDef> label() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_label) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> number() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_number) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type) } +inline upb::reffed_ptr<const upb::FieldDef> type_name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldDescriptorProto_type_name) } +inline upb::reffed_ptr<const upb::EnumDef> Label() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Label) } +inline upb::reffed_ptr<const upb::EnumDef> Type() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldDescriptorProto_Type) } +} // namespace FieldDescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace FieldOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FieldOptions) } +inline upb::reffed_ptr<const upb::FieldDef> ctype() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_ctype) } +inline upb::reffed_ptr<const upb::FieldDef> deprecated() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_deprecated) } +inline upb::reffed_ptr<const upb::FieldDef> experimental_map_key() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_experimental_map_key) } +inline upb::reffed_ptr<const upb::FieldDef> lazy() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_lazy) } +inline upb::reffed_ptr<const upb::FieldDef> packed() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_packed) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_uninterpreted_option) } +inline upb::reffed_ptr<const upb::FieldDef> weak() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FieldOptions_weak) } +inline upb::reffed_ptr<const upb::EnumDef> CType() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FieldOptions_CType) } +} // namespace FieldOptions +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace FileDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_dependency) } +inline upb::reffed_ptr<const upb::FieldDef> enum_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_enum_type) } +inline upb::reffed_ptr<const upb::FieldDef> extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_extension) } +inline upb::reffed_ptr<const upb::FieldDef> message_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_message_type) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_package) } +inline upb::reffed_ptr<const upb::FieldDef> public_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_public_dependency) } +inline upb::reffed_ptr<const upb::FieldDef> service() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_service) } +inline upb::reffed_ptr<const upb::FieldDef> source_code_info() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_source_code_info) } +inline upb::reffed_ptr<const upb::FieldDef> weak_dependency() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorProto_weak_dependency) } +} // namespace FileDescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace FileDescriptorSet { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileDescriptorSet) } +inline upb::reffed_ptr<const upb::FieldDef> file() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileDescriptorSet_file) } +} // namespace FileDescriptorSet +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace FileOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_FileOptions) } +inline upb::reffed_ptr<const upb::FieldDef> cc_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_cc_generic_services) } +inline upb::reffed_ptr<const upb::FieldDef> go_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_go_package) } +inline upb::reffed_ptr<const upb::FieldDef> java_generate_equals_and_hash() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generate_equals_and_hash) } +inline upb::reffed_ptr<const upb::FieldDef> java_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_generic_services) } +inline upb::reffed_ptr<const upb::FieldDef> java_multiple_files() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_multiple_files) } +inline upb::reffed_ptr<const upb::FieldDef> java_outer_classname() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_outer_classname) } +inline upb::reffed_ptr<const upb::FieldDef> java_package() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_java_package) } +inline upb::reffed_ptr<const upb::FieldDef> optimize_for() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_optimize_for) } +inline upb::reffed_ptr<const upb::FieldDef> py_generic_services() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_py_generic_services) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_FileOptions_uninterpreted_option) } +inline upb::reffed_ptr<const upb::EnumDef> OptimizeMode() { RETURN_REFFED(upb::EnumDef, upbdefs_google_protobuf_FileOptions_OptimizeMode) } +} // namespace FileOptions +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace MessageOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MessageOptions) } +inline upb::reffed_ptr<const upb::FieldDef> message_set_wire_format() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_message_set_wire_format) } +inline upb::reffed_ptr<const upb::FieldDef> no_standard_descriptor_accessor() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_no_standard_descriptor_accessor) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MessageOptions_uninterpreted_option) } +} // namespace MessageOptions +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace MethodDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> input_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_input_type) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_options) } +inline upb::reffed_ptr<const upb::FieldDef> output_type() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodDescriptorProto_output_type) } +} // namespace MethodDescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace MethodOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_MethodOptions) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_MethodOptions_uninterpreted_option) } +} // namespace MethodOptions +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace ServiceDescriptorProto { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceDescriptorProto) } +inline upb::reffed_ptr<const upb::FieldDef> method() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_method) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_name) } +inline upb::reffed_ptr<const upb::FieldDef> options() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceDescriptorProto_options) } +} // namespace ServiceDescriptorProto +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace ServiceOptions { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_ServiceOptions) } +inline upb::reffed_ptr<const upb::FieldDef> uninterpreted_option() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_ServiceOptions_uninterpreted_option) } +} // namespace ServiceOptions +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace SourceCodeInfo { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo) } +inline upb::reffed_ptr<const upb::FieldDef> location() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_location) } +} // namespace SourceCodeInfo +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace SourceCodeInfo { +namespace Location { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_SourceCodeInfo_Location) } +inline upb::reffed_ptr<const upb::FieldDef> leading_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_leading_comments) } +inline upb::reffed_ptr<const upb::FieldDef> path() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_path) } +inline upb::reffed_ptr<const upb::FieldDef> span() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_span) } +inline upb::reffed_ptr<const upb::FieldDef> trailing_comments() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_SourceCodeInfo_Location_trailing_comments) } +} // namespace Location +} // namespace SourceCodeInfo +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace UninterpretedOption { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption) } +inline upb::reffed_ptr<const upb::FieldDef> aggregate_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_aggregate_value) } +inline upb::reffed_ptr<const upb::FieldDef> double_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_double_value) } +inline upb::reffed_ptr<const upb::FieldDef> identifier_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_identifier_value) } +inline upb::reffed_ptr<const upb::FieldDef> name() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_name) } +inline upb::reffed_ptr<const upb::FieldDef> negative_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_negative_int_value) } +inline upb::reffed_ptr<const upb::FieldDef> positive_int_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_positive_int_value) } +inline upb::reffed_ptr<const upb::FieldDef> string_value() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_string_value) } +} // namespace UninterpretedOption +} // namespace protobuf +} // namespace google + +namespace google { +namespace protobuf { +namespace UninterpretedOption { +namespace NamePart { +inline upb::reffed_ptr<const upb::MessageDef> MessageDef() { RETURN_REFFED(upb::MessageDef, upbdefs_google_protobuf_UninterpretedOption_NamePart) } +inline upb::reffed_ptr<const upb::FieldDef> is_extension() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_is_extension) } +inline upb::reffed_ptr<const upb::FieldDef> name_part() { RETURN_REFFED(upb::FieldDef, upbdefs_google_protobuf_UninterpretedOption_NamePart_name_part) } +} // namespace NamePart +} // namespace UninterpretedOption +} // namespace protobuf +} // namespace google + +} // namespace upbdefs + + +#undef RETURN_REFFED +#endif // __cplusplus + +#endif // GOOGLE_PROTOBUF_DESCRIPTOR_UPB_H_ diff --git a/upb/descriptor/reader.c b/upb/descriptor/reader.c index 9baca1d..c9425a3 100644 --- a/upb/descriptor/reader.c +++ b/upb/descriptor/reader.c @@ -223,11 +223,6 @@ static bool enumval_endmsg(void *closure, const void *hd, upb_status *status) { return false; } 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, status); free(r->name); r->name = NULL; @@ -507,52 +502,65 @@ static bool pushextension(void *closure, const void *hd) { return true; } -static const upb_fielddef *f(const upb_handlers *h, const char *name) { - const upb_fielddef *ret = upb_msgdef_ntof(upb_handlers_msgdef(h), name); - assert(ret); - return ret; -} +#define D(name) upbdefs_google_protobuf_ ## name(s) -static void reghandlers(void *closure, upb_handlers *h) { - UPB_UNUSED(closure); +static void reghandlers(const void *closure, upb_handlers *h) { + const upb_symtab *s = closure; const upb_msgdef *m = upb_handlers_msgdef(h); - if (m == GOOGLE_PROTOBUF_DESCRIPTORPROTO) { + if (m == D(DescriptorProto)) { upb_handlers_setstartmsg(h, &msg_startmsg, NULL); upb_handlers_setendmsg(h, &msg_endmsg, NULL); - upb_handlers_setstring(h, f(h, "name"), &msg_onname, NULL); - upb_handlers_setendsubmsg(h, f(h, "field"), &msg_onendfield, NULL); - upb_handlers_setendsubmsg(h, f(h, "extension"), &pushextension, NULL); - } else if (m == GOOGLE_PROTOBUF_FILEDESCRIPTORPROTO) { + upb_handlers_setstring(h, D(DescriptorProto_name), &msg_onname, NULL); + upb_handlers_setendsubmsg(h, D(DescriptorProto_field), &msg_onendfield, + NULL); + upb_handlers_setendsubmsg(h, D(DescriptorProto_extension), &pushextension, + NULL); + } else if (m == D(FileDescriptorProto)) { upb_handlers_setstartmsg(h, &file_startmsg, NULL); upb_handlers_setendmsg(h, &file_endmsg, NULL); - upb_handlers_setstring(h, f(h, "package"), &file_onpackage, NULL); - upb_handlers_setendsubmsg(h, f(h, "extension"), &pushextension, NULL); - } else if (m == GOOGLE_PROTOBUF_ENUMVALUEDESCRIPTORPROTO) { + upb_handlers_setstring(h, D(FileDescriptorProto_package), &file_onpackage, + NULL); + upb_handlers_setendsubmsg(h, D(FileDescriptorProto_extension), &pushextension, + NULL); + } else if (m == D(EnumValueDescriptorProto)) { upb_handlers_setstartmsg(h, &enumval_startmsg, NULL); upb_handlers_setendmsg(h, &enumval_endmsg, NULL); - upb_handlers_setstring(h, f(h, "name"), &enumval_onname, NULL); - upb_handlers_setint32(h, f(h, "number"), &enumval_onnumber, NULL); - } else if (m == GOOGLE_PROTOBUF_ENUMDESCRIPTORPROTO) { + upb_handlers_setstring(h, D(EnumValueDescriptorProto_name), &enumval_onname, NULL); + upb_handlers_setint32(h, D(EnumValueDescriptorProto_number), &enumval_onnumber, + NULL); + } else if (m == D(EnumDescriptorProto)) { upb_handlers_setstartmsg(h, &enum_startmsg, NULL); upb_handlers_setendmsg(h, &enum_endmsg, NULL); - upb_handlers_setstring(h, f(h, "name"), &enum_onname, NULL); - } else if (m == GOOGLE_PROTOBUF_FIELDDESCRIPTORPROTO) { + upb_handlers_setstring(h, D(EnumDescriptorProto_name), &enum_onname, NULL); + } else if (m == D(FieldDescriptorProto)) { upb_handlers_setstartmsg(h, &field_startmsg, NULL); upb_handlers_setendmsg(h, &field_endmsg, NULL); - upb_handlers_setint32(h, f(h, "type"), &field_ontype, NULL); - upb_handlers_setint32(h, f(h, "label"), &field_onlabel, NULL); - upb_handlers_setint32(h, f(h, "number"), &field_onnumber, NULL); - upb_handlers_setstring(h, f(h, "name"), &field_onname, NULL); - upb_handlers_setstring(h, f(h, "type_name"), &field_ontypename, NULL); - upb_handlers_setstring(h, f(h, "extendee"), &field_onextendee, NULL); - upb_handlers_setstring(h, f(h, "default_value"), &field_ondefaultval, NULL); - } else if (m == GOOGLE_PROTOBUF_FIELDOPTIONS) { - upb_handlers_setbool(h, f(h, "lazy"), &field_onlazy, NULL); + upb_handlers_setint32(h, D(FieldDescriptorProto_type), &field_ontype, + NULL); + upb_handlers_setint32(h, D(FieldDescriptorProto_label), &field_onlabel, + NULL); + upb_handlers_setint32(h, D(FieldDescriptorProto_number), &field_onnumber, + NULL); + upb_handlers_setstring(h, D(FieldDescriptorProto_name), &field_onname, + NULL); + upb_handlers_setstring(h, D(FieldDescriptorProto_type_name), + &field_ontypename, NULL); + upb_handlers_setstring(h, D(FieldDescriptorProto_extendee), + &field_onextendee, NULL); + upb_handlers_setstring(h, D(FieldDescriptorProto_default_value), + &field_ondefaultval, NULL); + } else if (m == D(FieldOptions)) { + upb_handlers_setbool(h, D(FieldOptions_lazy), &field_onlazy, NULL); } } +#undef D + const upb_handlers *upb_descreader_newhandlers(const void *owner) { - return upb_handlers_newfrozen( - GOOGLE_PROTOBUF_FILEDESCRIPTORSET, owner, reghandlers, NULL); + const upb_symtab *s = upbdefs_google_protobuf_descriptor(&s); + const upb_handlers *h = upb_handlers_newfrozen( + upbdefs_google_protobuf_FileDescriptorSet(s), owner, reghandlers, s); + upb_symtab_unref(s, &s); + return h; } diff --git a/upb/handlers-inl.h b/upb/handlers-inl.h index 0bee5a2..25cbf0a 100644 --- a/upb/handlers-inl.h +++ b/upb/handlers-inl.h @@ -164,7 +164,7 @@ template <class T> struct remove_constptr<const T *> { typedef T *type; }; template <class T, class U> struct disable_if_same { typedef void Type; }; template <class T> struct disable_if_same<T, T> {}; -template <class T> void DeletePointer(void *p) { delete static_cast<T *>(p); } +template <class T> void DeletePointer(void *p) { delete static_cast<T>(p); } template <class T1, class T2> struct FirstUnlessVoid { @@ -802,6 +802,7 @@ struct ConvertParams<BoundFunc5<R, P1, P2, P3, P4, P5, F, I> > { const FieldDef *f, \ const Handlers::utype ## Handler& handler) { \ assert(!handler.registered_); \ + handler.AddCleanup(this); \ handler.registered_ = true; \ return upb_handlers_set##ltype(this, f, handler.handler_, &handler.attr_); \ } \ @@ -876,8 +877,10 @@ template<class T> const void *UniquePtrForType() { template <class T> template <class F> inline Handler<T>::Handler(F func) - : registered_(false) { - upb_handlerattr_sethandlerdata(&attr_, func.GetData(), func.GetCleanup()); + : registered_(false), + cleanup_data_(func.GetData()), + cleanup_func_(func.GetCleanup()) { + upb_handlerattr_sethandlerdata(&attr_, func.GetData()); typedef typename ReturnOf<T>::Return Return; typedef typename ConvertParams<F>::Func ConvertedParamsFunc; typedef typename MaybeWrapReturn<ConvertedParamsFunc, Return>::Func @@ -911,9 +914,8 @@ inline Handler<T>::~Handler() { inline HandlerAttributes::HandlerAttributes() { upb_handlerattr_init(this); } inline HandlerAttributes::~HandlerAttributes() { upb_handlerattr_uninit(this); } -inline bool HandlerAttributes::SetHandlerData(void *hd, - upb_handlerfree *cleanup) { - return upb_handlerattr_sethandlerdata(this, hd, cleanup); +inline bool HandlerAttributes::SetHandlerData(const void *hd) { + return upb_handlerattr_sethandlerdata(this, hd); } inline const void* HandlerAttributes::handler_data() const { return upb_handlerattr_handlerdata(this); @@ -965,7 +967,7 @@ inline reffed_ptr<Handlers> Handlers::New(const MessageDef *m) { } inline reffed_ptr<const Handlers> Handlers::NewFrozen( const MessageDef *m, upb_handlers_callback *callback, - void *closure) { + const void *closure) { const upb_handlers *h = upb_handlers_newfrozen(m, &h, callback, closure); return reffed_ptr<const Handlers>(h, &h); } @@ -1001,58 +1003,70 @@ inline bool Handlers::Freeze(const std::vector<Handlers*>& h, Status* status) { inline const MessageDef *Handlers::message_def() const { return upb_handlers_msgdef(this); } +inline bool Handlers::AddCleanup(void *p, upb_handlerfree *func) { + return upb_handlers_addcleanup(this, p, func); +} inline bool Handlers::SetStartMessageHandler( const Handlers::StartMessageHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setstartmsg(this, handler.handler_, &handler.attr_); } inline bool Handlers::SetEndMessageHandler( const Handlers::EndMessageHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setendmsg(this, handler.handler_, &handler.attr_); } inline bool Handlers::SetStartStringHandler(const FieldDef *f, const StartStringHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setstartstr(this, f, handler.handler_, &handler.attr_); } inline bool Handlers::SetEndStringHandler(const FieldDef *f, const EndFieldHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setendstr(this, f, handler.handler_, &handler.attr_); } inline bool Handlers::SetStringHandler(const FieldDef *f, const StringHandler& handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setstring(this, f, handler.handler_, &handler.attr_); } inline bool Handlers::SetStartSequenceHandler( const FieldDef *f, const StartFieldHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setstartseq(this, f, handler.handler_, &handler.attr_); } inline bool Handlers::SetStartSubMessageHandler( const FieldDef *f, const StartFieldHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setstartsubmsg(this, f, handler.handler_, &handler.attr_); } inline bool Handlers::SetEndSubMessageHandler(const FieldDef *f, const EndFieldHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setendsubmsg(this, f, handler.handler_, &handler.attr_); } inline bool Handlers::SetEndSequenceHandler(const FieldDef *f, const EndFieldHandler &handler) { assert(!handler.registered_); handler.registered_ = true; + handler.AddCleanup(this); return upb_handlers_setendseq(this, f, handler.handler_, &handler.attr_); } inline bool Handlers::SetSubHandlers(const FieldDef *f, const Handlers *sub) { diff --git a/upb/handlers.c b/upb/handlers.c index be035ba..024cd0c 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -21,12 +21,17 @@ char _upb_noclosure; static void freehandlers(upb_refcounted *r) { upb_handlers *h = (upb_handlers*)r; - for (int i = 0; i < h->msg->selector_count; i++) { - upb_handlerfree *cleanup = h->table[i].attr.cleanup; - if (cleanup) { - cleanup(h->table[i].attr.handler_data_); - } + + upb_inttable_iter i; + upb_inttable_begin(&i, &h->cleanup_); + for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { + void *val = (void*)upb_inttable_iter_key(&i); + upb_value func_val = upb_inttable_iter_value(&i); + upb_handlerfree *func = upb_value_getfptr(func_val); + func(val); } + + upb_inttable_uninit(&h->cleanup_); upb_msgdef_unref(h->msg, h); free(h->sub); free(h); @@ -49,7 +54,7 @@ static const struct upb_refcounted_vtbl vtbl = {visithandlers, freehandlers}; typedef struct { upb_inttable tab; // maps upb_msgdef* -> upb_handlers*. upb_handlers_callback *callback; - void *closure; + const void *closure; } dfs_state; // TODO(haberman): discard upb_handlers* objects that do not actually have any @@ -283,6 +288,7 @@ upb_handlers *upb_handlers_new(const upb_msgdef *md, const void *owner) { h->sub = calloc(md->submsg_field_count, sizeof(*h->sub)); if (!h->sub) goto oom; if (!upb_refcounted_init(UPB_UPCAST(h), &vtbl, owner)) goto oom; + if (!upb_inttable_init(&h->cleanup_, UPB_CTYPE_FPTR)) goto oom; // calloc() above initialized all handlers to NULL. return h; @@ -295,7 +301,7 @@ oom: const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, const void *owner, upb_handlers_callback *callback, - void *closure) { + const void *closure) { dfs_state state; state.callback = callback; state.closure = closure; @@ -396,6 +402,15 @@ const upb_handlers *upb_handlers_getsubhandlers_sel(const upb_handlers *h, const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h) { return h->msg; } +bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *func) { + if (upb_inttable_lookupptr(&h->cleanup_, p, NULL)) { + return false; + } + bool ok = upb_inttable_insertptr(&h->cleanup_, p, upb_value_fptr(func)); + UPB_ASSERT_VAR(ok, ok); + return true; +} + /* "Static" methods ***********************************************************/ @@ -584,10 +599,8 @@ void upb_handlerattr_uninit(upb_handlerattr *attr) { UPB_UNUSED(attr); } -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, void *hd, - upb_handlerfree *cleanup) { +bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd) { attr->handler_data_ = hd; - attr->cleanup = cleanup; return true; } diff --git a/upb/handlers.h b/upb/handlers.h index a03c99e..6a8193a 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -91,7 +91,6 @@ extern char _upb_noclosure; // A selector refers to a specific field handler in the Handlers object // (for example: the STARTSUBMSG handler for field "field15"). typedef int32_t upb_selector_t; -typedef void upb_func(); #ifdef __cplusplus extern "C" { @@ -140,12 +139,9 @@ class upb::HandlerAttributes { ~HandlerAttributes(); // Sets the handler data that will be passed as the second parameter of the - // handler. - // - // Warning: if you use these attributes for multiple handlers, the - // cleanup handler will be called once for each handler it was successfully - // set on. - bool SetHandlerData(void *handler_data, upb_handlerfree *cleanup); + // handler. To free this pointer when the handlers are freed, call + // Handlers::AddCleanup(). + bool SetHandlerData(const void *handler_data); const void* handler_data() const; // Use this to specify the type of the closure. This will be checked against @@ -175,14 +171,13 @@ class upb::HandlerAttributes { #else struct upb_handlerattr { #endif - void *handler_data_; - upb_handlerfree *cleanup; + const void *handler_data_; const void *closure_type_; const void *return_closure_type_; bool alwaysok_; }; -#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, NULL, false} +#define UPB_HANDLERATTR_INITIALIZER {NULL, NULL, NULL, false} typedef struct { upb_func *func; @@ -292,7 +287,7 @@ class upb::Handlers { // correct type. typedef void GenericFunction(); - typedef void HandlersCallback(void *closure, upb_handlers *h); + typedef void HandlersCallback(const void *closure, upb_handlers *h); // Returns a new handlers object for the given frozen msgdef. // Returns NULL if memory allocation failed. @@ -305,7 +300,7 @@ class upb::Handlers { // subhandlers set by the callback will be overwritten. static reffed_ptr<const Handlers> NewFrozen(const MessageDef *m, HandlersCallback *callback, - void *closure); + const void *closure); // Functionality from upb::RefCounted. bool IsFrozen() const; @@ -335,6 +330,11 @@ class upb::Handlers { // Returns the msgdef associated with this handlers object. const MessageDef* message_def() const; + // Adds the given pointer and function to the list of cleanup functions that + // will be run when these handlers are freed. If this pointer has previously + // been registered, the function returns false and does nothing. + bool AddCleanup(void *ptr, upb_handlerfree *cleanup); + // Sets the startmsg handler for the message, which is defined as follows: // // bool startmsg(MyType* closure) { @@ -534,6 +534,7 @@ struct upb_handlers { const upb_msgdef *msg; const upb_handlers **sub; const void *top_closure_type; + upb_inttable cleanup_; upb_status status_; // Used only when mutable. upb_handlers_tabent table[1]; // Dynamically-sized field handler array. }; @@ -619,11 +620,20 @@ template <class T> class Handler { ~Handler(); private: + void AddCleanup(Handlers* h) const { + if (cleanup_func_) { + bool ok = h->AddCleanup(cleanup_data_, cleanup_func_); + UPB_ASSERT_VAR(ok, ok); + } + } + UPB_DISALLOW_COPY_AND_ASSIGN(Handler); friend class Handlers; FuncPtr handler_; mutable HandlerAttributes attr_; mutable bool registered_; + void *cleanup_data_; + upb_handlerfree *cleanup_func_; }; } // namespace upb @@ -657,8 +667,7 @@ size_t upb_bufhandle_objofs(const upb_bufhandle *h); void upb_handlerattr_init(upb_handlerattr *attr); void upb_handlerattr_uninit(upb_handlerattr *attr); -bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, void *hd, - upb_handlerfree *cleanup); +bool upb_handlerattr_sethandlerdata(upb_handlerattr *attr, const void *hd); bool upb_handlerattr_setclosuretype(upb_handlerattr *attr, const void *type); const void *upb_handlerattr_closuretype(const upb_handlerattr *attr); bool upb_handlerattr_setreturnclosuretype(upb_handlerattr *attr, @@ -673,13 +682,13 @@ UPB_INLINE const void *upb_handlerattr_handlerdata( } // upb_handlers -typedef void upb_handlers_callback(void *closure, upb_handlers *h); +typedef void upb_handlers_callback(const void *closure, upb_handlers *h); upb_handlers *upb_handlers_new(const upb_msgdef *m, const void *owner); const upb_handlers *upb_handlers_newfrozen(const upb_msgdef *m, const void *owner, upb_handlers_callback *callback, - void *closure); + const void *closure); bool upb_handlers_isfrozen(const upb_handlers *h); void upb_handlers_ref(const upb_handlers *h, const void *owner); void upb_handlers_unref(const upb_handlers *h, const void *owner); @@ -690,6 +699,7 @@ void upb_handlers_checkref(const upb_handlers *h, const void *owner); const upb_status *upb_handlers_status(upb_handlers *h); void upb_handlers_clearerr(upb_handlers *h); const upb_msgdef *upb_handlers_msgdef(const upb_handlers *h); +bool upb_handlers_addcleanup(upb_handlers *h, void *p, upb_handlerfree *hfree); bool upb_handlers_setstartmsg(upb_handlers *h, upb_startmsg_handlerfunc *func, upb_handlerattr *attr); diff --git a/upb/json/typed_printer.c b/upb/json/typed_printer.c new file mode 100644 index 0000000..e79cfc1 --- /dev/null +++ b/upb/json/typed_printer.c @@ -0,0 +1,322 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2014 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * Uses YAJL at the moment; this is not exposed publicly and will likely change + * in the future. + * + */ + +#include "upb/json/typed_printer.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <stdint.h> +#include <yajl/yajl_gen.h> + +static void doprint(void *_p, const char *buf, unsigned int len) { + upb_json_typedprinter *p = _p; + // YAJL doesn't support returning an error status here, so we can't properly + // support clients who return a value other than "len" here. + size_t n = upb_bytessink_putbuf(p->output_, p->subc_, buf, len, NULL); + UPB_ASSERT_VAR(n, n == len); +} + +// StringPiece; a pointer plus a length. +typedef struct { + const char *ptr; + size_t len; +} strpc; + +strpc *newstrpc(upb_handlers *h, const upb_fielddef *f) { + strpc *ret = malloc(sizeof(*ret)); + ret->ptr = upb_fielddef_name(f); + ret->len = strlen(ret->ptr); + upb_handlers_addcleanup(h, ret, free); + return ret; +} + +#define CHKYAJL(x) if ((x) != yajl_gen_status_ok) return false; +#define CHK(x) if (!(x)) return false; + +// Wrapper for yajl_gen_string that takes "const char*" instead of "const +// unsigned char*". +static yajl_gen_status yajl_gen_string2(yajl_gen yajl, const char *ptr, + size_t len) { + return yajl_gen_string(yajl, (const unsigned char *)ptr, len); +} + +// Wrappers for yajl_gen_number() that formats floating point values +// according to our custom formats. Right now we use %.8g and %.17g +// for float/double, respectively, to match proto2::util::JsonFormat's +// defaults. May want to change this later. + +static yajl_gen_status upbyajl_gen_double(yajl_gen yajl, double val) { + char data[64]; + int n = snprintf(data, sizeof(data), "%.17g", val); + CHK(n > 0 && n < sizeof(data)); + return yajl_gen_number(yajl, data, n); +} + +static yajl_gen_status upbyajl_gen_float(yajl_gen yajl, float val) { + char data[64]; + int n = snprintf(data, sizeof(data), "%.8g", val); + CHK(n > 0 && n < sizeof(data)); + return yajl_gen_number(yajl, data, n); +} + +static yajl_gen_status upbyajl_gen_uint64(yajl_gen yajl, + unsigned long long val) { + char data[64]; + int n = snprintf(data, sizeof(data), "%llu", val); + CHK(n > 0 && n < sizeof(data)); + return yajl_gen_number(yajl, data, n); +} + +static bool putkey(void *closure, const void *handler_data) { + upb_json_typedprinter *p = closure; + const strpc *key = handler_data; + CHKYAJL(yajl_gen_string2(p->yajl_gen_, key->ptr, key->len)); + return true; +} + +#define TYPE_HANDLERS(type, yajlfunc) \ + static bool put##type(void *closure, const void *handler_data, type val) { \ + upb_json_typedprinter *p = closure; \ + UPB_UNUSED(handler_data); \ + CHKYAJL(yajlfunc(p->yajl_gen_, val)); \ + return true; \ + } \ + static bool scalar_##type(void *closure, const void *handler_data, \ + type val) { \ + CHK(putkey(closure, handler_data)); \ + CHK(put##type(closure, handler_data, val)); \ + return true; \ + } + +TYPE_HANDLERS(double, upbyajl_gen_double); +TYPE_HANDLERS(float, upbyajl_gen_float); +TYPE_HANDLERS(bool, yajl_gen_bool); +TYPE_HANDLERS(int32_t, yajl_gen_integer); +TYPE_HANDLERS(uint32_t, yajl_gen_integer); +TYPE_HANDLERS(int64_t, yajl_gen_integer); +TYPE_HANDLERS(uint64_t, upbyajl_gen_uint64); + +#undef TYPE_HANDLERS + +static void *startsubmsg(void *closure, const void *handler_data) { + return putkey(closure, handler_data) ? closure : UPB_BREAK; +} + +static bool startmap(void *closure, const void *handler_data) { + UPB_UNUSED(handler_data); + upb_json_typedprinter *p = closure; + if (p->depth_++ == 0) { + upb_bytessink_start(p->output_, 0, &p->subc_); + } + CHKYAJL(yajl_gen_map_open(p->yajl_gen_)); + return true; +} + +static bool endmap(void *closure, const void *handler_data, upb_status *s) { + UPB_UNUSED(handler_data); + UPB_UNUSED(s); + upb_json_typedprinter *p = closure; + if (--p->depth_ == 0) { + upb_bytessink_end(p->output_); + } + CHKYAJL(yajl_gen_map_close(p->yajl_gen_)); + return true; +} + +static void *startseq(void *closure, const void *handler_data) { + upb_json_typedprinter *p = closure; + CHK(putkey(closure, handler_data)); + CHKYAJL(yajl_gen_array_open(p->yajl_gen_)); + return closure; +} + +static bool endseq(void *closure, const void *handler_data) { + UPB_UNUSED(handler_data); + upb_json_typedprinter *p = closure; + CHKYAJL(yajl_gen_array_close(p->yajl_gen_)); + return true; +} + +static size_t putstr(void *closure, const void *handler_data, const char *str, + size_t len, const upb_bufhandle *handle) { + UPB_UNUSED(handle); + upb_json_typedprinter *p = closure; + CHKYAJL(yajl_gen_string2(p->yajl_gen_, str, len)); + return len; +} + +// This has to Base64 encode the bytes, because JSON has no "bytes" type. +static size_t putbytes(void *closure, const void *handler_data, const char *str, + size_t len, const upb_bufhandle *handle) { + UPB_UNUSED(handle); + upb_json_typedprinter *p = closure; + + // This is the regular base64, not the "web-safe" version. + static const char base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + // Base64-encode. + char data[16000]; + const char *limit = data + sizeof(data); + const unsigned char *from = (const unsigned char*)str; + char *to = data; + size_t remaining = len; + while (remaining > 2) { + // TODO(haberman): handle encoded lengths > sizeof(data) + UPB_ASSERT_VAR(limit, (limit - to) >= 4); + + to[0] = base64[from[0] >> 2]; + to[1] = base64[((from[0] & 0x3) << 4) + (from[1] >> 4)]; + to[2] = base64[((from[1] & 0xf) << 2) + (from[2] >> 6)]; + to[3] = base64[from[2] & 0x3f]; + + remaining -= 3; + to += 4; + from += 3; + } + + size_t bytes = to - data; + if (yajl_gen_string2(p->yajl_gen_, data, bytes) != yajl_gen_status_ok) { + return 0; + } + return len; +} + +static size_t scalar_str(void *closure, const void *handler_data, + const char *str, size_t len, + const upb_bufhandle *handle) { + CHK(putkey(closure, handler_data)); + CHK(putstr(closure, handler_data, str, len, handle)); + return len; +} + +static size_t scalar_bytes(void *closure, const void *handler_data, + const char *str, size_t len, + const upb_bufhandle *handle) { + CHK(putkey(closure, handler_data)); + CHK(putbytes(closure, handler_data, str, len, handle)); + return len; +} + +void sethandlers(const void *closure, upb_handlers *h) { + UPB_UNUSED(closure); + + upb_handlerattr empty_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlers_setstartmsg(h, startmap, &empty_attr); + upb_handlers_setendmsg(h, endmap, &empty_attr); + +#define TYPE(type, name, ctype) \ + case type: \ + if (upb_fielddef_isseq(f)) { \ + upb_handlers_set##name(h, f, put##ctype, &empty_attr); \ + } else { \ + upb_handlers_set##name(h, f, scalar_##ctype, &name_attr); \ + } \ + break; + + upb_msg_iter i; + upb_msg_begin(&i, upb_handlers_msgdef(h)); + for(; !upb_msg_done(&i); upb_msg_next(&i)) { + const upb_fielddef *f = upb_msg_iter_field(&i); + + upb_handlerattr name_attr = UPB_HANDLERATTR_INITIALIZER; + upb_handlerattr_sethandlerdata(&name_attr, newstrpc(h, f)); + + if (upb_fielddef_isseq(f)) { + upb_handlers_setstartseq(h, f, startseq, &name_attr); + upb_handlers_setendseq(h, f, endseq, &empty_attr); + } + + switch (upb_fielddef_type(f)) { + TYPE(UPB_TYPE_FLOAT, float, float); + TYPE(UPB_TYPE_DOUBLE, double, double); + TYPE(UPB_TYPE_BOOL, bool, bool); + TYPE(UPB_TYPE_ENUM, int32, int32_t); + TYPE(UPB_TYPE_INT32, int32, int32_t); + TYPE(UPB_TYPE_UINT32, uint32, uint32_t); + TYPE(UPB_TYPE_INT64, int64, int64_t); + TYPE(UPB_TYPE_UINT64, uint64, uint64_t); + case UPB_TYPE_STRING: + // XXX: this doesn't support strings that span buffers yet. + if (upb_fielddef_isseq(f)) { + upb_handlers_setstring(h, f, putstr, &empty_attr); + } else { + upb_handlers_setstring(h, f, scalar_str, &name_attr); + } + break; + case UPB_TYPE_BYTES: + // XXX: this doesn't support strings that span buffers yet. + if (upb_fielddef_isseq(f)) { + upb_handlers_setstring(h, f, putbytes, &empty_attr); + } else { + upb_handlers_setstring(h, f, scalar_bytes, &name_attr); + } + break; + case UPB_TYPE_MESSAGE: + if (!upb_fielddef_isseq(f)) { + upb_handlers_setstartsubmsg(h, f, startsubmsg, &name_attr); + } + break; + } + + upb_handlerattr_uninit(&name_attr); + } + + upb_handlerattr_uninit(&empty_attr); +#undef TYPE +} + +// YAJL unfortunately does not support stack allocation, nor resetting an +// allocated object, so we have to allocate on the heap and reallocate whenever +// there is a reset. +static void reset(upb_json_typedprinter *p, bool free) { + if (free) { + yajl_gen_free(p->yajl_gen_); + } + p->yajl_gen_ = yajl_gen_alloc(NULL); + yajl_gen_config(p->yajl_gen_, yajl_gen_validate_utf8, 0); + yajl_gen_config(p->yajl_gen_, yajl_gen_print_callback, &doprint, p); +} + +/* Public API *****************************************************************/ + +void upb_json_typedprinter_init(upb_json_typedprinter *p, + const upb_handlers *h) { + p->output_ = NULL; + p->depth_ = 0; + reset(p, false); + upb_sink_reset(&p->input_, h, p); +} + +void upb_json_typedprinter_uninit(upb_json_typedprinter *p) { + yajl_gen_free(p->yajl_gen_); +} + +void upb_json_typedprinter_reset(upb_json_typedprinter *p) { + p->depth_ = 0; + reset(p, true); +} + +void upb_json_typedprinter_resetoutput(upb_json_typedprinter *p, + upb_bytessink *output) { + upb_json_typedprinter_reset(p); + p->output_ = output; +} + +upb_sink *upb_json_typedprinter_input(upb_json_typedprinter *p) { + return &p->input_; +} + +const upb_handlers *upb_json_typedprinter_newhandlers(const upb_msgdef *md, + const void *owner) { + return upb_handlers_newfrozen(md, owner, sethandlers, NULL); +} diff --git a/upb/json/typed_printer.h b/upb/json/typed_printer.h new file mode 100644 index 0000000..190aeb3 --- /dev/null +++ b/upb/json/typed_printer.h @@ -0,0 +1,116 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2014 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * upb::json::TypedPrinter allows you to create handlers that emit JSON + * according to a specific protobuf schema. + */ + +#ifndef UPB_JSON_TYPED_PRINTER_H_ +#define UPB_JSON_TYPED_PRINTER_H_ + +#include "upb/sink.h" + +#ifdef __cplusplus +namespace upb { +namespace json { +class TypedPrinter; +} // namespace json +} // namespace upb + +typedef upb::json::TypedPrinter upb_json_typedprinter; +#else +struct upb_json_typedprinter; +typedef struct upb_json_typedprinter upb_json_typedprinter; +#endif + + +/* upb::json::TypedPrinter ****************************************************/ + +#ifdef __cplusplus + +// Prints an incoming stream of data to a BytesSink in JSON format. +class upb::json::TypedPrinter { + public: + TypedPrinter(const upb::Handlers* handlers); + ~TypedPrinter(); + + // Resets the state of the printer, so that it will expect to begin a new + // document. + void Reset(); + + // Resets the output pointer which will serve as our closure. Implies + // Reset(). + void ResetOutput(BytesSink* output); + + // The input to the printer. + Sink* input(); + + // Returns handlers for printing according to the specified schema. + static reffed_ptr<const Handlers> NewHandlers(const upb::MessageDef* md); + + private: +#else +struct upb_json_typedprinter { +#endif + upb_sink input_; + // Pointer to yajl_gen; void* here so we don't have to include YAJL headers. + void *yajl_gen_; + void *subc_; + upb_bytessink *output_; + // We track the depth so that we know when to emit startstr/endstr on the + // output. + int depth_; +}; + +// Native C API. +#ifdef __cplusplus +extern "C" { +#endif + +void upb_json_typedprinter_init(upb_json_typedprinter *p, + const upb_handlers *h); +void upb_json_typedprinter_uninit(upb_json_typedprinter *p); +void upb_json_typedprinter_reset(upb_json_typedprinter *p); +void upb_json_typedprinter_resetoutput(upb_json_typedprinter *p, + upb_bytessink *output); +upb_sink *upb_json_typedprinter_input(upb_json_typedprinter *p); +const upb_handlers *upb_json_typedprinter_newhandlers(const upb_msgdef *md, + const void *owner); + +#ifdef __cplusplus +} // extern "C" +#endif + +#ifdef __cplusplus + +namespace upb { +namespace json { +inline TypedPrinter::TypedPrinter(const upb::Handlers* handlers) { + upb_json_typedprinter_init(this, handlers); +} +inline TypedPrinter::~TypedPrinter() { + upb_json_typedprinter_uninit(this); +} +inline void TypedPrinter::Reset() { + upb_json_typedprinter_reset(this); +} +inline void TypedPrinter::ResetOutput(BytesSink* output) { + upb_json_typedprinter_resetoutput(this, output); +} +inline Sink* TypedPrinter::input() { + return upb_json_typedprinter_input(this); +} +inline reffed_ptr<const Handlers> TypedPrinter::NewHandlers( + const upb::MessageDef *md) { + const Handlers* h = upb_json_typedprinter_newhandlers(md, &h); + return reffed_ptr<const Handlers>(h, &h); +} +} // namespace json +} // namespace upb + +#endif + +#endif // UPB_JSON_TYPED_PRINTER_H_ diff --git a/upb/pb/compile_decoder.c b/upb/pb/compile_decoder.c index 400d6fa..59bd03b 100644 --- a/upb/pb/compile_decoder.c +++ b/upb/pb/compile_decoder.c @@ -4,7 +4,14 @@ * Copyright (c) 2013 Google Inc. See LICENSE for details. * Author: Josh Haberman <jhaberman@gmail.com> * - * Code to compile a upb::MessageDef into bytecode for decoding that message. + * Code to compile a upb::Handlers into bytecode for decoding a protobuf + * according to that specific schema and destination handlers. + * + * Compiling to bytecode is always the first step. If we are using the + * interpreted decoder we leave it as bytecode and interpret that. If we are + * using a JIT decoder we use a code generator to turn the bytecode into native + * code, LLVM IR, etc. + * * Bytecode definition is in decoder.int.h. */ diff --git a/upb/pb/compile_decoder_x64.dasc b/upb/pb/compile_decoder_x64.dasc index 97fb5ce..9eec6a5 100644 --- a/upb/pb/compile_decoder_x64.dasc +++ b/upb/pb/compile_decoder_x64.dasc @@ -5,8 +5,7 @@ |// Author: Josh Haberman <jhaberman@gmail.com> |// |// JIT compiler for upb_pbdecoder on x86-64. Generates machine code from the -|// bytecode generated in compile_decoder.c, but unlike the interpreter we bind -|// to a specific set of handlers for greater efficiency. +|// bytecode generated in compile_decoder.c. | |.arch x64 |.actionlist upb_jit_actionlist diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c index 9c54b8a..1098e63 100644 --- a/upb/pb/decoder.c +++ b/upb/pb/decoder.c @@ -3,6 +3,19 @@ * * Copyright (c) 2008-2013 Google Inc. See LICENSE for details. * Author: Josh Haberman <jhaberman@gmail.com> + * + * This file implements a VM for the interpreted (bytecode) decoder. + * + * Bytecode must previously have been generated using the bytecode compiler in + * compile_decoder.c. This decoder then walks through the bytecode op-by-op to + * parse the input. + * + * Decoding is fully resumable; we just keep a pointer to the current bytecode + * instruction and resume from there. A fair amount of the logic here is to + * handle the fact that values can span buffer seams and we have to be able to + * be capable of suspending/resuming from any byte in the stream. This + * sometimes requires keeping a few trailing bytes from the last buffer around + * in the "residual" buffer. */ #include <inttypes.h> @@ -55,7 +68,7 @@ static bool consumes_input(opcode op) { } } -static bool in_residual_buf(upb_pbdecoder *d, const char *p); +static bool in_residual_buf(const upb_pbdecoder *d, const char *p); // It's unfortunate that we have to micro-manage the compiler this way, // especially since this tuning is necessarily specific to one hardware @@ -83,18 +96,14 @@ void upb_pbdecoder_seterr(upb_pbdecoder *d, const char *msg) { // How many bytes can be safely read from d->ptr without reading past end-of-buf // or past the current delimited end. -static size_t curbufleft(upb_pbdecoder *d) { +static size_t curbufleft(const upb_pbdecoder *d) { assert(d->data_end >= d->ptr); return d->data_end - d->ptr; } -static const char *ptr(upb_pbdecoder *d) { - return d->ptr; -} - -// Overall offset of d->ptr. -uint64_t offset(upb_pbdecoder *d) { - return d->bufstart_ofs + (ptr(d) - d->buf); +// Overall stream offset of d->ptr. +uint64_t offset(const upb_pbdecoder *d) { + return d->bufstart_ofs + (d->ptr - d->buf); } // Advances d->ptr. @@ -107,12 +116,12 @@ static bool in_buf(const char *p, const char *buf, const char *end) { return p >= buf && p <= end; } -static bool in_residual_buf(upb_pbdecoder *d, const char *p) { +static bool in_residual_buf(const upb_pbdecoder *d, const char *p) { return in_buf(p, d->residual, d->residual_end); } -// Calculates the delim_end value, which represents a combination of the -// current buffer and the stack, so must be called whenever either is updated. +// Calculates the delim_end value, which is affected by both the current buffer +// and the parsing stack, so must be called whenever either is updated. static void set_delim_end(upb_pbdecoder *d) { size_t delim_ofs = d->top->end_ofs - d->bufstart_ofs; if (delim_ofs <= (d->end - d->buf)) { @@ -141,8 +150,8 @@ static void checkpoint(upb_pbdecoder *d) { // The assertion here is in the interests of efficiency, not correctness. // We are trying to ensure that we don't checkpoint() more often than // necessary. - assert(d->checkpoint != ptr(d)); - d->checkpoint = ptr(d); + assert(d->checkpoint != d->ptr); + d->checkpoint = d->ptr; } // Resumes the decoder from an initial state or from a previous suspend. @@ -154,14 +163,14 @@ int32_t upb_pbdecoder_resume(upb_pbdecoder *d, void *p, const char *buf, d->handle = handle; if (d->residual_end > d->residual) { // We have residual bytes from the last buffer. - assert(ptr(d) == d->residual); + assert(d->ptr == d->residual); } else { switchtobuf(d, buf, buf + size); } - d->checkpoint = ptr(d); + d->checkpoint = d->ptr; if (d->top->groupnum < 0) { CHECK_RETURN(upb_pbdecoder_skipunknown(d, -1, 0)); - d->checkpoint = ptr(d); + d->checkpoint = d->ptr; } return DECODE_OK; } @@ -198,7 +207,7 @@ static size_t suspend_save(upb_pbdecoder *d) { // Checkpoint was in residual buf; append user byte(s) to residual buf. assert((d->residual_end - d->residual) + d->size_param <= sizeof(d->residual)); - if (!in_residual_buf(d, ptr(d))) { + if (!in_residual_buf(d, d->ptr)) { d->bufstart_ofs -= (d->residual_end - d->residual); } memcpy(d->residual_end, d->buf_param, d->size_param); @@ -209,7 +218,7 @@ static size_t suspend_save(upb_pbdecoder *d) { d->ptr = d->checkpoint; size_t save = curbufleft(d); assert(save <= sizeof(d->residual)); - memcpy(d->residual, ptr(d), save); + memcpy(d->residual, d->ptr, save); d->residual_end = d->residual + save; d->bufstart_ofs = offset(d); } @@ -218,8 +227,11 @@ static size_t suspend_save(upb_pbdecoder *d) { return d->size_param; } +// Skips "bytes" bytes in the stream, which may be more than available. If we +// skip more bytes than are available, we return a long read count to the caller +// indicating how many bytes the caller should skip before passing a new buffer. static int32_t skip(upb_pbdecoder *d, size_t bytes) { - assert(!in_residual_buf(d, ptr(d)) || d->size_param == 0); + assert(!in_residual_buf(d, d->ptr) || d->size_param == 0); if (curbufleft(d) >= bytes) { // Skipped data is all in current buffer. advance(d, bytes); @@ -235,19 +247,24 @@ static int32_t skip(upb_pbdecoder *d, size_t bytes) { } } +// Copies the next "bytes" bytes into "buf" and advances the stream. +// Requires that this many bytes are available in the current buffer. FORCEINLINE void consumebytes(upb_pbdecoder *d, void *buf, size_t bytes) { assert(bytes <= curbufleft(d)); - memcpy(buf, ptr(d), bytes); + memcpy(buf, d->ptr, bytes); advance(d, bytes); } +// Slow path for getting the next "bytes" bytes, regardless of whether they are +// available in the current buffer or not. Returns a status code as described +// in decoder.int.h. static NOINLINE int32_t getbytes_slow(upb_pbdecoder *d, void *buf, size_t bytes) { const size_t avail = curbufleft(d); consumebytes(d, buf, avail); bytes -= avail; assert(bytes > 0); - if (in_residual_buf(d, ptr(d))) { + if (in_residual_buf(d, d->ptr)) { advancetobuf(d, d->buf_param, d->size_param); } if (curbufleft(d) >= bytes) { @@ -261,6 +278,8 @@ static NOINLINE int32_t getbytes_slow(upb_pbdecoder *d, void *buf, } } +// Gets the next "bytes" bytes, regardless of whether they are available in the +// current buffer or not. Returns a status code as described in decoder.int.h. FORCEINLINE int32_t getbytes(upb_pbdecoder *d, void *buf, size_t bytes) { if (curbufleft(d) >= bytes) { // Buffer has enough data to satisfy. @@ -274,8 +293,8 @@ FORCEINLINE int32_t getbytes(upb_pbdecoder *d, void *buf, size_t bytes) { static NOINLINE size_t peekbytes_slow(upb_pbdecoder *d, void *buf, size_t bytes) { size_t ret = curbufleft(d); - memcpy(buf, ptr(d), ret); - if (in_residual_buf(d, ptr(d))) { + memcpy(buf, d->ptr, ret); + if (in_residual_buf(d, d->ptr)) { size_t copy = UPB_MIN(bytes - ret, d->size_param); memcpy(buf + ret, d->buf_param, copy); ret += copy; @@ -285,7 +304,7 @@ static NOINLINE size_t peekbytes_slow(upb_pbdecoder *d, void *buf, FORCEINLINE size_t peekbytes(upb_pbdecoder *d, void *buf, size_t bytes) { if (curbufleft(d) >= bytes) { - memcpy(buf, ptr(d), bytes); + memcpy(buf, d->ptr, bytes); return bytes; } else { return peekbytes_slow(d, buf, bytes); @@ -295,6 +314,8 @@ FORCEINLINE size_t peekbytes(upb_pbdecoder *d, void *buf, size_t bytes) { /* Decoding of wire types *****************************************************/ +// Slow path for decoding a varint from the current buffer position. +// Returns a status code as described in decoder.int.h. NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, uint64_t *u64) { *u64 = 0; @@ -312,19 +333,21 @@ NOINLINE int32_t upb_pbdecoder_decode_varint_slow(upb_pbdecoder *d, return DECODE_OK; } +// Decodes a varint from the current buffer position. +// Returns a status code as described in decoder.int.h. FORCEINLINE int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { - if (curbufleft(d) > 0 && !(*ptr(d) & 0x80)) { - *u64 = *ptr(d); + if (curbufleft(d) > 0 && !(*d->ptr & 0x80)) { + *u64 = *d->ptr; advance(d, 1); return DECODE_OK; } else if (curbufleft(d) >= 10) { // Fast case. - upb_decoderet r = upb_vdecode_fast(ptr(d)); + upb_decoderet r = upb_vdecode_fast(d->ptr); if (r.p == NULL) { seterr(d, kUnterminatedVarint); return upb_pbdecoder_suspend(d); } - advance(d, r.p - ptr(d)); + advance(d, r.p - d->ptr); *u64 = r.val; return DECODE_OK; } else { @@ -333,6 +356,8 @@ FORCEINLINE int32_t decode_varint(upb_pbdecoder *d, uint64_t *u64) { } } +// Decodes a 32-bit varint from the current buffer position. +// Returns a status code as described in decoder.int.h. FORCEINLINE int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { uint64_t u64; int32_t ret = decode_varint(d, &u64); @@ -349,16 +374,22 @@ FORCEINLINE int32_t decode_v32(upb_pbdecoder *d, uint32_t *u32) { return DECODE_OK; } +// Decodes a fixed32 from the current buffer position. +// Returns a status code as described in decoder.int.h. // TODO: proper byte swapping for big-endian machines. FORCEINLINE int32_t decode_fixed32(upb_pbdecoder *d, uint32_t *u32) { return getbytes(d, u32, 4); } +// Decodes a fixed64 from the current buffer position. +// Returns a status code as described in decoder.int.h. // TODO: proper byte swapping for big-endian machines. FORCEINLINE int32_t decode_fixed64(upb_pbdecoder *d, uint64_t *u64) { return getbytes(d, u64, 8); } +// Non-static versions of the above functions. +// These are called by the JIT for fallback paths. int32_t upb_pbdecoder_decode_f32(upb_pbdecoder *d, uint32_t *u32) { return decode_fixed32(d, u32); } @@ -370,6 +401,7 @@ int32_t upb_pbdecoder_decode_f64(upb_pbdecoder *d, uint64_t *u64) { static double as_double(uint64_t n) { double d; memcpy(&d, &n, 8); return d; } static float as_float(uint32_t n) { float f; memcpy(&f, &n, 4); return f; } +// Pushes a frame onto the decoder stack. static bool push(upb_pbdecoder *d, uint64_t end) { upb_pbdecoder_frame *fr = d->top; @@ -400,6 +432,7 @@ static bool pushtagdelim(upb_pbdecoder *d, uint32_t arg) { return true; } +// Pops a frame from the decoder stack. static void pop(upb_pbdecoder *d) { d->top--; } NOINLINE int32_t upb_pbdecoder_checktag_slow(upb_pbdecoder *d, @@ -477,7 +510,7 @@ have_tag: return DECODE_OK; } - if (ptr(d) == d->delim_end) { + if (d->ptr == d->delim_end) { seterr(d, "Enclosing submessage ended in the middle of value or group"); // Unlike most errors we notice during parsing, right now we have consumed // all of the user's input. @@ -516,6 +549,12 @@ static void goto_endmsg(upb_pbdecoder *d) { d->pc = d->top->base + upb_value_getuint64(v); } +// Parses a tag and jumps to the corresponding bytecode instruction for this +// field. +// +// If the tag is unknown (or the wire type doesn't match), parses the field as +// unknown. If the tag is a valid ENDGROUP tag, jumps to the bytecode +// instruction for the end of message. static int32_t dispatch(upb_pbdecoder *d) { upb_inttable *dispatch = d->top->dispatch; @@ -564,6 +603,8 @@ upb_pbdecoder_frame *outer_frame(upb_pbdecoder *d) { /* The main decoding loop *****************************************************/ +// The main decoder VM function. Uses traditional bytecode dispatch loop with a +// switch() statement. size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, size_t size, const upb_bufhandle *handle) { upb_pbdecoder *d = closure; @@ -591,15 +632,15 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, opcode op = getop(instruction); uint32_t arg = instruction >> 8; int32_t longofs = arg; - assert(ptr(d) != d->residual_end); + assert(d->ptr != d->residual_end); #ifdef UPB_DUMP_BYTECODE fprintf(stderr, "s_ofs=%d buf_ofs=%d data_rem=%d buf_rem=%d delim_rem=%d " "%x %s (%d)\n", (int)offset(d), - (int)(ptr(d) - d->buf), - (int)(d->data_end - ptr(d)), - (int)(d->end - ptr(d)), - (int)((d->top->end_ofs - d->bufstart_ofs) - (ptr(d) - d->buf)), + (int)(d->ptr - d->buf), + (int)(d->data_end - d->ptr), + (int)(d->end - d->ptr), + (int)((d->top->end_ofs - d->bufstart_ofs) - (d->ptr - d->buf)), (int)(d->pc - 1 - group->bytecode), upb_pbdecoder_getopname(op), arg); @@ -657,25 +698,24 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, ) VMCASE(OP_STRING, uint32_t len = curbufleft(d); - size_t n = upb_sink_putstring(&d->top->sink, arg, ptr(d), len, handle); + size_t n = upb_sink_putstring(&d->top->sink, arg, d->ptr, len, handle); if (n > len) { if (n > d->top->end_ofs - offset(d)) { seterr(d, "Tried to skip past end of string."); return upb_pbdecoder_suspend(d); } else { - return skip(d, n); + int32_t ret = skip(d, n); + // This shouldn't return DECODE_OK, because n > len. + assert(ret >= 0); + return ret; } - } else if (n < len) { - advance(d, n); + } + advance(d, n); + if (n < len || d->delim_end == NULL) { + // We aren't finished with this string yet. + d->pc--; // Repeat OP_STRING. + if (n > 0) checkpoint(d); return upb_pbdecoder_suspend(d); - } else { - advance(d, n); - if (d->delim_end == NULL) { // String extends beyond this buf? - d->pc--; // Do OP_STRING again when we resume. - d->bufstart_ofs += size; - d->residual_end = d->residual; - return size; - } } ) VMCASE(OP_ENDSTR, @@ -703,8 +743,8 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, VMCASE(OP_CHECKDELIM, // We are guaranteed of this assert because we never allow ourselves to // consume bytes beyond data_end, which covers delim_end when non-NULL. - assert(!(d->delim_end && ptr(d) > d->delim_end)); - if (ptr(d) == d->delim_end) + assert(!(d->delim_end && d->ptr > d->delim_end)); + if (d->ptr == d->delim_end) d->pc += longofs; ) VMCASE(OP_CALL, @@ -721,7 +761,7 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, VMCASE(OP_TAG1, CHECK_SUSPEND(curbufleft(d) > 0); uint8_t expected = (arg >> 8) & 0xff; - if (*ptr(d) == expected) { + if (*d->ptr == expected) { advance(d, 1); } else { int8_t shortofs; @@ -740,7 +780,7 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, uint16_t expected = (arg >> 8) & 0xffff; if (curbufleft(d) >= 2) { uint16_t actual; - memcpy(&actual, ptr(d), 2); + memcpy(&actual, d->ptr, 2); if (expected == actual) { advance(d, 2); } else { @@ -856,6 +896,10 @@ void upb_pbdecoder_reset(upb_pbdecoder *d) { d->call_len = 1; } +uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d) { + return offset(d); +} + // Not currently required, but to support outgrowing the static stack we need // this. void upb_pbdecoder_uninit(upb_pbdecoder *d) { diff --git a/upb/pb/decoder.h b/upb/pb/decoder.h index 586d2d5..0aa35ec 100644 --- a/upb/pb/decoder.h +++ b/upb/pb/decoder.h @@ -1,11 +1,18 @@ /* * upb - a minimalist implementation of protocol buffers. * - * Copyright (c) 2009-2013 Google Inc. See LICENSE for details. + * Copyright (c) 2009-2014 Google Inc. See LICENSE for details. * Author: Josh Haberman <jhaberman@gmail.com> * * upb::pb::Decoder implements a high performance, streaming, resumable decoder * for the binary protobuf format. + * + * This interface works the same regardless of what decoder backend is being + * used. A client of this class does not need to know whether decoding is using + * a JITted decoder (DynASM, LLVM, etc) or an interpreted decoder. By default, + * it will always use the fastest available decoder. However, you can call + * set_allow_jit(false) to disable any JIT decoder that might be available. + * This is primarily useful for testing purposes. */ #ifndef UPB_DECODER_H_ @@ -200,6 +207,15 @@ class upb::pb::Decoder { // Resets the state of the decoder. void Reset(); + // Returns number of bytes successfully parsed. + // + // This can be useful for determining the stream position where an error + // occurred. + // + // This value may not be up-to-date when called from inside a parsing + // callback. + uint64_t BytesParsed() const; + // Resets the output sink of the Decoder. // The given sink must match method()->dest_handlers(). // @@ -332,6 +348,7 @@ void upb_pbdecoder_reset(upb_pbdecoder *d); const upb_pbdecodermethod *upb_pbdecoder_method(const upb_pbdecoder *d); bool upb_pbdecoder_resetoutput(upb_pbdecoder *d, upb_sink *sink); upb_bytessink *upb_pbdecoder_input(upb_pbdecoder *d); +uint64_t upb_pbdecoder_bytesparsed(const upb_pbdecoder *d); void upb_pbdecodermethodopts_init(upb_pbdecodermethodopts *opts, const upb_handlers *h); @@ -400,6 +417,9 @@ inline const DecoderMethod* Decoder::method() const { inline void Decoder::Reset() { upb_pbdecoder_reset(this); } +inline uint64_t Decoder::BytesParsed() const { + return upb_pbdecoder_bytesparsed(this); +} inline bool Decoder::ResetOutput(Sink* sink) { return upb_pbdecoder_resetoutput(this, sink); } diff --git a/upb/pb/decoder.int.h b/upb/pb/decoder.int.h index 11aa133..d0f12cc 100644 --- a/upb/pb/decoder.int.h +++ b/upb/pb/decoder.int.h @@ -1,3 +1,11 @@ +/* + * upb - a minimalist implementation of protocol buffers. + * + * Copyright (c) 2009-2014 Google Inc. See LICENSE for details. + * Author: Josh Haberman <jhaberman@gmail.com> + * + * Internal-only definitions for the decoder. + */ #ifndef UPB_DECODER_INT_H_ #define UPB_DECODER_INT_H_ diff --git a/upb/pb/textprinter.c b/upb/pb/textprinter.c index 8a49c73..94f19e2 100644 --- a/upb/pb/textprinter.c +++ b/upb/pb/textprinter.c @@ -170,11 +170,10 @@ static bool putenum(void *closure, const void *handler_data, int32_t val) { putf(p, "%s: %s", upb_fielddef_name(f), label); endfield(p); } else { - CHECK(putint32(closure, handler_data, val)); + if (!putint32(closure, handler_data, val)) + return false; } return true; -err: - return false; } static void *startstr(void *closure, const void *handler_data, @@ -182,6 +181,7 @@ static void *startstr(void *closure, const void *handler_data, const upb_fielddef *f = handler_data; UPB_UNUSED(size_hint); upb_textprinter *p = closure; + indent(p); putf(p, "%s: \"", upb_fielddef_name(f)); return p; } @@ -244,16 +244,18 @@ void upb_textprinter_reset(upb_textprinter *p, bool single_line) { p->indent_depth_ = 0; } -static void onmreg(void *c, upb_handlers *h) { - (void)c; +static void onmreg(const void *c, upb_handlers *h) { + UPB_UNUSED(c); const upb_msgdef *m = upb_handlers_msgdef(h); + upb_handlers_setstartmsg(h, startmsg, NULL); upb_handlers_setendmsg(h, endmsg, NULL); + upb_msg_iter i; for(upb_msg_begin(&i, m); !upb_msg_done(&i); upb_msg_next(&i)) { upb_fielddef *f = upb_msg_iter_field(&i); upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, f, NULL); + upb_handlerattr_sethandlerdata(&attr, f); switch (upb_fielddef_type(f)) { case UPB_TYPE_INT32: upb_handlers_setint32(h, f, putint32, &attr); @@ -287,9 +289,7 @@ static void onmreg(void *c, upb_handlers *h) { upb_fielddef_istagdelim(f) ? shortname(upb_msgdef_fullname(upb_fielddef_msgsubdef(f))) : upb_fielddef_name(f); - // TODO(haberman): add "setconsthandlerdata"? If we pass NULL for - // cleanup then we don't need a non-const pointer. - upb_handlerattr_sethandlerdata(&attr, (void*)name, NULL); + upb_handlerattr_sethandlerdata(&attr, name); upb_handlers_setstartsubmsg(h, f, startsubmsg, &attr); upb_handlers_setendsubmsg(h, f, endsubmsg, &attr); break; diff --git a/upb/refcounted.c b/upb/refcounted.c index 455e536..4e01081 100644 --- a/upb/refcounted.c +++ b/upb/refcounted.c @@ -23,7 +23,6 @@ #include <setjmp.h> #include <stdlib.h> -uint32_t static_refcount = 1; static void freeobj(upb_refcounted *o); /* arch-specific atomic primitives *******************************************/ @@ -52,6 +51,27 @@ static bool atomic_dec(upb_atomic_t *a) { Implement them or compile with UPB_THREAD_UNSAFE. #endif +// All static objects point to this refcount. +// It is special-cased in ref/unref below. +uint32_t static_refcount = -1; + +// We can avoid atomic ops for statically-declared objects. +// This is a minor optimization but nice since we can avoid degrading under +// contention in this case. + +static void refgroup(uint32_t *group) { + if (group != &static_refcount) + atomic_inc(group); +} + +static bool unrefgroup(uint32_t *group) { + if (group == &static_refcount) { + return false; + } else { + return atomic_dec(group); + } +} + /* Reference tracking (debug only) ********************************************/ @@ -82,7 +102,7 @@ typedef struct { bool is_ref2; } trackedref; -trackedref *trackedref_new(bool is_ref2) { +static trackedref *trackedref_new(bool is_ref2) { trackedref *ret = malloc(sizeof(*ret)); CHECK_OOM(ret); ret->count = 1; @@ -319,20 +339,20 @@ UPB_NORETURN static void oom(tarjan *t) { err(t); } -uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) { +static uint64_t trygetattr(const tarjan *t, const upb_refcounted *r) { upb_value v; return upb_inttable_lookupptr(&t->objattr, r, &v) ? upb_value_getuint64(v) : 0; } -uint64_t getattr(const tarjan *t, const upb_refcounted *r) { +static uint64_t getattr(const tarjan *t, const upb_refcounted *r) { upb_value v; bool found = upb_inttable_lookupptr(&t->objattr, r, &v); UPB_ASSERT_VAR(found, found); return upb_value_getuint64(v); } -void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) { +static void setattr(tarjan *t, const upb_refcounted *r, uint64_t attr) { upb_inttable_removeptr(&t->objattr, r, NULL); upb_inttable_insertptr(&t->objattr, r, upb_value_uint64(attr)); } @@ -400,7 +420,7 @@ static void set_lowlink(tarjan *t, const upb_refcounted *r, uint32_t lowlink) { setattr(t, r, ((uint64_t)lowlink << 33) | (getattr(t, r) & 0x1FFFFFFFF)); } -uint32_t *group(tarjan *t, upb_refcounted *r) { +static uint32_t *group(tarjan *t, upb_refcounted *r) { assert(color(t, r) == WHITE); uint64_t groupnum = getattr(t, r) >> 8; upb_value v; @@ -480,7 +500,7 @@ static void crossref(const upb_refcounted *r, const upb_refcounted *subobj, if (color(t, subobj) > BLACK && r->group != subobj->group) { // Previously this ref was not reflected in subobj->group because they // were in the same group; now that they are split a ref must be taken. - atomic_inc(subobj->group); + refgroup(subobj->group); } } @@ -668,7 +688,7 @@ static void release_ref2(const upb_refcounted *obj, } static void unref(const upb_refcounted *r) { - if (atomic_dec(r->group)) { + if (unrefgroup(r->group)) { free(r->group); // In two passes, since release_ref2 needs a guarantee that any subobjs @@ -720,7 +740,7 @@ void upb_refcounted_ref(const upb_refcounted *r, const void *owner) { track(r, owner, false); if (!r->is_frozen) ((upb_refcounted*)r)->individual_count++; - atomic_inc(r->group); + refgroup(r->group); } void upb_refcounted_unref(const upb_refcounted *r, const void *owner) { @@ -734,7 +754,7 @@ void upb_refcounted_ref2(const upb_refcounted *r, upb_refcounted *from) { assert(!from->is_frozen); // Non-const pointer implies this. track(r, from, true); if (r->is_frozen) { - atomic_inc(r->group); + refgroup(r->group); } else { merge((upb_refcounted*)r, from); } @@ -753,8 +773,8 @@ void upb_refcounted_unref2(const upb_refcounted *r, upb_refcounted *from) { void upb_refcounted_donateref( const upb_refcounted *r, const void *from, const void *to) { assert(from != to); - assert(to != NULL); - upb_refcounted_ref(r, to); + if (to != NULL) + upb_refcounted_ref(r, to); if (from != NULL) upb_refcounted_unref(r, from); } diff --git a/upb/shim/shim.c b/upb/shim/shim.c index 797a2d1..02da85d 100644 --- a/upb/shim/shim.c +++ b/upb/shim/shim.c @@ -37,8 +37,9 @@ bool upb_shim_set(upb_handlers *h, const upb_fielddef *f, size_t offset, d->hasbit = hasbit; upb_handlerattr attr = UPB_HANDLERATTR_INITIALIZER; - upb_handlerattr_sethandlerdata(&attr, d, free); + upb_handlerattr_sethandlerdata(&attr, d); upb_handlerattr_setalwaysok(&attr, true); + upb_handlers_addcleanup(h, d, free); #define TYPE(u, l) \ case UPB_TYPE_##u: \ @@ -476,6 +476,11 @@ inline bool Sink::EndSequence(Handlers::Selector sel) { } template <class T> +BytesSink::BytesSink(const BytesHandler* handler, T* closure) { + Reset(handler, closure); +} + +template <class T> void BytesSink::Reset(const BytesHandler *handler, T *closure) { upb_bytessink_reset(this, handler, closure); } diff --git a/upb/symtab.c b/upb/symtab.c index 099aa8d..0269618 100644 --- a/upb/symtab.c +++ b/upb/symtab.c @@ -52,47 +52,35 @@ upb_symtab *upb_symtab_new(const void *owner) { return s; } -const upb_def **upb_symtab_getdefs(const upb_symtab *s, upb_deftype_t type, - const void *owner, int *n) { - int total = upb_strtable_count(&s->symtab); - // We may only use part of this, depending on how many symbols are of the - // correct type. - const upb_def **defs = malloc(sizeof(*defs) * total); - upb_strtable_iter iter; - upb_strtable_begin(&iter, &s->symtab); - int i = 0; - for(; !upb_strtable_done(&iter); upb_strtable_next(&iter)) { - upb_def *def = upb_value_getptr(upb_strtable_iter_value(&iter)); - assert(def); - if(type == UPB_DEF_ANY || def->type == type) - defs[i++] = def; - } - *n = i; - if (owner) - for(i = 0; i < *n; i++) upb_def_ref(defs[i], owner); - return defs; +void upb_symtab_freeze(upb_symtab *s) { + assert(!upb_symtab_isfrozen(s)); + upb_refcounted *r = UPB_UPCAST(s); + // The symtab does not take ref2's (see refcounted.h) on the defs, because + // defs cannot refer back to the table and therefore cannot create cycles. So + // 0 will suffice for maxdepth here. + bool ok = upb_refcounted_freeze(&r, 1, NULL, 0); + UPB_ASSERT_VAR(ok, ok); } -const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym, - const void *owner) { +const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym) { upb_value v; upb_def *ret = upb_strtable_lookup(&s->symtab, sym, &v) ? upb_value_getptr(v) : NULL; - if (ret) upb_def_ref(ret, owner); return ret; } -const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym, - const void *owner) { +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym) { upb_value v; upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? upb_value_getptr(v) : NULL; - upb_msgdef *ret = NULL; - if(def && def->type == UPB_DEF_MSG) { - ret = upb_downcast_msgdef_mutable(def); - upb_def_ref(def, owner); - } - return ret; + return def ? upb_dyncast_msgdef(def) : NULL; +} + +const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym) { + upb_value v; + upb_def *def = upb_strtable_lookup(&s->symtab, sym, &v) ? + upb_value_getptr(v) : NULL; + return def ? upb_dyncast_enumdef(def) : NULL; } // Given a symbol and the base symbol inside which it is defined, find the @@ -115,9 +103,8 @@ static upb_def *upb_resolvename(const upb_strtable *t, } const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, - const char *sym, const void *owner) { + const char *sym) { upb_def *ret = upb_resolvename(&s->symtab, base, sym); - if (ret) upb_def_ref(ret, owner); return ret; } @@ -192,6 +179,7 @@ oom: // The came_from_user stuff in particular is not tested. bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, upb_status *status) { + assert(!upb_symtab_isfrozen(s)); upb_def **add_defs = NULL; upb_strtable addtab; if (!upb_strtable_init(&addtab, UPB_CTYPE_PTR)) { @@ -262,7 +250,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, m = upb_value_getptr(v); } else { // Need to find and dup the extendee from the existing symtab. - const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname, &frozen_m); + const upb_msgdef *frozen_m = upb_symtab_lookupmsg(s, msgname); if (!frozen_m) { upb_status_seterrf(status, "Tried to extend message %s that does not exist " @@ -271,7 +259,6 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, goto err; } m = upb_msgdef_dup(frozen_m, s); - upb_msgdef_unref(frozen_m, &frozen_m); if (!m) goto oom_err; if (!upb_strtable_insert(&addtab, msgname, upb_value_ptr(m))) { upb_msgdef_unref(m, s); @@ -310,7 +297,7 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, for(upb_msg_begin(&j, m); !upb_msg_done(&j); upb_msg_next(&j)) { upb_fielddef *f = upb_msg_iter_field(&j); const char *name = upb_fielddef_subdefname(f); - if (name) { + if (name && !upb_fielddef_subdef(f)) { upb_def *subdef = upb_resolvename(&addtab, base, name); if (subdef == NULL) { upb_status_seterrf( @@ -320,10 +307,6 @@ bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, goto err; } } - - if (!upb_fielddef_resolveenumdefault(f, status)) { - goto err; - } } } @@ -380,3 +363,35 @@ err: { assert(!upb_ok(status)); return false; } + +// Iteration. + +static void advance_to_matching(upb_symtab_iter *iter) { + if (iter->type == UPB_DEF_ANY) + return; + + while (!upb_strtable_done(&iter->iter) && + iter->type != upb_symtab_iter_def(iter)->type) { + upb_strtable_next(&iter->iter); + } +} + +void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, + upb_deftype_t type) { + upb_strtable_begin(&iter->iter, &s->symtab); + iter->type = type; + advance_to_matching(iter); +} + +void upb_symtab_next(upb_symtab_iter *iter) { + upb_strtable_next(&iter->iter); + advance_to_matching(iter); +} + +bool upb_symtab_done(const upb_symtab_iter *iter) { + return upb_strtable_done(&iter->iter); +} + +const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter) { + return upb_value_getptr(upb_strtable_iter_value(&iter->iter)); +} diff --git a/upb/symtab.h b/upb/symtab.h index c260671..f2baeb7 100644 --- a/upb/symtab.h +++ b/upb/symtab.h @@ -28,8 +28,14 @@ typedef struct upb_symtab upb_symtab; #include "upb/def.h" +typedef struct { + upb_strtable_iter iter; + upb_deftype_t type; +} upb_symtab_iter; + #ifdef __cplusplus +// Non-const methods in upb::SymbolTable are NOT thread-safe. class upb::SymbolTable { public: // Returns a new symbol table with a single ref owned by "owner." @@ -43,6 +49,21 @@ class upb::SymbolTable { void DonateRef(const void *from, const void *to) const; void CheckRef(const void *owner) const; + // For all lookup functions, the returned pointer is not owned by the + // caller; it may be invalidated by any non-const call or unref of the + // SymbolTable! To protect against this, take a ref if desired. + + // Freezes the symbol table: prevents further modification of it. + // After the Freeze() operation is successful, the SymbolTable must only be + // accessed via a const pointer. + // + // Unlike with upb::MessageDef/upb::EnumDef/etc, freezing a SymbolTable is not + // a necessary step in using a SymbolTable. If you have no need for it to be + // immutable, there is no need to freeze it ever. However sometimes it is + // useful, and SymbolTables that are statically compiled into the binary are + // always frozen by nature. + void Freeze(); + // Resolves the given symbol using the rules described in descriptor.proto, // namely: // @@ -52,19 +73,17 @@ class upb::SymbolTable { // to the root namespace). // // If not found, returns NULL. - reffed_ptr<const Def> Resolve(const char* base, const char* sym) const; + const Def* Resolve(const char* base, const char* sym) const; // Finds an entry in the symbol table with this exact name. If not found, // returns NULL. - reffed_ptr<const Def> Lookup(const char *sym) const; - reffed_ptr<const MessageDef> LookupMessage(const char *sym) const; + const Def* Lookup(const char *sym) const; + const MessageDef* LookupMessage(const char *sym) const; + const EnumDef* LookupEnum(const char *sym) const; - // Gets an array of pointers to all currently active defs in this symtab. - // The caller owns the returned array (which is of length *n) as well as a - // ref to each symbol inside (owned by owner). If type is UPB_DEF_ANY then - // defs of all types are returned, otherwise only defs of the required type - // are returned. - const Def** GetDefs(upb_deftype_t type, const void *owner, int *n) const; + // TODO: introduce a C++ iterator, but make it nice and templated so that if + // you ask for an iterator of MessageDef the iterated elements are strongly + // typed as MessageDef*. // Adds the given mutable defs to the symtab, resolving all symbols // (including enum default values) and finalizing the defs. Only one def per @@ -113,6 +132,9 @@ struct upb_symtab { upb_strtable symtab; }; +#define UPB_SYMTAB_INIT(symtab, refs, ref2s) \ + { UPB_REFCOUNT_INIT(refs, ref2s), symtab } + // Native C API. #ifdef __cplusplus extern "C" { @@ -126,17 +148,31 @@ void upb_symtab_donateref( void upb_symtab_checkref(const upb_symtab *s, const void *owner); upb_symtab *upb_symtab_new(const void *owner); +void upb_symtab_freeze(upb_symtab *s); const upb_def *upb_symtab_resolve(const upb_symtab *s, const char *base, - const char *sym, const void *owner); -const upb_def *upb_symtab_lookup( - const upb_symtab *s, const char *sym, const void *owner); -const upb_msgdef *upb_symtab_lookupmsg( - const upb_symtab *s, const char *sym, const void *owner); -const upb_def **upb_symtab_getdefs( - const upb_symtab *s, upb_deftype_t type, const void *owner, int *n); + const char *sym); +const upb_def *upb_symtab_lookup(const upb_symtab *s, const char *sym); +const upb_msgdef *upb_symtab_lookupmsg(const upb_symtab *s, const char *sym); +const upb_enumdef *upb_symtab_lookupenum(const upb_symtab *s, const char *sym); bool upb_symtab_add(upb_symtab *s, upb_def *const*defs, int n, void *ref_donor, upb_status *status); +// upb_symtab_iter i; +// for(upb_symtab_begin(&i, s, type); !upb_symtab_done(&i); +// upb_symtab_next(&i)) { +// const upb_def *def = upb_symtab_iter_def(&i); +// // ... +// } +// +// For C we don't have separate iterators for const and non-const. +// It is the caller's responsibility to cast the upb_fielddef* to +// const if the upb_msgdef* is const. +void upb_symtab_begin(upb_symtab_iter *iter, const upb_symtab *s, + upb_deftype_t type); +void upb_symtab_next(upb_symtab_iter *iter); +bool upb_symtab_done(const upb_symtab_iter *iter); +const upb_def *upb_symtab_iter_def(const upb_symtab_iter *iter); + #ifdef __cplusplus } /* extern "C" */ @@ -184,23 +220,18 @@ inline void SymbolTable::CheckRef(const void *owner) const { upb_symtab_checkref(this, owner); } -inline reffed_ptr<const Def> SymbolTable::Resolve( - const char* base, const char* sym) const { - const upb_def *def = upb_symtab_resolve(this, base, sym, &def); - return reffed_ptr<const Def>(def, &def); +inline void SymbolTable::Freeze() { + return upb_symtab_freeze(this); } -inline reffed_ptr<const Def> SymbolTable::Lookup(const char *sym) const { - const upb_def *def = upb_symtab_lookup(this, sym, &def); - return reffed_ptr<const Def>(def, &def); +inline const Def *SymbolTable::Resolve(const char *base, + const char *sym) const { + return upb_symtab_resolve(this, base, sym); } -inline reffed_ptr<const MessageDef> SymbolTable::LookupMessage( - const char *sym) const { - const upb_msgdef *m = upb_symtab_lookupmsg(this, sym, &m); - return reffed_ptr<const MessageDef>(m, &m); +inline const Def* SymbolTable::Lookup(const char *sym) const { + return upb_symtab_lookup(this, sym); } -inline const Def** SymbolTable::GetDefs( - upb_deftype_t type, const void *owner, int *n) const { - return upb_symtab_getdefs(this, type, owner, n); +inline const MessageDef *SymbolTable::LookupMessage(const char *sym) const { + return upb_symtab_lookupmsg(this, sym); } inline bool SymbolTable::Add( Def*const* defs, int n, void* ref_donor, upb_status* status) { diff --git a/upb/table.c b/upb/table.c index 0b43fd9..c7d2a9d 100644 --- a/upb/table.c +++ b/upb/table.c @@ -186,16 +186,17 @@ static bool rm(upb_table *t, upb_tabkey key, upb_value *val, } } -static const upb_tabent *next(const upb_table *t, const upb_tabent *e) { - const upb_tabent *end = t->entries + upb_table_size(t); - do { if (++e == end) return NULL; } while(e->key.num == 0); - return e; +static size_t next(const upb_table *t, size_t i) { + do { + if (++i >= upb_table_size(t)) + return SIZE_MAX; + } while(upb_tabent_isempty(&t->entries[i])); + + return i; } -// TODO: is calculating t->entries - 1 undefined behavior? If so find a better -// solution. -static const upb_tabent *begin(const upb_table *t) { - return next(t, t->entries - 1); +static size_t begin(const upb_table *t) { + return next(t, -1); } @@ -222,20 +223,27 @@ void upb_strtable_uninit(upb_strtable *t) { uninit(&t->t); } +bool upb_strtable_resize(upb_strtable *t, size_t size_lg2) { + upb_strtable new_table; + if (!init(&new_table.t, t->t.ctype, size_lg2)) + return false; + upb_strtable_iter i; + upb_strtable_begin(&i, t); + for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { + upb_strtable_insert( + &new_table, upb_strtable_iter_key(&i), upb_strtable_iter_value(&i)); + } + upb_strtable_uninit(t); + *t = new_table; + return true; +} + bool upb_strtable_insert(upb_strtable *t, const char *k, upb_value v) { if (isfull(&t->t)) { // Need to resize. New table of double the size, add old elements to it. - upb_strtable new_table; - if (!init(&new_table.t, t->t.ctype, t->t.size_lg2 + 1)) + if (!upb_strtable_resize(t, t->t.size_lg2 + 1)) { return false; - upb_strtable_iter i; - upb_strtable_begin(&i, t); - for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) { - upb_strtable_insert( - &new_table, upb_strtable_iter_key(&i), upb_strtable_iter_value(&i)); } - upb_strtable_uninit(t); - *t = new_table; } if ((k = upb_strdup(k)) == NULL) return false; insert(&t->t, strkey(k), v, &strhash, &streql); @@ -256,13 +264,45 @@ bool upb_strtable_remove(upb_strtable *t, const char *key, upb_value *val) { } } +// Iteration + +static const upb_tabent *str_tabent(const upb_strtable_iter *i) { + return &i->t->t.entries[i->index]; +} + void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t) { i->t = t; - i->e = begin(&t->t); + i->index = begin(&t->t); } void upb_strtable_next(upb_strtable_iter *i) { - i->e = next(&i->t->t, i->e); + i->index = next(&i->t->t, i->index); +} + +bool upb_strtable_done(const upb_strtable_iter *i) { + return i->index >= upb_table_size(&i->t->t) || + upb_tabent_isempty(str_tabent(i)); +} + +const char *upb_strtable_iter_key(upb_strtable_iter *i) { + assert(!upb_strtable_done(i)); + return str_tabent(i)->key.str; +} + +upb_value upb_strtable_iter_value(const upb_strtable_iter *i) { + assert(!upb_strtable_done(i)); + return _upb_value_val(str_tabent(i)->val, i->t->t.ctype); +} + +void upb_strtable_iter_setdone(upb_strtable_iter *i) { + i->index = SIZE_MAX; +} + +bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, + const upb_strtable_iter *i2) { + if (upb_strtable_done(i1) && upb_strtable_done(i2)) + return true; + return i1->t == i2->t && i1->index == i2->index; } @@ -347,8 +387,9 @@ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val) { upb_table new_table; if (!init(&new_table, t->t.ctype, t->t.size_lg2 + 1)) return false; - const upb_tabent *e; - for (e = begin(&t->t); e; e = next(&t->t, e)) { + size_t i; + for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) { + const upb_tabent *e = &t->t.entries[i]; upb_value v; _upb_value_setval(&v, e->val, t->t.ctype); insert(&new_table, e->key, v, &upb_inthash, &inteql); @@ -479,9 +520,21 @@ void upb_inttable_compact(upb_inttable *t) { *t = new_t; } +// Iteration. + +static const upb_tabent *int_tabent(const upb_inttable_iter *i) { + assert(!i->array_part); + return &i->t->t.entries[i->index]; +} + +static _upb_value int_arrent(const upb_inttable_iter *i) { + assert(i->array_part); + return i->t->array[i->index]; +} + void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) { i->t = t; - i->arrkey = -1; + i->index = -1; i->array_part = true; upb_inttable_next(i); } @@ -489,16 +542,51 @@ void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t) { void upb_inttable_next(upb_inttable_iter *iter) { const upb_inttable *t = iter->t; if (iter->array_part) { - for (size_t i = iter->arrkey; ++i < t->array_size; ) - if (upb_arrhas(t->array[i])) { - iter->ptr.val = &t->array[i]; - iter->arrkey = i; + while (++iter->index < t->array_size) { + if (upb_arrhas(int_arrent(iter))) { return; } + } iter->array_part = false; - iter->ptr.ent = t->t.entries - 1; + iter->index = begin(&t->t); + } else { + iter->index = next(&t->t, iter->index); + } +} + +bool upb_inttable_done(const upb_inttable_iter *i) { + if (i->array_part) { + return i->index >= i->t->array_size || + !upb_arrhas(int_arrent(i)); + } else { + return i->index >= upb_table_size(&i->t->t) || + upb_tabent_isempty(int_tabent(i)); } - iter->ptr.ent = next(&t->t, iter->ptr.ent); +} + +uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { + assert(!upb_inttable_done(i)); + return i->array_part ? i->index : int_tabent(i)->key.num; +} + +upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { + assert(!upb_inttable_done(i)); + return _upb_value_val( + i->array_part ? i->t->array[i->index] : int_tabent(i)->val, + i->t->t.ctype); +} + +void upb_inttable_iter_setdone(upb_inttable_iter *i) { + i->index = SIZE_MAX; + i->array_part = false; +} + +bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, + const upb_inttable_iter *i2) { + if (upb_inttable_done(i1) && upb_inttable_done(i2)) + return true; + return i1->t == i2->t && i1->index == i2->index && + i1->array_part == i2->array_part; } #ifdef UPB_UNALIGNED_READS_OK diff --git a/upb/table.int.h b/upb/table.int.h index 109f76b..395ab7a 100644 --- a/upb/table.int.h +++ b/upb/table.int.h @@ -46,6 +46,7 @@ typedef enum { UPB_CTYPE_CSTR = 6, UPB_CTYPE_PTR = 7, UPB_CTYPE_CONSTPTR = 8, + UPB_CTYPE_FPTR = 9, } upb_ctype_t; typedef union { @@ -57,6 +58,7 @@ typedef union { char *cstr; void *ptr; const void *constptr; + upb_func *fptr; } _upb_value; typedef struct { @@ -90,6 +92,7 @@ typedef struct { #define UPB_VALUE_INIT_CSTR(v) UPB_VALUE_INIT(v, cstr) #define UPB_VALUE_INIT_PTR(v) UPB_VALUE_INIT(v, ptr) #define UPB_VALUE_INIT_CONSTPTR(v) UPB_VALUE_INIT(v, constptr) +#define UPB_VALUE_INIT_FPTR(v) UPB_VALUE_INIT(v, fptr) // Like strdup(), which isn't always available since it's not ANSI C. char *upb_strdup(const char *s); @@ -138,6 +141,7 @@ FUNCS(bool, _bool, bool, UPB_CTYPE_BOOL); FUNCS(cstr, cstr, char*, UPB_CTYPE_CSTR); FUNCS(ptr, ptr, void*, UPB_CTYPE_PTR); FUNCS(constptr, constptr, const void*, UPB_CTYPE_CONSTPTR); +FUNCS(fptr, fptr, upb_func*, UPB_CTYPE_FPTR); #undef FUNCS @@ -302,10 +306,35 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, } } +// Exposed for testing only. +bool upb_strtable_resize(upb_strtable *t, size_t size_lg2); + +/* Iterators ******************************************************************/ + +// Iterators for int and string tables. We are subject to some kind of unusual +// design constraints: +// +// For high-level languages: +// - we must be able to guarantee that we don't crash or corrupt memory even if +// the program accesses an invalidated iterator. +// +// For C++11 range-based for: +// - iterators must be copyable +// - iterators must be comparable +// - it must be possible to construct an "end" value. +// +// Iteration order is undefined. +// +// Modifying the table invalidates iterators. upb_{str,int}table_done() is +// guaranteed to work even on an invalidated iterator, as long as the table it +// is iterating over has not been freed. Calling next() or accessing data from +// an invalidated iterator yields unspecified elements from the table, but it is +// guaranteed not to crash and to return real table elements (except when done() +// is true). + /* upb_strtable_iter **********************************************************/ -// Strtable iteration. Order is undefined. Insertions invalidate iterators. // upb_strtable_iter i; // upb_strtable_begin(&i, t); // for(; !upb_strtable_done(&i); upb_strtable_next(&i)) { @@ -313,36 +342,24 @@ UPB_INLINE bool upb_inttable_lookup32(const upb_inttable *t, uint32_t key, // const upb_value val = upb_strtable_iter_value(&i); // // ... // } + typedef struct { const upb_strtable *t; - const upb_tabent *e; + size_t index; } upb_strtable_iter; void upb_strtable_begin(upb_strtable_iter *i, const upb_strtable *t); void upb_strtable_next(upb_strtable_iter *i); -UPB_INLINE bool upb_strtable_done(upb_strtable_iter *i) { return i->e == NULL; } -UPB_INLINE const char *upb_strtable_iter_key(upb_strtable_iter *i) { - return i->e->key.str; -} -UPB_INLINE upb_value upb_strtable_iter_value(upb_strtable_iter *i) { - return _upb_value_val(i->e->val, i->t->t.ctype); -} -UPB_INLINE void upb_strtable_iter_copy(upb_strtable_iter *to, - const upb_strtable_iter *from) { - *to = *from; -} -UPB_INLINE void upb_strtable_iter_setdone(upb_strtable_iter *i) { - i->e = NULL; -} -UPB_INLINE bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, - const upb_strtable_iter *i2) { - return i1->e == i2->e; -} +bool upb_strtable_done(const upb_strtable_iter *i); +const char *upb_strtable_iter_key(upb_strtable_iter *i); +upb_value upb_strtable_iter_value(const upb_strtable_iter *i); +void upb_strtable_iter_setdone(upb_strtable_iter *i); +bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, + const upb_strtable_iter *i2); /* upb_inttable_iter **********************************************************/ -// Inttable iteration. Order is undefined. Insertions invalidate iterators. // upb_inttable_iter i; // upb_inttable_begin(&i, t); // for(; !upb_inttable_done(&i); upb_inttable_next(&i)) { @@ -350,39 +367,22 @@ UPB_INLINE bool upb_strtable_iter_isequal(const upb_strtable_iter *i1, // upb_value val = upb_inttable_iter_value(&i); // // ... // } + typedef struct { const upb_inttable *t; - union { - const upb_tabent *ent; // For hash iteration. - const _upb_value *val; // For array iteration. - } ptr; - uintptr_t arrkey; + size_t index; bool array_part; } upb_inttable_iter; void upb_inttable_begin(upb_inttable_iter *i, const upb_inttable *t); void upb_inttable_next(upb_inttable_iter *i); -UPB_INLINE bool upb_inttable_done(const upb_inttable_iter *i) { - return i->ptr.ent == NULL; -} -UPB_INLINE uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i) { - return i->array_part ? i->arrkey : i->ptr.ent->key.num; -} -UPB_INLINE upb_value upb_inttable_iter_value(const upb_inttable_iter *i) { - return _upb_value_val( - i->array_part ? *i->ptr.val : i->ptr.ent->val, i->t->t.ctype); -} -UPB_INLINE void upb_inttable_iter_copy(upb_inttable_iter *to, - const upb_inttable_iter *from) { - *to = *from; -} -UPB_INLINE void upb_inttable_iter_setdone(upb_inttable_iter *i) { - i->ptr.ent = NULL; -} -UPB_INLINE bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, - const upb_inttable_iter *i2) { - return i1->ptr.ent == i2->ptr.ent; -} +bool upb_inttable_done(const upb_inttable_iter *i); +uintptr_t upb_inttable_iter_key(const upb_inttable_iter *i); +upb_value upb_inttable_iter_value(const upb_inttable_iter *i); +void upb_inttable_iter_setdone(upb_inttable_iter *i); +bool upb_inttable_iter_isequal(const upb_inttable_iter *i1, + const upb_inttable_iter *i2); + #ifdef __cplusplus } /* extern "C" */ @@ -80,6 +80,8 @@ // debug mode. #define UPB_ASSERT_VAR(var, predicate) UPB_UNUSED(var); assert(predicate) +// Generic function type. +typedef void upb_func(); /* Casts **********************************************************************/ |