M bench/baseline.json => bench/baseline.json +49 -28
@@ 1,35 1,56 @@
{
- "schema_message": "hello.Person",
- "results": [
+ "schemas": [
{
- "size_label": "10B",
- "size_bytes": 10,
- "encode": {"alloc_kb_per_op_full": 0.367, "alloc_kb_per_op_runtime": 0.633},
- "decode": {"alloc_kb_per_op_full": 0.508, "alloc_kb_per_op_runtime": 0.508}
+ "schema": "hello.Person",
+ "results": [
+ {
+ "size_label": "10B",
+ "size_bytes": 10,
+ "encode": {"alloc_kb_per_op_full": 0.133, "alloc_kb_per_op_runtime": 0.133},
+ "decode": {"alloc_kb_per_op_full": 0.109, "alloc_kb_per_op_runtime": 0.109}
+ },
+ {
+ "size_label": "100B",
+ "size_bytes": 94,
+ "encode": {"alloc_kb_per_op_full": 0.133, "alloc_kb_per_op_runtime": 0.133},
+ "decode": {"alloc_kb_per_op_full": 0.109, "alloc_kb_per_op_runtime": 0.109}
+ },
+ {
+ "size_label": "1KB",
+ "size_bytes": 930,
+ "encode": {"alloc_kb_per_op_full": 1.336, "alloc_kb_per_op_runtime": 1.336},
+ "decode": {"alloc_kb_per_op_full": 0.977, "alloc_kb_per_op_runtime": 0.977}
+ },
+ {
+ "size_label": "10KB",
+ "size_bytes": 9634,
+ "encode": {"alloc_kb_per_op_full": 8.340, "alloc_kb_per_op_runtime": 8.340},
+ "decode": {"alloc_kb_per_op_full": 4.727, "alloc_kb_per_op_runtime": 4.727}
+ },
+ {
+ "size_label": "100KB",
+ "size_bytes": 96674,
+ "encode": {"alloc_kb_per_op_full": 128.521, "alloc_kb_per_op_runtime": 128.521},
+ "decode": {"alloc_kb_per_op_full": 32.727, "alloc_kb_per_op_runtime": 32.727}
+ }
+ ]
},
{
- "size_label": "100B",
- "size_bytes": 94,
- "encode": {"alloc_kb_per_op_full": 0.367, "alloc_kb_per_op_runtime": 0.633},
- "decode": {"alloc_kb_per_op_full": 0.508, "alloc_kb_per_op_runtime": 0.508}
- },
- {
- "size_label": "1KB",
- "size_bytes": 930,
- "encode": {"alloc_kb_per_op_full": 5.978, "alloc_kb_per_op_runtime": 7.040},
- "decode": {"alloc_kb_per_op_full": 7.750, "alloc_kb_per_op_runtime": 7.883}
- },
- {
- "size_label": "10KB",
- "size_bytes": 9634,
- "encode": {"alloc_kb_per_op_full": 47.489, "alloc_kb_per_op_runtime": 48.551},
- "decode": {"alloc_kb_per_op_full": 59.500, "alloc_kb_per_op_runtime": 59.633}
- },
- {
- "size_label": "100KB",
- "size_bytes": 96674,
- "encode": {"alloc_kb_per_op_full": 444.126, "alloc_kb_per_op_runtime": 445.189},
- "decode": {"alloc_kb_per_op_full": 567.500, "alloc_kb_per_op_runtime": 567.633}
+ "schema": "proto2_basic.BenchPayload",
+ "results": [
+ {
+ "size_label": "min",
+ "size_bytes": 5,
+ "encode": {"alloc_kb_per_op_full": 0.102, "alloc_kb_per_op_runtime": 0.102},
+ "decode": {"alloc_kb_per_op_full": 0.359, "alloc_kb_per_op_runtime": 0.359}
+ },
+ {
+ "size_label": "mid",
+ "size_bytes": 609,
+ "encode": {"alloc_kb_per_op_full": 1.438, "alloc_kb_per_op_runtime": 1.438},
+ "decode": {"alloc_kb_per_op_full": 2.313, "alloc_kb_per_op_runtime": 2.313}
+ }
+ ]
}
]
}
M bench/bench.lua => bench/bench.lua +193 -84
@@ 22,20 22,30 @@ local json = require('json')
local fio = require('fio')
local MODES = {'full', 'runtime'}
-local SIZES = {
+
+-- Per-fixture size lists. The proto3 Person fixture sweeps five decades to
+-- characterize behavior across allocation regimes; proto2 only needs two
+-- sizes (one fits-in-cache, one larger) because its purpose is to gate
+-- the proto2-specific shapes (required/group/extension), not to recharacterize
+-- alloc scaling — that's already covered by Person.
+local PERSON_SIZES = {
{label = '10B', target = 10},
{label = '100B', target = 100},
{label = '1KB', target = 1024},
{label = '10KB', target = 10240},
{label = '100KB', target = 102400},
}
+local PROTO2_SIZES = {
+ {label = 'min', target = 0}, -- minimal: required + extension only
+ {label = 'mid', target = 1024}, -- with group + repeated + extension
+}
-- Build a `Person` payload whose encoded size is close to `target` bytes.
--
-- Strategy: pick one knob per decade so each size still exercises the
-- full encoder (varints, packed repeated, length-delimited strings,
-- nested messages) — not just one giant byte-string.
-local function build_payload(target)
+local function build_person_payload(target)
if target <= 10 then
-- name(6) + age(1) ⇒ 10 bytes encoded.
return {name = 'bigbes', age = 42}
@@ 65,6 75,65 @@ local function build_payload(target)
return p
end
+-- Build a `BenchPayload` proto2 message. Two sizes:
+-- * `min` — required + one extension (~12 bytes): tightest measure of the
+-- per-message overhead the new code paths add.
+-- * `mid` — required + group + repeated + extension (~1 KB): exercises
+-- SGROUP/EGROUP framing, the packed-int32 path under proto2 semantics
+-- (NOT packed unless explicitly marked), the `pairs`-free
+-- extensions_list walk, and the nested message branch.
+local function build_proto2_payload(target)
+ if target <= 0 then
+ return {
+ id = 7,
+ _extensions = {
+ ['proto2_basic.ext_count'] = 42,
+ },
+ }
+ end
+ local n_tags = 16
+ local per_tag = 30
+ local tags = {}
+ for i = 1, n_tags do
+ tags[i] = string.rep('t', per_tag - 2) .. string.format('%02d', i)
+ end
+ local lucky = {}
+ for i = 1, 8 do lucky[i] = 1000 + i end
+ return {
+ id = 7,
+ name = 'bench',
+ retries = 9,
+ lucky_numbers = lucky,
+ tags = tags,
+ inner = {key = string.rep('k', 16), weight = 3},
+ stats = {latency_ns = 1234567, attempts = 4},
+ _extensions = {
+ ['proto2_basic.ext_count'] = 99,
+ ['proto2_basic.ext_label'] = string.rep('x', 32),
+ },
+ }
+end
+
+-- Each fixture binds a schema + payload builder + sizes to bench.
+local FIXTURES = {
+ {
+ name = 'hello.Person',
+ module_path = '.hello.hello_pb',
+ encode_field = 'Person_encode',
+ decode_field = 'Person_decode',
+ build_payload = build_person_payload,
+ sizes = PERSON_SIZES,
+ },
+ {
+ name = 'proto2_basic.BenchPayload',
+ module_path = '.proto2_basic.proto2_basic_pb',
+ encode_field = 'BenchPayload_encode',
+ decode_field = 'BenchPayload_decode',
+ build_payload = build_proto2_payload,
+ sizes = PROTO2_SIZES,
+ },
+}
+
-- Pick iteration count adaptively: smaller messages need more iters to
-- amortize loop + clock overhead; larger messages need fewer to keep
-- wall time bounded.
@@ 142,12 211,12 @@ local function bench_alloc(fn, expected_bytes)
}
end
-local function bench_one(mode, size)
- local hello_pb = require(mode .. '.hello.hello_pb')
- local encode = hello_pb.Person_encode
- local decode = hello_pb.Person_decode
+local function bench_one(fixture, mode, size)
+ local mod = require(mode .. fixture.module_path)
+ local encode = mod[fixture.encode_field]
+ local decode = mod[fixture.decode_field]
- local payload = build_payload(size.target)
+ local payload = fixture.build_payload(size.target)
local bytes = encode(payload)
local n = iter_count(#bytes)
local runs = 5
@@ 168,6 237,7 @@ local function bench_one(mode, size)
dec_throughput.alloc_bytes_per_op = dec_alloc.bytes_per_op
return {
+ schema = fixture.name,
mode = mode,
size_label = size.label,
size_bytes = #bytes,
@@ 177,24 247,28 @@ local function bench_one(mode, size)
end
local function run_all()
- local results = {}
- for _, mode in ipairs(MODES) do
- for _, size in ipairs(SIZES) do
- io.stderr:write(string.format(' bench %s/%s ... ', mode, size.label))
- io.stderr:flush()
- local r = bench_one(mode, size)
- io.stderr:write(string.format(
- 'enc %.0f msgs/s (%.1f MB/s) dec %.0f msgs/s (%.1f MB/s)\n',
- r.encode.msgs_per_s, r.encode.mb_per_s,
- r.decode.msgs_per_s, r.decode.mb_per_s))
- results[#results + 1] = r
+ local schemas = {}
+ for _, fixture in ipairs(FIXTURES) do
+ io.stderr:write(string.format('schema %s\n', fixture.name))
+ local results = {}
+ for _, mode in ipairs(MODES) do
+ for _, size in ipairs(fixture.sizes) do
+ io.stderr:write(string.format(' bench %s/%s ... ', mode, size.label))
+ io.stderr:flush()
+ local r = bench_one(fixture, mode, size)
+ io.stderr:write(string.format(
+ 'enc %.0f msgs/s (%.1f MB/s) dec %.0f msgs/s (%.1f MB/s)\n',
+ r.encode.msgs_per_s, r.encode.mb_per_s,
+ r.decode.msgs_per_s, r.decode.mb_per_s))
+ results[#results + 1] = r
+ end
end
+ schemas[#schemas + 1] = {schema = fixture.name, results = results}
end
return {
- tarantool = _TARANTOOL,
- jit = jit and jit.version or nil,
- schema_message = 'hello.Person',
- results = results,
+ tarantool = _TARANTOOL,
+ jit = jit and jit.version or nil,
+ schemas = schemas,
}
end
@@ 216,17 290,24 @@ local function render(doc)
lines[#lines + 1] = '{'
lines[#lines + 1] = string.format(' "tarantool": %s,', json.encode(doc.tarantool))
lines[#lines + 1] = string.format(' "jit": %s,', json.encode(doc.jit or json.NULL))
- lines[#lines + 1] = string.format(' "schema_message": %s,', json.encode(doc.schema_message))
- lines[#lines + 1] = ' "results": ['
- for i, r in ipairs(doc.results) do
- local sep = (i == #doc.results) and '' or ','
+ lines[#lines + 1] = ' "schemas": ['
+ for si, schema in ipairs(doc.schemas) do
+ local schema_sep = (si == #doc.schemas) and '' or ','
lines[#lines + 1] = ' {'
- lines[#lines + 1] = string.format(' "mode": %s,', json.encode(r.mode))
- lines[#lines + 1] = string.format(' "size_label": %s,', json.encode(r.size_label))
- lines[#lines + 1] = string.format(' "size_bytes": %d,', r.size_bytes)
- lines[#lines + 1] = string.format(' "encode": %s,', render_metric(r.encode))
- lines[#lines + 1] = string.format(' "decode": %s', render_metric(r.decode))
- lines[#lines + 1] = ' }' .. sep
+ lines[#lines + 1] = string.format(' "schema": %s,', json.encode(schema.schema))
+ lines[#lines + 1] = ' "results": ['
+ for i, r in ipairs(schema.results) do
+ local sep = (i == #schema.results) and '' or ','
+ lines[#lines + 1] = ' {'
+ lines[#lines + 1] = string.format(' "mode": %s,', json.encode(r.mode))
+ lines[#lines + 1] = string.format(' "size_label": %s,', json.encode(r.size_label))
+ lines[#lines + 1] = string.format(' "size_bytes": %d,', r.size_bytes)
+ lines[#lines + 1] = string.format(' "encode": %s,', render_metric(r.encode))
+ lines[#lines + 1] = string.format(' "decode": %s', render_metric(r.decode))
+ lines[#lines + 1] = ' }' .. sep
+ end
+ lines[#lines + 1] = ' ]'
+ lines[#lines + 1] = ' }' .. schema_sep
end
lines[#lines + 1] = ' ]'
lines[#lines + 1] = '}'
@@ 239,50 320,69 @@ end
-- bytes, not time — so that's all we commit. Throughput is in --print
-- output for human inspection only.
local function reduce_for_baseline(doc)
- local by_key = {}
- for _, r in ipairs(doc.results) do
- by_key[r.mode .. '/' .. r.size_label] = r
- end
- local out = {}
- for _, size in ipairs(SIZES) do
- local full = by_key['full/' .. size.label]
- local runtime = by_key['runtime/' .. size.label]
- out[#out + 1] = {
- size_label = size.label,
- size_bytes = full.size_bytes,
- encode = {
- alloc_kb_per_op_full = full.encode.alloc_kb_per_op,
- alloc_kb_per_op_runtime = runtime.encode.alloc_kb_per_op,
- },
- decode = {
- alloc_kb_per_op_full = full.decode.alloc_kb_per_op,
- alloc_kb_per_op_runtime = runtime.decode.alloc_kb_per_op,
- },
- }
+ local out_schemas = {}
+ for _, schema in ipairs(doc.schemas) do
+ local by_key = {}
+ for _, r in ipairs(schema.results) do
+ by_key[r.mode .. '/' .. r.size_label] = r
+ end
+ -- Recover size order from the first mode's run (declaration order).
+ local seen, sizes = {}, {}
+ for _, r in ipairs(schema.results) do
+ if not seen[r.size_label] then
+ seen[r.size_label] = true
+ sizes[#sizes + 1] = r.size_label
+ end
+ end
+ local results = {}
+ for _, label in ipairs(sizes) do
+ local full = by_key['full/' .. label]
+ local runtime = by_key['runtime/' .. label]
+ results[#results + 1] = {
+ size_label = label,
+ size_bytes = full.size_bytes,
+ encode = {
+ alloc_kb_per_op_full = full.encode.alloc_kb_per_op,
+ alloc_kb_per_op_runtime = runtime.encode.alloc_kb_per_op,
+ },
+ decode = {
+ alloc_kb_per_op_full = full.decode.alloc_kb_per_op,
+ alloc_kb_per_op_runtime = runtime.decode.alloc_kb_per_op,
+ },
+ }
+ end
+ out_schemas[#out_schemas + 1] = {schema = schema.schema, results = results}
end
- return {schema_message = doc.schema_message, results = out}
+ return {schemas = out_schemas}
end
local function render_baseline(reduced)
local lines = {'{'}
- lines[#lines + 1] = string.format(' "schema_message": %s,', json.encode(reduced.schema_message))
- lines[#lines + 1] = ' "results": ['
- for i, r in ipairs(reduced.results) do
- local sep = (i == #reduced.results) and '' or ','
+ lines[#lines + 1] = ' "schemas": ['
+ for si, schema in ipairs(reduced.schemas) do
+ local schema_sep = (si == #reduced.schemas) and '' or ','
lines[#lines + 1] = ' {'
- lines[#lines + 1] = string.format(' "size_label": %s,', json.encode(r.size_label))
- lines[#lines + 1] = string.format(' "size_bytes": %d,', r.size_bytes)
- lines[#lines + 1] = string.format(
- ' "encode": {"alloc_kb_per_op_full": %.3f, '
- .. '"alloc_kb_per_op_runtime": %.3f},',
- r.encode.alloc_kb_per_op_full,
- r.encode.alloc_kb_per_op_runtime)
- lines[#lines + 1] = string.format(
- ' "decode": {"alloc_kb_per_op_full": %.3f, '
- .. '"alloc_kb_per_op_runtime": %.3f}',
- r.decode.alloc_kb_per_op_full,
- r.decode.alloc_kb_per_op_runtime)
- lines[#lines + 1] = ' }' .. sep
+ lines[#lines + 1] = string.format(' "schema": %s,', json.encode(schema.schema))
+ lines[#lines + 1] = ' "results": ['
+ for i, r in ipairs(schema.results) do
+ local sep = (i == #schema.results) and '' or ','
+ lines[#lines + 1] = ' {'
+ lines[#lines + 1] = string.format(' "size_label": %s,', json.encode(r.size_label))
+ lines[#lines + 1] = string.format(' "size_bytes": %d,', r.size_bytes)
+ lines[#lines + 1] = string.format(
+ ' "encode": {"alloc_kb_per_op_full": %.3f, '
+ .. '"alloc_kb_per_op_runtime": %.3f},',
+ r.encode.alloc_kb_per_op_full,
+ r.encode.alloc_kb_per_op_runtime)
+ lines[#lines + 1] = string.format(
+ ' "decode": {"alloc_kb_per_op_full": %.3f, '
+ .. '"alloc_kb_per_op_runtime": %.3f}',
+ r.decode.alloc_kb_per_op_full,
+ r.decode.alloc_kb_per_op_runtime)
+ lines[#lines + 1] = ' }' .. sep
+ end
+ lines[#lines + 1] = ' ]'
+ lines[#lines + 1] = ' }' .. schema_sep
end
lines[#lines + 1] = ' ]'
lines[#lines + 1] = '}'
@@ 299,27 399,36 @@ end
local function compare(current, baseline, tolerance)
local function index(b)
local m = {}
- for _, r in ipairs(b.results) do m[r.size_label] = r end
+ for _, schema in ipairs(b.schemas or {}) do
+ for _, r in ipairs(schema.results) do
+ m[schema.schema .. '|' .. r.size_label] = r
+ end
+ end
return m
end
- local cur = index(current)
+ local cur = index(current)
local base = index(baseline)
local regressions = {}
- for _, size in ipairs(SIZES) do
- local c = cur[size.label]
- local b = base[size.label]
- if not c or not b then goto continue end
- for _, op in ipairs({'encode', 'decode'}) do
- for _, key in ipairs({'alloc_kb_per_op_full', 'alloc_kb_per_op_runtime'}) do
- local bv, cv = b[op][key], c[op][key]
- if bv > 0 and cv > bv * (1 + tolerance) then
- regressions[#regressions + 1] = string.format(
- '%s/%s %s: %.3f -> %.3f KB/op (+%.1f%%)',
- size.label, op, key, bv, cv, (cv / bv - 1) * 100)
+ -- Walk in baseline declaration order so the report is stable.
+ for _, schema in ipairs(baseline.schemas or {}) do
+ for _, r in ipairs(schema.results) do
+ local key = schema.schema .. '|' .. r.size_label
+ local c = cur[key]
+ local b = base[key]
+ if c and b then
+ for _, op in ipairs({'encode', 'decode'}) do
+ for _, ak in ipairs({'alloc_kb_per_op_full', 'alloc_kb_per_op_runtime'}) do
+ local bv, cv = b[op][ak], c[op][ak]
+ if bv > 0 and cv > bv * (1 + tolerance) then
+ regressions[#regressions + 1] = string.format(
+ '%s %s/%s %s: %.3f -> %.3f KB/op (+%.1f%%)',
+ schema.schema, r.size_label, op, ak,
+ bv, cv, (cv / bv - 1) * 100)
+ end
+ end
end
end
end
- ::continue::
end
return regressions
end
M bench/jit_trace.lua => bench/jit_trace.lua +70 -0
@@ 269,6 269,76 @@ for _, mode in ipairs({'full', 'runtime'}) do
function() hello.Person_decode(big_person_bytes) end)
end
+-- ---------------------------------------------------------------------------
+-- Proto2-specific shapes: required, groups, extensions, closed enums.
+--
+-- The new code paths share most of their machinery with proto3 message and
+-- scalar fields, but introduce three distinct shapes worth pinning:
+--
+-- 1. The `required` writer wraps the regular scalar writer with a missing-
+-- value error. Should stay JIT-stable when the value is set.
+-- 2. Group fields use SGROUP/EGROUP tags and a per-element body without a
+-- length prefix. Different wire shape than messages; new writer/reader.
+-- 3. Extensions are walked at encode time via a `pairs()` over an array
+-- view (`extensions_list`), and looked up at decode time via the
+-- `extensions_by_id` hash. Both sides need to stay on trace; the
+-- hash lookup is one cdata read so should be fine, but the encode
+-- walk would abort if we used `pairs()` over a non-array — see the
+-- list-view layer in pb.codec.
+-- ---------------------------------------------------------------------------
+
+for _, mode in ipairs({'full', 'runtime'}) do
+ local p2 = require(mode .. '.proto2_basic.proto2_basic_pb')
+
+ -- Required: encode emits a clear error on missing, but the happy path
+ -- where the value is set should compile and stay on trace.
+ local card = {r = 7}
+ local card_bytes = p2.Cardinality_encode(card)
+ check(mode .. '/Cardinality_encode (required)',
+ function() p2.Cardinality_encode(card) end)
+ check(mode .. '/Cardinality_decode (required)',
+ function() p2.Cardinality_decode(card_bytes) end)
+
+ -- Groups: SGROUP/EGROUP framed body, no length prefix. Singular path.
+ local with_group = {singlegroup = {a = 7, s = 'ok'}}
+ local with_group_bytes = p2.WithGroup_encode(with_group)
+ check(mode .. '/WithGroup_encode (group)',
+ function() p2.WithGroup_encode(with_group) end)
+ check(mode .. '/WithGroup_decode (group)',
+ function() p2.WithGroup_decode(with_group_bytes) end)
+
+ -- Repeated groups: same shape, exercises the per-element bracket loop.
+ local with_rep = {repgroup = {{n = 1}, {n = 2}, {n = 3}, {n = 4}}}
+ local with_rep_bytes = p2.WithGroup_encode(with_rep)
+ check(mode .. '/WithGroup_encode (repeated group)',
+ function() p2.WithGroup_encode(with_rep) end)
+ check(mode .. '/WithGroup_decode (repeated group)',
+ function() p2.WithGroup_decode(with_rep_bytes) end)
+end
+
+-- Extensions: register a small proto2 fixture inline so the trace gate
+-- doesn't depend on the bulky conformance schema. Exercises both encode
+-- (walks _extensions and routes through encode_field) and decode (routes
+-- an unknown tag through extensions_by_id → decode_extension).
+do
+ local p2tests = require('full.protobuf_test_messages.proto2.test_messages_proto2_pb')
+ local Foo = p2tests.TestAllTypesProto2_descriptor
+ local msg = {
+ _extensions = {
+ ['protobuf_test_messages.proto2.extension_int32'] = 42,
+ ['protobuf_test_messages.proto2.extension_string'] = 'hi',
+ },
+ }
+ -- Encode-prime via the descriptor-driven path; tracing the inline
+ -- emitted code wouldn't cover the extension loop (it's in codec.lua).
+ local pb = require('pb')
+ local ext_bytes = pb.encode(Foo, msg)
+ check('full/extension_encode',
+ function() pb.encode(Foo, msg) end)
+ check('full/extension_decode',
+ function() pb.decode(Foo, ext_bytes) end)
+end
+
-- Pin the known map limitation: pairs() over a hash compiles to bytecode
-- ISNEXT, which Tarantool LuaJIT 2.1 can't trace. If this stops triggering,
-- upstream lifted the restriction and our scope claim can broaden.
M cmd/protoc-gen-tarantool/internal/gen/inline.go => cmd/protoc-gen-tarantool/internal/gen/inline.go +39 -3
@@ 53,6 53,31 @@ func emitInlineEncode(w *writer, name string, m *protogen.Message, file *protoge
for _, f := range m.Fields {
emitInlineEncodeField(w, f, file, selfPath, imports, prefix)
}
+ // Proto2 extensions: delegate to pb.codec.encode_field once per set
+ // entry. We don't inline an extension-specific writer here because
+ // extensions are runtime-mutable — a user can register more after the
+ // module loads — so the canonical iteration source is the descriptor's
+ // extensions_list. The walk is JIT-stable (array, not pairs over a
+ // hash). Skip entirely when extensions_list is nil (most proto3 messages
+ // and proto2 messages without `extensions` ranges) so the hot path
+ // pays nothing.
+ w.line(" local _exts = t._extensions")
+ w.line(" if _exts ~= nil then")
+ w.line(" local _elist = M.%s_descriptor.extensions_list", name)
+ w.line(" if _elist ~= nil then")
+ w.line(" for _i = 1, #_elist do")
+ w.line(" local _ext = _elist[_i]")
+ w.line(" local _ev = _exts[_ext.full_name]")
+ w.line(" if _ev ~= nil then")
+ w.line(" pb.codec.encode_field(_ext, _ev, out, true)")
+ w.line(" end")
+ w.line(" end")
+ // encode_field uses out[#out + 1] = … and doesn't know about our
+ // local `n` cursor — resync so the unknown-fields append below lands
+ // after the extension bytes, not on top of them.
+ w.line(" n = #out")
+ w.line(" end")
+ w.line(" end")
// Preserve unknown fields captured at decode time.
w.line(" local _uf = t._unknown_fields")
w.line(" if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end")
@@ 342,9 367,20 @@ func emitInlineDecode(w *writer, name string, m *protogen.Message, file *protoge
w.line(" if true then")
}
w.line(" else")
- w.line(" pos = wire.skip_field(buf, pos, wt, id)")
- w.line(" if _uf == nil then _uf = {} end")
- w.line(" _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)")
+ // Proto2 extensions: an unknown tag may belong to a registered
+ // extension on this descriptor. Route through pb.codec's
+ // decode_extension which mirrors the in-line dispatch on field
+ // kind (scalar/enum/message/group, singular/repeated) and stores
+ // into result._extensions[full_name].
+ w.line(" local _ebid = M.%s_descriptor.extensions_by_id", name)
+ w.line(" local _ext = _ebid and _ebid[id] or nil")
+ w.line(" if _ext ~= nil then")
+ w.line(" pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)")
+ w.line(" else")
+ w.line(" pos = wire.skip_field(buf, pos, wt, id)")
+ w.line(" if _uf == nil then _uf = {} end")
+ w.line(" _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)")
+ w.line(" end")
w.line(" end")
w.line(" end")
w.line(" if _uf ~= nil then result._unknown_fields = table.concat(_uf) end")
M examples/expected/full/conformance/conformance_pb.lua => examples/expected/full/conformance/conformance_pb.lua +115 -15
@@ 225,6 225,20 @@ function M.TestStatus_encode(t)
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestStatus_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 256,9 270,15 @@ function M.TestStatus_decode(buf)
val, pos = wire.decode_string(buf, pos)
result.matched_name = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestStatus_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 296,6 316,20 @@ function M.FailureSet_encode(t)
n = n + 1; out[n] = _b
end
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.FailureSet_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 321,9 355,15 @@ function M.FailureSet_decode(buf)
payload, pos = wire.decode_len(buf, pos)
list[#list + 1] = M.TestStatus_decode(payload)
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.FailureSet_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 430,6 470,20 @@ function M.ConformanceRequest_encode(t)
n = n + 1; out[n] = "\x48"
n = n + 1; out[n] = wire.encode_bool(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.ConformanceRequest_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 502,9 556,15 @@ function M.ConformanceRequest_decode(buf)
val, pos = wire.decode_bool(buf, pos)
result.print_unknown_fields = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.ConformanceRequest_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 604,6 664,20 @@ function M.ConformanceResponse_encode(t)
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.ConformanceResponse_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 731,9 805,15 @@ function M.ConformanceResponse_decode(buf)
result.skipped = nil
result.jspb_payload = nil
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.ConformanceResponse_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 766,6 846,20 @@ function M.JspbEncodingConfig_encode(t)
n = n + 1; out[n] = "\x08"
n = n + 1; out[n] = wire.encode_bool(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.JspbEncodingConfig_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 789,9 883,15 @@ function M.JspbEncodingConfig_decode(buf)
val, pos = wire.decode_bool(buf, pos)
result.use_jspb_array_any_format = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.JspbEncodingConfig_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
M examples/expected/full/hello/hello_pb.lua => examples/expected/full/hello/hello_pb.lua +138 -18
@@ 246,6 246,20 @@ function M.Result_encode(t)
n = n + 1; out[n] = wire.encode_varint(#_b)
n = n + 1; out[n] = _b
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Result_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 292,9 306,15 @@ function M.Result_decode(buf)
result.text = nil
result.code = nil
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Result_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 328,6 348,20 @@ function M.HelloRequest_encode(t)
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.HelloRequest_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 351,9 385,15 @@ function M.HelloRequest_decode(buf)
val, pos = wire.decode_string(buf, pos)
result.name = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.HelloRequest_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 387,6 427,20 @@ function M.HelloReply_encode(t)
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.HelloReply_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 410,9 464,15 @@ function M.HelloReply_decode(buf)
val, pos = wire.decode_string(buf, pos)
result.greeting = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.HelloReply_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 534,6 594,20 @@ function M.Event_encode(t)
n = n + 1; out[n] = wire.encode_varint(#_b)
n = n + 1; out[n] = _b
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Event_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 601,9 675,15 @@ function M.Event_decode(buf)
payload, pos = wire.decode_len(buf, pos)
result.update_mask = pb.wkt.FieldMask_decode(payload)
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Event_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 657,6 737,20 @@ function M.Address_encode(t)
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Address_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 692,9 786,15 @@ function M.Address_decode(buf)
val, pos = wire.decode_string(buf, pos)
result.apartment = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Address_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 873,6 973,20 @@ function M.Person_encode(t)
n = n + 1; out[n] = wire.encode_len(table.concat(entry))
end
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Person_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 1017,9 1131,15 @@ function M.Person_decode(buf)
end
map[_key] = _val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Person_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
M examples/expected/full/proto2_basic/proto2_basic_pb.lua => examples/expected/full/proto2_basic/proto2_basic_pb.lua +624 -21
@@ 27,6 27,9 @@ M.Nested_Inner_descriptor = {name = "proto2_basic.Nested.Inner"}
M.WithGroup_descriptor = {name = "proto2_basic.WithGroup"}
M.WithGroup_SingleGroup_descriptor = {name = "proto2_basic.WithGroup.SingleGroup"}
M.WithGroup_RepGroup_descriptor = {name = "proto2_basic.WithGroup.RepGroup"}
+M.BenchPayload_descriptor = {name = "proto2_basic.BenchPayload"}
+M.BenchPayload_Stats_descriptor = {name = "proto2_basic.BenchPayload.Stats"}
+M.BenchPayload_Inner_descriptor = {name = "proto2_basic.BenchPayload.Inner"}
-- Message: proto2_basic.Defaults
M.Defaults_descriptor.fields = {
@@ 121,6 124,49 @@ M.WithGroup_RepGroup_fields = pb.field_names({
n = "n",
})
+-- Message: proto2_basic.BenchPayload
+M.BenchPayload_descriptor.fields = {
+ {name="id", id=1, kind='scalar', proto_type="int32", required=true},
+ {name="name", id=2, kind='scalar', proto_type="string", optional=true, default_value="anonymous"},
+ {name="retries", id=3, kind='scalar', proto_type="int32", optional=true, default_value=3},
+ {name="lucky_numbers", id=4, kind='scalar', proto_type="int32", repeated=true, packed=true, options={packed = true}},
+ {name="tags", id=5, kind='scalar', proto_type="string", repeated=true},
+ {name="inner", id=6, kind='message', message=M.BenchPayload_Inner_descriptor, optional=true},
+ {name="stats", id=7, kind='group', message=M.BenchPayload_Stats_descriptor, optional=true},
+}
+pb.finalize_message(M.BenchPayload_descriptor)
+M.BenchPayload_fields = pb.field_names({
+ id = "id",
+ name = "name",
+ retries = "retries",
+ lucky_numbers = "lucky_numbers",
+ tags = "tags",
+ inner = "inner",
+ stats = "stats",
+})
+
+-- Message: proto2_basic.BenchPayload.Stats
+M.BenchPayload_Stats_descriptor.fields = {
+ {name="latency_ns", id=8, kind='scalar', proto_type="int32", optional=true},
+ {name="attempts", id=9, kind='scalar', proto_type="int32", optional=true},
+}
+pb.finalize_message(M.BenchPayload_Stats_descriptor)
+M.BenchPayload_Stats_fields = pb.field_names({
+ latency_ns = "latency_ns",
+ attempts = "attempts",
+})
+
+-- Message: proto2_basic.BenchPayload.Inner
+M.BenchPayload_Inner_descriptor.fields = {
+ {name="key", id=1, kind='scalar', proto_type="string", required=true},
+ {name="weight", id=2, kind='scalar', proto_type="int32", optional=true},
+}
+pb.finalize_message(M.BenchPayload_Inner_descriptor)
+M.BenchPayload_Inner_fields = pb.field_names({
+ key = "key",
+ weight = "weight",
+})
+
-- EmmyLua / lua-language-server type annotations.
-- These are comments — no runtime effect. They give editors
-- autocomplete and type-checking for the generated wrappers.
@@ 164,6 210,26 @@ M.WithGroup_RepGroup_fields = pb.field_names({
---@class proto2_basic.WithGroup.RepGroup
---@field n? integer
+--- Bench fixture exercising the proto2-only shapes: required scalar,
+--- optional repeated, custom default, a `group` field, and a nested
+--- message. Used by bench/bench.lua against both modes.
+---@class proto2_basic.BenchPayload
+---@field id integer
+---@field name? string
+---@field retries? integer
+---@field lucky_numbers integer[]
+---@field tags string[]
+---@field inner? proto2_basic.BenchPayload.Inner
+---@field stats? proto2_basic.BenchPayload.Stats
+
+---@class proto2_basic.BenchPayload.Stats
+---@field latency_ns? integer
+---@field attempts? integer
+
+---@class proto2_basic.BenchPayload.Inner
+---@field key string
+---@field weight? integer
+
---@param t? proto2_basic.Defaults
---@return proto2_basic.Defaults
function M.Defaults_new(t) return t or {} end
@@ 237,6 303,20 @@ function M.Defaults_encode(t)
n = n + 1; out[n] = "\x48"
n = n + 1; out[n] = wire.encode_int32(nv)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Defaults_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 292,9 372,15 @@ function M.Defaults_decode(buf)
u, pos = wire.decode_varint(buf, pos)
result.color = wire.varint_to_int32(u)
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Defaults_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 409,6 495,20 @@ function M.Cardinality_encode(t)
n = n + 1; out[n] = wire.encode_int32(v[_i])
end
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Cardinality_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 487,9 587,15 @@ function M.Cardinality_decode(buf)
list[#list + 1] = val
end
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Cardinality_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 538,6 644,20 @@ function M.Nested_encode(t)
n = n + 1; out[n] = wire.encode_varint(#_b)
n = n + 1; out[n] = _b
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Nested_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 575,9 695,15 @@ function M.Nested_decode(buf)
pb.codec.merge_message(M.Nested_Inner_descriptor, prev, M.Nested_Inner_decode(payload))
end
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Nested_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 616,6 742,20 @@ function M.Nested_Inner_encode(t)
end
n = n + 1; out[n] = "\x08"
n = n + 1; out[n] = wire.encode_int32(v)
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.Nested_Inner_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 639,9 779,15 @@ function M.Nested_Inner_decode(buf)
val, pos = wire.decode_int32(buf, pos)
result.x = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.Nested_Inner_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 686,6 832,20 @@ function M.WithGroup_encode(t)
n = n + 1; out[n] = _etag
end
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.WithGroup_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 720,9 880,15 @@ function M.WithGroup_decode(buf)
payload, pos = pb.codec.decode_group(M.WithGroup_RepGroup_descriptor, buf, pos, 4)
list[#list + 1] = payload
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.WithGroup_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 767,6 933,20 @@ function M.WithGroup_SingleGroup_encode(t)
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.WithGroup_SingleGroup_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 794,9 974,15 @@ function M.WithGroup_SingleGroup_decode(buf)
val, pos = wire.decode_string(buf, pos)
result.s = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.WithGroup_SingleGroup_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 839,6 1025,20 @@ function M.WithGroup_RepGroup_encode(t)
n = n + 1; out[n] = "\x28"
n = n + 1; out[n] = wire.encode_int32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.WithGroup_RepGroup_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 862,9 1062,15 @@ function M.WithGroup_RepGroup_decode(buf)
val, pos = wire.decode_int32(buf, pos)
result.n = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.WithGroup_RepGroup_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 884,4 1090,401 @@ function M.WithGroup_RepGroup_has_n(t) return t.n ~= nil end
---@param t proto2_basic.WithGroup.RepGroup
function M.WithGroup_RepGroup_clear_n(t) t.n = nil end
+---@param t? proto2_basic.BenchPayload
+---@return proto2_basic.BenchPayload
+function M.BenchPayload_new(t) return t or {} end
+
+---@param t proto2_basic.BenchPayload
+---@return string
+function M.BenchPayload_encode(t)
+ if type(t) ~= 'table' then
+ error("expected table for proto2_basic.BenchPayload, got " .. type(t), 0)
+ end
+ local out, n = {}, 0
+ local v
+ -- field 1: id
+ v = t.id
+ if v == nil then
+ error("required field missing on encode: proto2_basic.BenchPayload.id", 0)
+ end
+ n = n + 1; out[n] = "\x08"
+ n = n + 1; out[n] = wire.encode_int32(v)
+ -- field 2: name
+ v = t.name
+ if v ~= nil then
+ n = n + 1; out[n] = "\x12"
+ n = n + 1; out[n] = wire.encode_varint(#v)
+ n = n + 1; out[n] = v
+ end
+ -- field 3: retries
+ v = t.retries
+ if v ~= nil then
+ n = n + 1; out[n] = "\x18"
+ n = n + 1; out[n] = wire.encode_int32(v)
+ end
+ -- field 4: lucky_numbers
+ v = t.lucky_numbers
+ if v ~= nil and #v > 0 then
+ local parts, m = {}, 0
+ for _i = 1, #v do
+ m = m + 1; parts[m] = wire.encode_int32(v[_i])
+ end
+ local _b = table.concat(parts)
+ n = n + 1; out[n] = "\x22"
+ n = n + 1; out[n] = wire.encode_varint(#_b)
+ n = n + 1; out[n] = _b
+ end
+ -- field 5: tags
+ v = t.tags
+ if v ~= nil and #v > 0 then
+ local _tag = "\x2a"
+ for _i = 1, #v do
+ local _b = v[_i]
+ n = n + 1; out[n] = _tag
+ n = n + 1; out[n] = wire.encode_varint(#_b)
+ n = n + 1; out[n] = _b
+ end
+ end
+ -- field 6: inner
+ v = t.inner
+ if v ~= nil or type(v) == 'cdata' then
+ local _b = M.BenchPayload_Inner_encode(v)
+ n = n + 1; out[n] = "\x32"
+ n = n + 1; out[n] = wire.encode_varint(#_b)
+ n = n + 1; out[n] = _b
+ end
+ -- field 7: stats
+ v = t.stats
+ if v ~= nil or type(v) == 'cdata' then
+ n = n + 1; out[n] = "\x3b"
+ n = n + 1; out[n] = M.BenchPayload_Stats_encode(v)
+ n = n + 1; out[n] = "\x3c"
+ end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.BenchPayload_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
+ local _uf = t._unknown_fields
+ if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
+ return table.concat(out)
+end
+
+---@param b string
+---@return proto2_basic.BenchPayload
+function M.BenchPayload_decode(buf)
+ if type(buf) ~= 'string' then
+ error("expected string for proto2_basic.BenchPayload decode, got " .. type(buf), 0)
+ end
+ local result = {}
+ local pos, len = 1, #buf
+ local _uf
+ while pos <= len do
+ local _tag_start = pos
+ local id, wt
+ id, wt, pos = wire.decode_tag(buf, pos)
+ if id == 1 then
+ local val
+ val, pos = wire.decode_int32(buf, pos)
+ result.id = val
+ elseif id == 2 then
+ local val
+ val, pos = wire.decode_string(buf, pos)
+ result.name = val
+ elseif id == 3 then
+ local val
+ val, pos = wire.decode_int32(buf, pos)
+ result.retries = val
+ elseif id == 4 then
+ local list = result.lucky_numbers
+ if list == nil then list = {}; result.lucky_numbers = list end
+ if wt == 2 then
+ local payload
+ payload, pos = wire.decode_len(buf, pos)
+ local p2, lim = 1, #payload
+ while p2 <= lim do
+ local val
+ val, p2 = wire.decode_int32(payload, p2)
+ list[#list + 1] = val
+ end
+ else
+ local val
+ val, pos = wire.decode_int32(buf, pos)
+ list[#list + 1] = val
+ end
+ elseif id == 5 then
+ local list = result.tags
+ if list == nil then list = {}; result.tags = list end
+ local val
+ val, pos = wire.decode_string(buf, pos)
+ list[#list + 1] = val
+ elseif id == 6 then
+ local payload
+ payload, pos = wire.decode_len(buf, pos)
+ local prev = result.inner
+ if prev == nil then
+ result.inner = M.BenchPayload_Inner_decode(payload)
+ else
+ pb.codec.merge_message(M.BenchPayload_Inner_descriptor, prev, M.BenchPayload_Inner_decode(payload))
+ end
+ elseif id == 7 then
+ local payload
+ payload, pos = pb.codec.decode_group(M.BenchPayload_Stats_descriptor, buf, pos, 7)
+ local prev = result.stats
+ if prev == nil then
+ result.stats = payload
+ else
+ pb.codec.merge_message(M.BenchPayload_Stats_descriptor, prev, payload)
+ end
+ else
+ local _ebid = M.BenchPayload_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
+ end
+ end
+ if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
+ return result
+end
+
+---@param b string
+---@return pb.MessageView
+function M.BenchPayload_decode_lazy(b) return pb.decode_lazy(M.BenchPayload_descriptor, b) end
+---@param t proto2_basic.BenchPayload
+---@param opts? {single_line: boolean?, indent: string?}
+---@return string
+function M.BenchPayload_text(t, opts) return pb.text.encode(M.BenchPayload_descriptor, t, opts) end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_name(t) return t.name ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_name(t) t.name = nil end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_retries(t) return t.retries ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_retries(t) t.retries = nil end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_inner(t) return t.inner ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_inner(t) t.inner = nil end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_stats(t) return t.stats ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_stats(t) t.stats = nil end
+
+---@param t? proto2_basic.BenchPayload.Stats
+---@return proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_new(t) return t or {} end
+
+---@param t proto2_basic.BenchPayload.Stats
+---@return string
+function M.BenchPayload_Stats_encode(t)
+ if type(t) ~= 'table' then
+ error("expected table for proto2_basic.BenchPayload.Stats, got " .. type(t), 0)
+ end
+ local out, n = {}, 0
+ local v
+ -- field 8: latency_ns
+ v = t.latency_ns
+ if v ~= nil then
+ n = n + 1; out[n] = "\x40"
+ n = n + 1; out[n] = wire.encode_int32(v)
+ end
+ -- field 9: attempts
+ v = t.attempts
+ if v ~= nil then
+ n = n + 1; out[n] = "\x48"
+ n = n + 1; out[n] = wire.encode_int32(v)
+ end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.BenchPayload_Stats_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
+ local _uf = t._unknown_fields
+ if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
+ return table.concat(out)
+end
+
+---@param b string
+---@return proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_decode(buf)
+ if type(buf) ~= 'string' then
+ error("expected string for proto2_basic.BenchPayload.Stats decode, got " .. type(buf), 0)
+ end
+ local result = {}
+ local pos, len = 1, #buf
+ local _uf
+ while pos <= len do
+ local _tag_start = pos
+ local id, wt
+ id, wt, pos = wire.decode_tag(buf, pos)
+ if id == 8 then
+ local val
+ val, pos = wire.decode_int32(buf, pos)
+ result.latency_ns = val
+ elseif id == 9 then
+ local val
+ val, pos = wire.decode_int32(buf, pos)
+ result.attempts = val
+ else
+ local _ebid = M.BenchPayload_Stats_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
+ end
+ end
+ if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
+ return result
+end
+
+---@param b string
+---@return pb.MessageView
+function M.BenchPayload_Stats_decode_lazy(b) return pb.decode_lazy(M.BenchPayload_Stats_descriptor, b) end
+---@param t proto2_basic.BenchPayload.Stats
+---@param opts? {single_line: boolean?, indent: string?}
+---@return string
+function M.BenchPayload_Stats_text(t, opts) return pb.text.encode(M.BenchPayload_Stats_descriptor, t, opts) end
+---@param t proto2_basic.BenchPayload.Stats
+---@return boolean
+function M.BenchPayload_Stats_has_latency_ns(t) return t.latency_ns ~= nil end
+---@param t proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_clear_latency_ns(t) t.latency_ns = nil end
+---@param t proto2_basic.BenchPayload.Stats
+---@return boolean
+function M.BenchPayload_Stats_has_attempts(t) return t.attempts ~= nil end
+---@param t proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_clear_attempts(t) t.attempts = nil end
+
+---@param t? proto2_basic.BenchPayload.Inner
+---@return proto2_basic.BenchPayload.Inner
+function M.BenchPayload_Inner_new(t) return t or {} end
+
+---@param t proto2_basic.BenchPayload.Inner
+---@return string
+function M.BenchPayload_Inner_encode(t)
+ if type(t) ~= 'table' then
+ error("expected table for proto2_basic.BenchPayload.Inner, got " .. type(t), 0)
+ end
+ local out, n = {}, 0
+ local v
+ -- field 1: key
+ v = t.key
+ if v == nil then
+ error("required field missing on encode: proto2_basic.BenchPayload.Inner.key", 0)
+ end
+ n = n + 1; out[n] = "\x0a"
+ n = n + 1; out[n] = wire.encode_varint(#v)
+ n = n + 1; out[n] = v
+ -- field 2: weight
+ v = t.weight
+ if v ~= nil then
+ n = n + 1; out[n] = "\x10"
+ n = n + 1; out[n] = wire.encode_int32(v)
+ end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.BenchPayload_Inner_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
+ local _uf = t._unknown_fields
+ if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
+ return table.concat(out)
+end
+
+---@param b string
+---@return proto2_basic.BenchPayload.Inner
+function M.BenchPayload_Inner_decode(buf)
+ if type(buf) ~= 'string' then
+ error("expected string for proto2_basic.BenchPayload.Inner decode, got " .. type(buf), 0)
+ end
+ local result = {}
+ local pos, len = 1, #buf
+ local _uf
+ while pos <= len do
+ local _tag_start = pos
+ local id, wt
+ id, wt, pos = wire.decode_tag(buf, pos)
+ if id == 1 then
+ local val
+ val, pos = wire.decode_string(buf, pos)
+ result.key = val
+ elseif id == 2 then
+ local val
+ val, pos = wire.decode_int32(buf, pos)
+ result.weight = val
+ else
+ local _ebid = M.BenchPayload_Inner_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
+ end
+ end
+ if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
+ return result
+end
+
+---@param b string
+---@return pb.MessageView
+function M.BenchPayload_Inner_decode_lazy(b) return pb.decode_lazy(M.BenchPayload_Inner_descriptor, b) end
+---@param t proto2_basic.BenchPayload.Inner
+---@param opts? {single_line: boolean?, indent: string?}
+---@return string
+function M.BenchPayload_Inner_text(t, opts) return pb.text.encode(M.BenchPayload_Inner_descriptor, t, opts) end
+---@param t proto2_basic.BenchPayload.Inner
+---@return boolean
+function M.BenchPayload_Inner_has_weight(t) return t.weight ~= nil end
+---@param t proto2_basic.BenchPayload.Inner
+function M.BenchPayload_Inner_clear_weight(t) t.weight = nil end
+
+-- Extension: proto2_basic.ext_count extends proto2_basic.BenchPayload (tag 100)
+pb.register_extension(M.BenchPayload_descriptor, {name="ext_count", full_name="proto2_basic.ext_count", id=100, kind='scalar', proto_type="int32", optional=true})
+-- Extension: proto2_basic.ext_label extends proto2_basic.BenchPayload (tag 101)
+pb.register_extension(M.BenchPayload_descriptor, {name="ext_label", full_name="proto2_basic.ext_label", id=101, kind='scalar', proto_type="string", optional=true})
+
return M
M examples/expected/full/protobuf_test_messages/proto2/test_messages_proto2_pb.lua => examples/expected/full/protobuf_test_messages/proto2/test_messages_proto2_pb.lua +483 -63
@@ 2259,6 2259,20 @@ function M.TestAllTypesProto2_encode(t)
n = n + 1; out[n] = "\x90\x1a"
n = n + 1; out[n] = wire.encode_int32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllTypesProto2_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 3835,9 3849,15 @@ function M.TestAllTypesProto2_decode(buf)
val, pos = wire.decode_int32(buf, pos)
result.Field_name18__ = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllTypesProto2_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4163,6 4183,20 @@ function M.TestAllTypesProto2_NestedMessage_encode(t)
n = n + 1; out[n] = wire.encode_varint(#_b)
n = n + 1; out[n] = _b
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllTypesProto2_NestedMessage_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4195,9 4229,15 @@ function M.TestAllTypesProto2_NestedMessage_decode(buf)
pb.codec.merge_message(M.TestAllTypesProto2_descriptor, prev, M.TestAllTypesProto2_decode(payload))
end
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllTypesProto2_NestedMessage_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4246,6 4286,20 @@ function M.TestAllTypesProto2_Data_encode(t)
n = n + 1; out[n] = "\xd8\x0c"
n = n + 1; out[n] = wire.encode_uint32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllTypesProto2_Data_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4273,9 4327,15 @@ function M.TestAllTypesProto2_Data_decode(buf)
val, pos = wire.decode_uint32(buf, pos)
result.group_uint32 = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllTypesProto2_Data_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4324,6 4384,20 @@ function M.TestAllTypesProto2_MultiWordGroupField_encode(t)
n = n + 1; out[n] = "\xf0\x0c"
n = n + 1; out[n] = wire.encode_uint32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllTypesProto2_MultiWordGroupField_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4351,9 4425,15 @@ function M.TestAllTypesProto2_MultiWordGroupField_decode(buf)
val, pos = wire.decode_uint32(buf, pos)
result.group_uint32 = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllTypesProto2_MultiWordGroupField_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4396,6 4476,20 @@ function M.ForeignMessageProto2_encode(t)
n = n + 1; out[n] = "\x08"
n = n + 1; out[n] = wire.encode_int32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.ForeignMessageProto2_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4419,9 4513,15 @@ function M.ForeignMessageProto2_decode(buf)
val, pos = wire.decode_int32(buf, pos)
result.c = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.ForeignMessageProto2_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4465,6 4565,20 @@ function M.GroupField_encode(t)
n = n + 1; out[n] = "\xd8\x07"
n = n + 1; out[n] = wire.encode_uint32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.GroupField_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4492,9 4606,15 @@ function M.GroupField_decode(buf)
val, pos = wire.decode_uint32(buf, pos)
result.group_uint32 = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.GroupField_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4574,6 4694,20 @@ function M.UnknownToTestAllTypes_encode(t)
n = n + 1; out[n] = wire.encode_int32(v[_i])
end
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.UnknownToTestAllTypes_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4640,9 4774,15 @@ function M.UnknownToTestAllTypes_decode(buf)
list[#list + 1] = val
end
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.UnknownToTestAllTypes_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4700,6 4840,20 @@ function M.UnknownToTestAllTypes_OptionalGroup_encode(t)
n = n + 1; out[n] = "\x08"
n = n + 1; out[n] = wire.encode_int32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.UnknownToTestAllTypes_OptionalGroup_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4723,9 4877,15 @@ function M.UnknownToTestAllTypes_OptionalGroup_decode(buf)
val, pos = wire.decode_int32(buf, pos)
result.a = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.UnknownToTestAllTypes_OptionalGroup_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4757,6 4917,20 @@ function M.NullHypothesisProto2_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.NullHypothesisProto2_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4777,9 4951,15 @@ function M.NullHypothesisProto2_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.NullHypothesisProto2_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4806,6 4986,20 @@ function M.EnumOnlyProto2_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.EnumOnlyProto2_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4826,9 5020,15 @@ function M.EnumOnlyProto2_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.EnumOnlyProto2_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4862,6 5062,20 @@ function M.OneStringProto2_encode(t)
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.OneStringProto2_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4885,9 5099,15 @@ function M.OneStringProto2_decode(buf)
val, pos = wire.decode_string(buf, pos)
result.data = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.OneStringProto2_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4943,6 5163,20 @@ function M.ProtoWithKeywords_encode(t)
n = n + 1; out[n] = _b
end
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.ProtoWithKeywords_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4976,9 5210,15 @@ function M.ProtoWithKeywords_decode(buf)
val, pos = wire.decode_string(buf, pos)
list[#list + 1] = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.ProtoWithKeywords_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 5317,6 5557,20 @@ function M.TestAllRequiredTypesProto2_encode(t)
n = n + 1; out[n] = "\xfa\x0f"
n = n + 1; out[n] = wire.encode_varint(#v)
n = n + 1; out[n] = v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllRequiredTypesProto2_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 5517,9 5771,15 @@ function M.TestAllRequiredTypesProto2_decode(buf)
val, pos = wire.decode_bytes(buf, pos)
result.default_bytes = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllRequiredTypesProto2_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 5575,6 5835,20 @@ function M.TestAllRequiredTypesProto2_NestedMessage_encode(t)
n = n + 1; out[n] = wire.encode_varint(#_b)
n = n + 1; out[n] = _b
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllRequiredTypesProto2_NestedMessage_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 5616,9 5890,15 @@ function M.TestAllRequiredTypesProto2_NestedMessage_decode(buf)
pb.codec.merge_message(M.TestAllRequiredTypesProto2_descriptor, prev, M.TestAllRequiredTypesProto2_decode(payload))
end
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllRequiredTypesProto2_NestedMessage_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 5664,6 5944,20 @@ function M.TestAllRequiredTypesProto2_Data_encode(t)
end
n = n + 1; out[n] = "\xd8\x0c"
n = n + 1; out[n] = wire.encode_uint32(v)
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllRequiredTypesProto2_Data_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 5691,9 5985,15 @@ function M.TestAllRequiredTypesProto2_Data_decode(buf)
val, pos = wire.decode_uint32(buf, pos)
result.group_uint32 = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllRequiredTypesProto2_Data_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 5766,6 6066,20 @@ function M.TestLargeOneof_encode(t)
n = n + 1; out[n] = wire.encode_varint(#_b)
n = n + 1; out[n] = _b
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestLargeOneof_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 5850,9 6164,15 @@ function M.TestLargeOneof_decode(buf)
result.a3 = nil
result.a4 = nil
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestLargeOneof_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 5879,6 6199,20 @@ function M.TestLargeOneof_A1_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestLargeOneof_A1_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 5899,9 6233,15 @@ function M.TestLargeOneof_A1_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestLargeOneof_A1_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 5928,6 6268,20 @@ function M.TestLargeOneof_A2_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestLargeOneof_A2_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 5948,9 6302,15 @@ function M.TestLargeOneof_A2_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestLargeOneof_A2_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 5977,6 6337,20 @@ function M.TestLargeOneof_A3_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestLargeOneof_A3_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 5997,9 6371,15 @@ function M.TestLargeOneof_A3_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestLargeOneof_A3_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 6026,6 6406,20 @@ function M.TestLargeOneof_A4_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestLargeOneof_A4_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 6046,9 6440,15 @@ function M.TestLargeOneof_A4_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestLargeOneof_A4_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 6075,6 6475,20 @@ function M.TestLargeOneof_A5_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestLargeOneof_A5_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 6095,9 6509,15 @@ function M.TestLargeOneof_A5_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestLargeOneof_A5_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
M examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua => examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua +115 -15
@@ 2207,6 2207,20 @@ function M.TestAllTypesProto3_encode(t)
n = n + 1; out[n] = "\x90\x1a"
n = n + 1; out[n] = wire.encode_int32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllTypesProto3_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 3861,9 3875,15 @@ function M.TestAllTypesProto3_decode(buf)
val, pos = wire.decode_int32(buf, pos)
result.Field_name18__ = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllTypesProto3_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 3904,6 3924,20 @@ function M.TestAllTypesProto3_NestedMessage_encode(t)
n = n + 1; out[n] = wire.encode_varint(#_b)
n = n + 1; out[n] = _b
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.TestAllTypesProto3_NestedMessage_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 3936,9 3970,15 @@ function M.TestAllTypesProto3_NestedMessage_decode(buf)
pb.codec.merge_message(M.TestAllTypesProto3_descriptor, prev, M.TestAllTypesProto3_decode(payload))
end
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.TestAllTypesProto3_NestedMessage_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 3971,6 4011,20 @@ function M.ForeignMessage_encode(t)
n = n + 1; out[n] = "\x08"
n = n + 1; out[n] = wire.encode_int32(v)
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.ForeignMessage_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 3994,9 4048,15 @@ function M.ForeignMessage_decode(buf)
val, pos = wire.decode_int32(buf, pos)
result.c = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.ForeignMessage_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4023,6 4083,20 @@ function M.NullHypothesisProto3_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.NullHypothesisProto3_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4043,9 4117,15 @@ function M.NullHypothesisProto3_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.NullHypothesisProto3_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
@@ 4072,6 4152,20 @@ function M.EnumOnlyProto3_encode(t)
end
local out, n = {}, 0
local v
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.EnumOnlyProto3_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 4092,9 4186,15 @@ function M.EnumOnlyProto3_decode(buf)
id, wt, pos = wire.decode_tag(buf, pos)
if true then
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.EnumOnlyProto3_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
M examples/expected/full/quickstart/quickstart_pb.lua => examples/expected/full/quickstart/quickstart_pb.lua +23 -3
@@ 96,6 96,20 @@ function M.User_encode(t)
n = n + 1; out[n] = _b
end
end
+ local _exts = t._extensions
+ if _exts ~= nil then
+ local _elist = M.User_descriptor.extensions_list
+ if _elist ~= nil then
+ for _i = 1, #_elist do
+ local _ext = _elist[_i]
+ local _ev = _exts[_ext.full_name]
+ if _ev ~= nil then
+ pb.codec.encode_field(_ext, _ev, out, true)
+ end
+ end
+ n = #out
+ end
+ end
local _uf = t._unknown_fields
if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end
return table.concat(out)
@@ 133,9 147,15 @@ function M.User_decode(buf)
val, pos = wire.decode_string(buf, pos)
list[#list + 1] = val
else
- pos = wire.skip_field(buf, pos, wt, id)
- if _uf == nil then _uf = {} end
- _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ local _ebid = M.User_descriptor.extensions_by_id
+ local _ext = _ebid and _ebid[id] or nil
+ if _ext ~= nil then
+ pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)
+ else
+ pos = wire.skip_field(buf, pos, wt, id)
+ if _uf == nil then _uf = {} end
+ _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)
+ end
end
end
if _uf ~= nil then result._unknown_fields = table.concat(_uf) end
M examples/expected/runtime/proto2_basic/proto2_basic_pb.lua => examples/expected/runtime/proto2_basic/proto2_basic_pb.lua +157 -0
@@ 27,6 27,9 @@ M.Nested_Inner_descriptor = {name = "proto2_basic.Nested.Inner"}
M.WithGroup_descriptor = {name = "proto2_basic.WithGroup"}
M.WithGroup_SingleGroup_descriptor = {name = "proto2_basic.WithGroup.SingleGroup"}
M.WithGroup_RepGroup_descriptor = {name = "proto2_basic.WithGroup.RepGroup"}
+M.BenchPayload_descriptor = {name = "proto2_basic.BenchPayload"}
+M.BenchPayload_Stats_descriptor = {name = "proto2_basic.BenchPayload.Stats"}
+M.BenchPayload_Inner_descriptor = {name = "proto2_basic.BenchPayload.Inner"}
-- Message: proto2_basic.Defaults
M.Defaults_descriptor.fields = {
@@ 121,6 124,49 @@ M.WithGroup_RepGroup_fields = pb.field_names({
n = "n",
})
+-- Message: proto2_basic.BenchPayload
+M.BenchPayload_descriptor.fields = {
+ {name="id", id=1, kind='scalar', proto_type="int32", required=true},
+ {name="name", id=2, kind='scalar', proto_type="string", optional=true, default_value="anonymous"},
+ {name="retries", id=3, kind='scalar', proto_type="int32", optional=true, default_value=3},
+ {name="lucky_numbers", id=4, kind='scalar', proto_type="int32", repeated=true, packed=true, options={packed = true}},
+ {name="tags", id=5, kind='scalar', proto_type="string", repeated=true},
+ {name="inner", id=6, kind='message', message=M.BenchPayload_Inner_descriptor, optional=true},
+ {name="stats", id=7, kind='group', message=M.BenchPayload_Stats_descriptor, optional=true},
+}
+pb.finalize_message(M.BenchPayload_descriptor)
+M.BenchPayload_fields = pb.field_names({
+ id = "id",
+ name = "name",
+ retries = "retries",
+ lucky_numbers = "lucky_numbers",
+ tags = "tags",
+ inner = "inner",
+ stats = "stats",
+})
+
+-- Message: proto2_basic.BenchPayload.Stats
+M.BenchPayload_Stats_descriptor.fields = {
+ {name="latency_ns", id=8, kind='scalar', proto_type="int32", optional=true},
+ {name="attempts", id=9, kind='scalar', proto_type="int32", optional=true},
+}
+pb.finalize_message(M.BenchPayload_Stats_descriptor)
+M.BenchPayload_Stats_fields = pb.field_names({
+ latency_ns = "latency_ns",
+ attempts = "attempts",
+})
+
+-- Message: proto2_basic.BenchPayload.Inner
+M.BenchPayload_Inner_descriptor.fields = {
+ {name="key", id=1, kind='scalar', proto_type="string", required=true},
+ {name="weight", id=2, kind='scalar', proto_type="int32", optional=true},
+}
+pb.finalize_message(M.BenchPayload_Inner_descriptor)
+M.BenchPayload_Inner_fields = pb.field_names({
+ key = "key",
+ weight = "weight",
+})
+
-- EmmyLua / lua-language-server type annotations.
-- These are comments — no runtime effect. They give editors
-- autocomplete and type-checking for the generated wrappers.
@@ 164,6 210,26 @@ M.WithGroup_RepGroup_fields = pb.field_names({
---@class proto2_basic.WithGroup.RepGroup
---@field n? integer
+--- Bench fixture exercising the proto2-only shapes: required scalar,
+--- optional repeated, custom default, a `group` field, and a nested
+--- message. Used by bench/bench.lua against both modes.
+---@class proto2_basic.BenchPayload
+---@field id integer
+---@field name? string
+---@field retries? integer
+---@field lucky_numbers integer[]
+---@field tags string[]
+---@field inner? proto2_basic.BenchPayload.Inner
+---@field stats? proto2_basic.BenchPayload.Stats
+
+---@class proto2_basic.BenchPayload.Stats
+---@field latency_ns? integer
+---@field attempts? integer
+
+---@class proto2_basic.BenchPayload.Inner
+---@field key string
+---@field weight? integer
+
---@param t? proto2_basic.Defaults
---@return proto2_basic.Defaults
function M.Defaults_new(t) return t or {} end
@@ 358,4 424,95 @@ function M.WithGroup_RepGroup_has_n(t) return t.n ~= nil end
---@param t proto2_basic.WithGroup.RepGroup
function M.WithGroup_RepGroup_clear_n(t) t.n = nil end
+---@param t? proto2_basic.BenchPayload
+---@return proto2_basic.BenchPayload
+function M.BenchPayload_new(t) return t or {} end
+---@param t proto2_basic.BenchPayload
+---@return string
+function M.BenchPayload_encode(t) return pb.encode(M.BenchPayload_descriptor, t) end
+---@param b string
+---@return proto2_basic.BenchPayload
+function M.BenchPayload_decode(b) return pb.decode(M.BenchPayload_descriptor, b) end
+---@param b string
+---@return pb.MessageView
+function M.BenchPayload_decode_lazy(b) return pb.decode_lazy(M.BenchPayload_descriptor, b) end
+---@param t proto2_basic.BenchPayload
+---@param opts? {single_line: boolean?, indent: string?}
+---@return string
+function M.BenchPayload_text(t, opts) return pb.text.encode(M.BenchPayload_descriptor, t, opts) end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_name(t) return t.name ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_name(t) t.name = nil end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_retries(t) return t.retries ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_retries(t) t.retries = nil end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_inner(t) return t.inner ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_inner(t) t.inner = nil end
+---@param t proto2_basic.BenchPayload
+---@return boolean
+function M.BenchPayload_has_stats(t) return t.stats ~= nil end
+---@param t proto2_basic.BenchPayload
+function M.BenchPayload_clear_stats(t) t.stats = nil end
+
+---@param t? proto2_basic.BenchPayload.Stats
+---@return proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_new(t) return t or {} end
+---@param t proto2_basic.BenchPayload.Stats
+---@return string
+function M.BenchPayload_Stats_encode(t) return pb.encode(M.BenchPayload_Stats_descriptor, t) end
+---@param b string
+---@return proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_decode(b) return pb.decode(M.BenchPayload_Stats_descriptor, b) end
+---@param b string
+---@return pb.MessageView
+function M.BenchPayload_Stats_decode_lazy(b) return pb.decode_lazy(M.BenchPayload_Stats_descriptor, b) end
+---@param t proto2_basic.BenchPayload.Stats
+---@param opts? {single_line: boolean?, indent: string?}
+---@return string
+function M.BenchPayload_Stats_text(t, opts) return pb.text.encode(M.BenchPayload_Stats_descriptor, t, opts) end
+---@param t proto2_basic.BenchPayload.Stats
+---@return boolean
+function M.BenchPayload_Stats_has_latency_ns(t) return t.latency_ns ~= nil end
+---@param t proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_clear_latency_ns(t) t.latency_ns = nil end
+---@param t proto2_basic.BenchPayload.Stats
+---@return boolean
+function M.BenchPayload_Stats_has_attempts(t) return t.attempts ~= nil end
+---@param t proto2_basic.BenchPayload.Stats
+function M.BenchPayload_Stats_clear_attempts(t) t.attempts = nil end
+
+---@param t? proto2_basic.BenchPayload.Inner
+---@return proto2_basic.BenchPayload.Inner
+function M.BenchPayload_Inner_new(t) return t or {} end
+---@param t proto2_basic.BenchPayload.Inner
+---@return string
+function M.BenchPayload_Inner_encode(t) return pb.encode(M.BenchPayload_Inner_descriptor, t) end
+---@param b string
+---@return proto2_basic.BenchPayload.Inner
+function M.BenchPayload_Inner_decode(b) return pb.decode(M.BenchPayload_Inner_descriptor, b) end
+---@param b string
+---@return pb.MessageView
+function M.BenchPayload_Inner_decode_lazy(b) return pb.decode_lazy(M.BenchPayload_Inner_descriptor, b) end
+---@param t proto2_basic.BenchPayload.Inner
+---@param opts? {single_line: boolean?, indent: string?}
+---@return string
+function M.BenchPayload_Inner_text(t, opts) return pb.text.encode(M.BenchPayload_Inner_descriptor, t, opts) end
+---@param t proto2_basic.BenchPayload.Inner
+---@return boolean
+function M.BenchPayload_Inner_has_weight(t) return t.weight ~= nil end
+---@param t proto2_basic.BenchPayload.Inner
+function M.BenchPayload_Inner_clear_weight(t) t.weight = nil end
+
+-- Extension: proto2_basic.ext_count extends proto2_basic.BenchPayload (tag 100)
+pb.register_extension(M.BenchPayload_descriptor, {name="ext_count", full_name="proto2_basic.ext_count", id=100, kind='scalar', proto_type="int32", optional=true})
+-- Extension: proto2_basic.ext_label extends proto2_basic.BenchPayload (tag 101)
+pb.register_extension(M.BenchPayload_descriptor, {name="ext_label", full_name="proto2_basic.ext_label", id=101, kind='scalar', proto_type="string", optional=true})
+
return M
M runtime/pb/codec.lua => runtime/pb/codec.lua +21 -9
@@ 909,15 909,21 @@ encode_message = function(desc, data)
end
end
-- Proto2 extensions: data._extensions = { [full_name] = value, ... }.
- -- Walk known extensions in declaration order via extensions_by_full_name
- -- so the wire bytes are stable across runs (pairs() ordering otherwise
- -- depends on hash). Unknown extensions stay in _unknown_fields.
+ -- Walk via the parallel array `extensions_list` rather than `pairs()`
+ -- over a hash — pairs() compiles to bytecode ISNEXT, which is NYI in
+ -- Tarantool's LuaJIT 2.1 fork (same limitation that gates map encode).
+ -- pb.register_extension keeps the array in registration order, which
+ -- is also the deterministic on-wire order.
local exts = data._extensions
- if exts ~= nil and desc.extensions_by_full_name ~= nil then
- for full_name, ext in pairs(desc.extensions_by_full_name) do
- local v = exts[full_name]
- if v ~= nil then
- encode_field(ext, v, out, true)
+ if exts ~= nil then
+ local elist = desc.extensions_list
+ if elist ~= nil then
+ for i = 1, #elist do
+ local ext = elist[i]
+ local v = exts[ext.full_name]
+ if v ~= nil then
+ encode_field(ext, v, out, true)
+ end
end
end
end
@@ 1037,7 1043,13 @@ M.decode_group = decode_group
-- result._extensions[ext.full_name]. Mirrors the in-line decode dispatch on
-- field kind (scalar/enum/message/group, singular/repeated). Returns the
-- new buffer position after the value bytes.
-local function decode_extension(ext, buf, pos, wt, result)
+-- Exposed for inline-mode generated code: the per-message decoder calls
+-- decode_extension when it sees an unknown tag that matches a registered
+-- extension on the descriptor.
+local decode_extension
+function M.decode_extension(...) return decode_extension(...) end
+
+decode_extension = function(ext, buf, pos, wt, result)
local exts = result._extensions
if exts == nil then exts = {}; result._extensions = exts end
local key = ext.full_name
M runtime/pb/init.lua => runtime/pb/init.lua +11 -2
@@ 190,14 190,23 @@ return {
-- Proto2 extension registration. Generated code emits one call per
-- `extend Foo { ... }` field, attaching the extension's field shape
-- to the extendee's descriptor. The codec consults `extensions_by_id`
- -- when decoding an unrecognized tag and walks `extensions_by_full_name`
- -- when encoding `data._extensions`.
+ -- when decoding an unrecognized tag, walks `extensions_list` (array)
+ -- when encoding `data._extensions`, and uses
+ -- `extensions_by_full_name` for text/JSON encoder lookups.
+ --
+ -- `extensions_list` is the JIT-stable iteration source — pairs() over
+ -- a hash compiles to bytecode ISNEXT which is NYI in LuaJIT 2.1, so
+ -- the hot encode loop iterates the array instead. The hash tables
+ -- stay around for O(1) name/id lookups.
register_extension = function(extendee_desc, ext)
if extendee_desc.extensions_by_id == nil then
extendee_desc.extensions_by_id = {}
extendee_desc.extensions_by_full_name = {}
+ extendee_desc.extensions_list = {}
end
extendee_desc.extensions_by_id[ext.id] = ext
extendee_desc.extensions_by_full_name[ext.full_name] = ext
+ local list = extendee_desc.extensions_list
+ list[#list + 1] = ext
end,
}
M runtime/pb/json.lua => runtime/pb/json.lua +11 -7
@@ 940,17 940,21 @@ encode_message = function(desc, t)
end
end
-- Proto2 extensions: surface set entries under their bracketed
- -- fully-qualified name (`[pkg.ext_name]`). Repeated extensions
- -- emit as JSON arrays per the proto2 JSON spec.
+ -- fully-qualified name (`[pkg.ext_name]`). Walk the array
+ -- (`extensions_list`) rather than the hash — pairs() compiles to
+ -- ISNEXT which is NYI on the JIT. Repeated extensions emit as JSON
+ -- arrays per the proto2 JSON spec.
local exts = t._extensions
- if exts ~= nil and desc.extensions_by_full_name ~= nil then
- for full_name, ext in pairs(desc.extensions_by_full_name) do
- local v = exts[full_name]
+ local elist = exts ~= nil and desc.extensions_list or nil
+ if elist ~= nil then
+ for i = 1, #elist do
+ local ext = elist[i]
+ local v = exts[ext.full_name]
if v ~= nil then
- local k = '[' .. full_name .. ']'
+ local k = '[' .. ext.full_name .. ']'
if ext.repeated then
local arr = setmetatable({}, {__serialize='seq'})
- for i = 1, #v do arr[i] = encode_field_value(ext, v[i]) end
+ for j = 1, #v do arr[j] = encode_field_value(ext, v[j]) end
out[k] = arr
else
out[k] = encode_field_value(ext, v)
M runtime/pb/text.lua => runtime/pb/text.lua +12 -8
@@ 370,19 370,23 @@ emit_message = function(buf, desc, t, depth)
end
end
-- Proto2 extensions: emit each set entry as `[full.name]: value` in
- -- declaration order via the registry. Repeated extensions emit one
- -- entry per element to keep the round-trip lossless.
+ -- registration order via the array view (`extensions_list`). Same
+ -- ISNEXT-NYI reasoning as the wire encoder — walk the array, not the
+ -- hash. Repeated extensions emit one entry per element to keep the
+ -- round-trip lossless.
local exts = t._extensions
- if exts ~= nil and desc.extensions_by_full_name ~= nil then
- for full_name, ext in pairs(desc.extensions_by_full_name) do
- local v = exts[full_name]
+ local elist = exts ~= nil and desc.extensions_list or nil
+ if elist ~= nil then
+ for i = 1, #elist do
+ local ext = elist[i]
+ local v = exts[ext.full_name]
if v ~= nil then
if ext.repeated then
- for i = 1, #v do
- emit_extension_entry(buf, ext, full_name, v[i], depth)
+ for j = 1, #v do
+ emit_extension_entry(buf, ext, ext.full_name, v[j], depth)
end
else
- emit_extension_entry(buf, ext, full_name, v, depth)
+ emit_extension_entry(buf, ext, ext.full_name, v, depth)
end
end
end
M test/proto/proto2_basic.proto => test/proto/proto2_basic.proto +29 -0
@@ 48,3 48,32 @@ message WithGroup {
optional int32 n = 5;
}
}
+
+// Bench fixture exercising the proto2-only shapes: required scalar,
+// optional repeated, custom default, a `group` field, and a nested
+// message. Used by bench/bench.lua against both modes.
+message BenchPayload {
+ required int32 id = 1;
+ optional string name = 2 [default = "anonymous"];
+ optional int32 retries = 3 [default = 3];
+ repeated int32 lucky_numbers = 4 [packed = true];
+ repeated string tags = 5;
+ optional Inner inner = 6;
+ optional group Stats = 7 {
+ optional int32 latency_ns = 8;
+ optional int32 attempts = 9;
+ }
+
+ message Inner {
+ required string key = 1;
+ optional int32 weight = 2;
+ }
+
+ // Reserve a range for the file-level extensions declared below.
+ extensions 100 to 199;
+}
+
+extend BenchPayload {
+ optional int32 ext_count = 100;
+ optional string ext_label = 101;
+}
M test/proto2_test.lua => test/proto2_test.lua +46 -0
@@ 188,6 188,52 @@ for _, mode in ipairs(MODES) do
t.assert(s:find('SingleGroup'), 'expected SingleGroup label in: ' .. s)
t.assert_not(s:find('singlegroup'), 'lowercase field name must not appear')
end
+
+ -- ----- Proto2 extensions -----
+
+ g.test_extension_registry_uses_array_view = function()
+ -- The hot encode loop iterates extensions_list (array) rather than
+ -- pairs() over extensions_by_full_name to stay JIT-stable. If a
+ -- future refactor drops the array view, encode silently falls off
+ -- the JIT — pin both indices here.
+ local d = pb.BenchPayload_descriptor
+ t.assert(type(d.extensions_list) == 'table',
+ 'extensions_list array view must exist')
+ t.assert(#d.extensions_list >= 2)
+ t.assert(d.extensions_by_id[100])
+ t.assert(d.extensions_by_full_name['proto2_basic.ext_count'])
+ end
+
+ g.test_extension_round_trip = function()
+ local msg = {
+ id = 7,
+ _extensions = {
+ ['proto2_basic.ext_count'] = 42,
+ ['proto2_basic.ext_label'] = 'tag',
+ },
+ }
+ local dec = pb.BenchPayload_decode(pb.BenchPayload_encode(msg))
+ t.assert_equals(dec.id, 7)
+ t.assert_equals(dec._extensions['proto2_basic.ext_count'], 42)
+ t.assert_equals(dec._extensions['proto2_basic.ext_label'], 'tag')
+ end
+
+ g.test_extension_inline_codegen_walks_them = function()
+ -- Regression pin: the inline (full-mode) generated code added an
+ -- explicit extensions walk after the field loop. Verify that the
+ -- bytes-on-wire match what the runtime codec produces for the
+ -- same input.
+ local full = require('full.proto2_basic.proto2_basic_pb')
+ local runtime = require('runtime.proto2_basic.proto2_basic_pb')
+ local msg = {
+ id = 9,
+ _extensions = {['proto2_basic.ext_count'] = 17},
+ }
+ t.assert_equals(
+ hex(full.BenchPayload_encode(msg)),
+ hex(runtime.BenchPayload_encode(msg)),
+ 'inline and runtime extension emission must match byte-for-byte')
+ end
end
-- Dynamic (source-parsed) proto2: load test/proto/proto2_basic.proto at