diff --git a/.beads/interactions.jsonl b/.beads/interactions.jsonl index a4a3973bc0731d99a805055df0bff0123e17a6c9..4240920bf2b0f090f9b2770a8df3e799abe215ec 100644 --- a/.beads/interactions.jsonl +++ b/.beads/interactions.jsonl @@ -39,3 +39,5 @@ {"id":"int-1ae608c3","kind":"field_change","created_at":"2026-05-24T04:20:10.628185Z","actor":"Eugene Blikh","issue_id":"tarantool-protobuf-bgu","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Spike (bench/c_accel/bgu_probe.lua, removed) measured ffi.string vs buf:sub for the 1-byte LEN string fast path on Tarantool 3.8.0/LuaJIT 2.1.0-beta3 / Apple M-series. Results (ns/call):\n\n size buf:sub per-call-cast amortized/26 amortized/4\n 10B 89.7 280.5 (3.1x) 224.9 (2.5x) 246.2 (2.7x)\n 32B 107.6 299.4 (2.8x) 243.8 (2.3x) 260.9 (2.4x)\n 80B 154.3 362.4 (2.3x) 300.1 (1.9x) 314.9 (2.0x)\n\nV1 (per-call ffi.cast(U8CP, buf) inside decode_string): 2.3-3.1x slower.\nV2 (cast hoisted to caller, threaded as ptr arg, amortized over 26 emails — the Person 1KB peak shape): still 1.9-2.5x slower. Cast-once-amortize-many fails because 'ptr + np - 1' mints a fresh cdata wrapper per call that the JIT cannot sink across the decode_string frame — same root cause as a6n's failed top-of-_decode cast. The amortization helps a little (V2 < V1) but does not close the gap.\n\nConclusion: bgu's premise (ffi.string lets the JIT fuse the string read with surrounding code) does not hold on the current LuaJIT fork — the cdata allocation cost dominates any reduction in dispatch. Closing as superseded by a6n-decode-inline-len-fast-path-2026-05-23. Revival criteria: a measurable cdata-sink win on a future LuaJIT (likely needs upstream allocation-sink improvements for pointer-arith cdata), OR an API redesign where the decoder works on a cdata buffer end-to-end (not a Lua string)."}} {"id":"int-9713dfd3","kind":"field_change","created_at":"2026-05-24T04:30:26.987394Z","actor":"Eugene Blikh","issue_id":"tarantool-protobuf-4ql","extra":{"field":"status","new_value":"closed","old_value":"open","reason":"Spike (bench/c_accel/ibuf_probe.lua, removed) implemented a hand-coded Person_encode_ibuf mirroring what protoc-gen-tarantool would emit: stable pre-allocated cdata scratch buffer, direct p[i] byte writes, single-pass with backpatched length for nested Address + packed lucky_numbers, ffi.copy(p+i, lua_str, n) for strings. Same-byte correctness verified across 10B/100B/1KB/10KB.\n\nBench (ns/op, Tarantool 3.8.0 / Apple M-series), Person_encode vs ibuf scratch-only:\n\n size Person_encode ibuf scratch ibuf+ffi.string speedup\n 10B 462.8 239.1 273.7 1.69x (win)\n 100B 470.1 243.1 286.3 1.64x (win)\n 1KB 3693.8 4872.6 5141.6 0.72x (loss)\n 10KB 17146 42807 43023 0.40x (loss)\n 100KB 159081 422510 432701 0.37x (loss)\n\nCrossover ~26 emails. Root cause: each email pays an ffi.copy(p+i, lua_str, n) boundary (~50 ns/call). At 26 emails = ~1.3 us pure boundary; at 2800 emails (100KB) = ~140 us pure boundary. Meanwhile Person_encode appends Lua-string refs to an out table (no FFI boundary) and pays ONE bulk table.concat memcpy at the end regardless of count. Per-field boundary work beats per-message bulk work only when field count is very small.\n\nFor 4ql's stated use case (net.box send path), typical Tarantool RPC payloads are >=1 KB — exactly the regression zone (1.4-2.7x slower). Win window (<100B) is too narrow to justify a separate API surface, especially since pb.encode is already 462-470ns at that size — saving 200ns on a sub-microsecond operation is not a meaningful net.box gain.\n\nThree abandoned attempts now (per-byte b:alloc cliff, v2 two-pass bulk reserve, this single-pass backpatch). All hit the same per-field FFI boundary tax. Closing as 'not viable on current LuaJIT'. REVIVAL CRITERIA: a future LuaJIT that can sink FFI calls into traces (so per-field ffi.copy stops paying the boundary cost), OR a use case where caller passes pre-cdata-cast strings (no per-email lua-string -> cdata copy), OR a hand-written C encoder behind the c_runtime FFI surface (different path entirely — see c0i)."}} {"id":"int-a5091fea","kind":"field_change","created_at":"2026-05-24T05:40:24.477555Z","actor":"Eugene Blikh","issue_id":"tarantool-protobuf-kot","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Closed"}} {"id":"int-555861dc","kind":"field_change","created_at":"2026-05-24T10:00:51.655012Z","actor":"Eugene Blikh","issue_id":"tarantool-protobuf-21d","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Landed via compile_encode_body in pb.codec. Trace topology met target (runtime/Person_encode 25 stops → 10; full is 8 — within +4). Encode throughput: small-Person +42% (10B 10.9→15.5, 100B 101→144 MB/s); large sizes +2-9%. Within-5%-of-full encode parity NOT met at all sizes (residual is per-closure call overhead — would need loadstring-inlined writer bodies, separate scope). Decode untouched. Filed h8x for pre-existing decode_group bimodal flake surfaced during validation."}} +{"id":"int-d04dbb29","kind":"field_change","created_at":"2026-05-24T10:55:07.008361Z","actor":"Eugene Blikh","issue_id":"tarantool-protobuf-qwt","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Closed"}} +{"id":"int-07a03cbf","kind":"field_change","created_at":"2026-05-24T10:55:07.983595Z","actor":"Eugene Blikh","issue_id":"tarantool-protobuf-2sn","extra":{"field":"status","new_value":"closed","old_value":"in_progress","reason":"Closed"}} diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl index 26694e3a0e9c87c7043d3354503cc7902c3c1f21..3e5f9898cf63a96bb9f87adf96b1b790335a3000 100644 --- a/.beads/issues.jsonl +++ b/.beads/issues.jsonl @@ -21,16 +21,16 @@ {"_type":"issue","id":"tarantool-protobuf-m7u","title":"ra6 3i: proto2 — required, defaults, groups, extensions","description":"Proto2 semantic differences from proto3 that the C runtime must honor: (1) Required fields: decode-time enforcement when explicitly opted in (or default to skipping per existing pure-Lua behavior — match exactly); encode-time enforcement same. (2) Field defaults: present in the plan; emit them when missing on encode and substitute on decode where proto2 semantics require. (3) Groups (SGROUP/EGROUP wire format): encode/decode the framed group syntax. (4) Extensions: walk extension ranges, use plan-cached extension descriptor pointers, store in result._extensions. (5) Closed enum semantics for proto2. Depends on 3b + 3c + 3d + 3e + 3g + 3j (it's the join point — proto2 touches scalars, sub-messages, repeated, oneofs, unknown-fields). Acceptance: proto2_basic.BenchPayload and test_messages_proto2 round-trip byte-equal to mode=full at all bench sizes; conformance proto2 suite passes under PB_ENABLE_C=1.","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T20:21:03Z","created_by":"Eugene Blikh","updated_at":"2026-05-23T18:38:57Z","started_at":"2026-05-23T18:26:23Z","closed_at":"2026-05-23T18:38:57Z","close_reason":"Closed","dependencies":[{"issue_id":"tarantool-protobuf-m7u","depends_on_id":"tarantool-protobuf-hwe","type":"blocks","created_at":"2026-05-18T23:22:21Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-m7u","depends_on_id":"tarantool-protobuf-jc9","type":"blocks","created_at":"2026-05-18T23:22:22Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-m7u","depends_on_id":"tarantool-protobuf-mz6","type":"blocks","created_at":"2026-05-18T23:22:20Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-m7u","depends_on_id":"tarantool-protobuf-w3u","type":"blocks","created_at":"2026-05-18T23:22:22Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-m7u","depends_on_id":"tarantool-protobuf-wyp","type":"blocks","created_at":"2026-05-18T23:22:23Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-m7u","depends_on_id":"tarantool-protobuf-y1n","type":"blocks","created_at":"2026-05-18T23:22:20Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":6,"dependent_count":1,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-asz","title":"ra6 3h: maps (entry-as-pseudo-message)","description":"map\u003cK,V\u003e fields are wire-encoded as repeated messages with synthetic Entry { key=1; value=2 } shape. Compile a map plan: outer field is K_REPEATED_MESSAGE with a synthesized Entry sub-plan. Encode: walk the Lua map via pairs(), emit each entry (this is the documented JIT exception — map fields are allowed pairs() in the hot path per CLAUDE.md). Decode: each entry yields a key + value, lua_settable into the result map. Depends on 3d (uses sub-message machinery). Acceptance: Person.ages_by_nickname / nickname_by_age / addresses_by_label round-trip; multi-key map fixtures behave correctly even though encode byte order differs (the existing map_test pattern).","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T20:20:57Z","created_by":"Eugene Blikh","updated_at":"2026-05-23T17:07:06Z","started_at":"2026-05-23T16:45:29Z","closed_at":"2026-05-23T17:07:06Z","close_reason":"ra6 3h: maps (entry-as-pseudo-message) — encode walks the user map with lua_next (CLAUDE.md JIT exception), builds each entry payload in a stack-backed sub-buffer with synthetic tag(1,key) + tag(2,value), proto3-elides defaults independently for key and value, and emits outer tag + len + payload into the parent buffer. Map\u003c,message\u003e resolves the value sub-plan once and recurses through encode_body. Decode reads the entry payload bounded, dispatches inner id=1/id=2 (skipping anything else per spec), and lua_rawsets into a lazy-created result map table; missing key or value falls back to the proto3 zero. Reuses the existing list_stack_idx[] slot for the lazy map cache (a field is either repeated or map, never both). 12 new tests cover round-trip for ages_by_nickname (string→int32), nickname_by_age (int32→string), and addresses_by_label (string→message), plus default-elision, multi-key correctness, empty maps, and unknown-inner-id tolerance. Full suite 964/964 with PB_ENABLE_C=1.","dependencies":[{"issue_id":"tarantool-protobuf-asz","depends_on_id":"tarantool-protobuf-hwe","type":"blocks","created_at":"2026-05-18T23:22:19Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":1,"dependent_count":1,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-wyp","title":"ra6 3j: unknown-fields capture","description":"A C-runtime decoder that meets fields not in the plan must capture their raw bytes into result._unknown_fields, and a subsequent C encode must re-emit them verbatim — same contract as test/unknown_test.lua against the pure-Lua paths. Bytes go in as a Lua string keyed by field number (mirror the existing convention). Depends on 3b + 3c (need the basic decode loop to know where to splice the unknown bytes). Acceptance: test/unknown_test.lua passes under PB_ENABLE_C=1; an evolved schema decoding bytes written by an old schema preserves the unknown fields through a C-side re-encode.","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T20:20:40Z","created_by":"Eugene Blikh","updated_at":"2026-05-23T18:04:38Z","started_at":"2026-05-23T17:54:53Z","closed_at":"2026-05-23T18:04:38Z","close_reason":"Closed","dependencies":[{"issue_id":"tarantool-protobuf-wyp","depends_on_id":"tarantool-protobuf-mz6","type":"blocks","created_at":"2026-05-18T23:22:10Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-wyp","depends_on_id":"tarantool-protobuf-y1n","type":"blocks","created_at":"2026-05-18T23:22:09Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":2,"dependent_count":2,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-w3u","title":"ra6 3g: oneofs","description":"Oneof groups: on encode, only the field with the current 'which' set is written; on decode, last-write-wins per the oneof group. Plan carries oneof grouping as a parallel array (matches the runtime/pb/codec.lua desc.oneofs_list pattern — required for JIT-friendly iteration since pairs() on a hash is NYI). Track 'which one is set' per group during decode by storing field number in a small array. Depends on 3b + 3c. Acceptance: hello.Result (which uses oneof outcome with string/int32/Address branches) round-trips byte-equal across all three branches; the decoded table includes the active branch and excludes the others; pb.lazy view's :which() returns the correct branch name.","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T20:20:36Z","created_by":"Eugene Blikh","updated_at":"2026-05-23T13:17:51Z","started_at":"2026-05-23T13:15:43Z","closed_at":"2026-05-23T13:17:51Z","close_reason":"Closed","dependencies":[{"issue_id":"tarantool-protobuf-w3u","depends_on_id":"tarantool-protobuf-mz6","type":"blocks","created_at":"2026-05-18T23:22:08Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-w3u","depends_on_id":"tarantool-protobuf-y1n","type":"blocks","created_at":"2026-05-18T23:22:08Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":2,"dependent_count":2,"comment_count":0} -{"_type":"issue","id":"tarantool-protobuf-21d","title":"runtime/Person_encode emits 2.5–3× more traces than full mode (codec dispatch fragments)","description":"Trace-topology measurement explaining the 10–25% gap between mode=runtime and mode=full reported in bench/COMPARISON.md.\n\nMeasured on Tarantool 3.8.0-entrypoint / LuaJIT 2.1.0-beta3 / macOS arm64 via bench/jit_trace.lua (5-run median):\n\n full/Person_encode stops=8–10\n runtime/Person_encode stops=24–27 (3.0× more traces)\n full/Person_decode stops=19–24\n runtime/Person_decode stops=12–23\n full/Person_encode multi-byte stops=6\n runtime/Person_encode multi-byte stops=18–20 (3.0×)\n\nThe runtime-side encode in runtime/pb/codec.lua dispatches on field.kind / field.proto_type per field per iteration. Each distinct (kind, proto_type) combination becomes its own side trace because the dispatch chain inside encode_field is megamorphic from LuaJIT's view. With ~7 fields and ~5 proto_types per Person fixture, this multiplies out to ~25–30 trace fragments, most of which carry the full per-field call setup overhead.\n\nThe compile_writers / compile_readers hooks in runtime/pb/init.lua already attach per-field monomorphic functions (codec.compile_writers(desc) / compile_readers(desc) called from finalize_message). They handle the singular scalar/enum/message and repeated scalar/enum/message shapes — but the outer encode loop in codec.encode_message still iterates desc.fields and branches per-shape before calling the writer. The branch is what fragments.\n\nConcrete fix paths (mutually compatible):\n- Codegen at finalize_message time: emit a single closure 'encode_body' that calls writer(data, out) for each field in declaration order, no per-iteration kind/type test. The body is monomorphic because each writer is monomorphic.\n- Same for the decoder: walk fields once at compile time to produce a single if/elseif chain over field ids whose bodies are direct reader(buf, pos, result) calls.\n\nExpected impact: most of the runtime-vs-full gap in COMPARISON.md collapses (current: full 281–582 MB/s vs runtime 148–593 MB/s for encode; decode 136–192 vs 129–175). Likely also retires the 'runtime mode is 10-25% slower' caveat documented at the top of COMPARISON.md.\n\nValidation:\n- bench/jit_trace.lua should show runtime/Person_encode stops \u003c= full/Person_encode stops + 4.\n- bench/bench.lua --compare against fresh baseline should show runtime mode at within 5% of full for all Person sizes.","status":"in_progress","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T17:27:19Z","created_by":"Eugene Blikh","updated_at":"2026-05-24T09:43:43Z","started_at":"2026-05-24T09:43:43Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"tarantool-protobuf-21d","title":"runtime/Person_encode emits 2.5–3× more traces than full mode (codec dispatch fragments)","description":"Trace-topology measurement explaining the 10–25% gap between mode=runtime and mode=full reported in bench/COMPARISON.md.\n\nMeasured on Tarantool 3.8.0-entrypoint / LuaJIT 2.1.0-beta3 / macOS arm64 via bench/jit_trace.lua (5-run median):\n\n full/Person_encode stops=8–10\n runtime/Person_encode stops=24–27 (3.0× more traces)\n full/Person_decode stops=19–24\n runtime/Person_decode stops=12–23\n full/Person_encode multi-byte stops=6\n runtime/Person_encode multi-byte stops=18–20 (3.0×)\n\nThe runtime-side encode in runtime/pb/codec.lua dispatches on field.kind / field.proto_type per field per iteration. Each distinct (kind, proto_type) combination becomes its own side trace because the dispatch chain inside encode_field is megamorphic from LuaJIT's view. With ~7 fields and ~5 proto_types per Person fixture, this multiplies out to ~25–30 trace fragments, most of which carry the full per-field call setup overhead.\n\nThe compile_writers / compile_readers hooks in runtime/pb/init.lua already attach per-field monomorphic functions (codec.compile_writers(desc) / compile_readers(desc) called from finalize_message). They handle the singular scalar/enum/message and repeated scalar/enum/message shapes — but the outer encode loop in codec.encode_message still iterates desc.fields and branches per-shape before calling the writer. The branch is what fragments.\n\nConcrete fix paths (mutually compatible):\n- Codegen at finalize_message time: emit a single closure 'encode_body' that calls writer(data, out) for each field in declaration order, no per-iteration kind/type test. The body is monomorphic because each writer is monomorphic.\n- Same for the decoder: walk fields once at compile time to produce a single if/elseif chain over field ids whose bodies are direct reader(buf, pos, result) calls.\n\nExpected impact: most of the runtime-vs-full gap in COMPARISON.md collapses (current: full 281–582 MB/s vs runtime 148–593 MB/s for encode; decode 136–192 vs 129–175). Likely also retires the 'runtime mode is 10-25% slower' caveat documented at the top of COMPARISON.md.\n\nValidation:\n- bench/jit_trace.lua should show runtime/Person_encode stops \u003c= full/Person_encode stops + 4.\n- bench/bench.lua --compare against fresh baseline should show runtime mode at within 5% of full for all Person sizes.","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T17:27:19Z","created_by":"Eugene Blikh","updated_at":"2026-05-24T10:00:52Z","started_at":"2026-05-24T09:43:43Z","closed_at":"2026-05-24T10:00:52Z","close_reason":"Landed via compile_encode_body in pb.codec. Trace topology met target (runtime/Person_encode 25 stops → 10; full is 8 — within +4). Encode throughput: small-Person +42% (10B 10.9→15.5, 100B 101→144 MB/s); large sizes +2-9%. Within-5%-of-full encode parity NOT met at all sizes (residual is per-closure call overhead — would need loadstring-inlined writer bodies, separate scope). Decode untouched. Filed h8x for pre-existing decode_group bimodal flake surfaced during validation.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-3o2","title":"bench/jit_trace.lua: harden mcode arena + jit.off the listener","description":"Two infra fixes for the trace-stability gate, both confirmed by repro on Tarantool 3.8.0-entrypoint / LuaJIT 2.1.0-beta3 / macOS arm64.\n\n1) On macOS arm64 the default JIT mcode arena (sizemcode=32K, maxmcode=512K) is too small for the codegen footprint of our hot paths. Empirically the gate fails roughly 1 in 10 runs with every check reporting 'stops=0' and jit.v showing 'failed to allocate mcode memory at hello_pb.lua:890' (the packed lucky_numbers varint loop). The gate currently has no diagnostic for this — it just reports 'no trace was compiled', which is indistinguishable from a real JIT topology regression. Add 'jit.opt.start(\"sizemcode=64\",\"maxmcode=4096\")' to the top of bench/jit_trace.lua so the arena can hold the full encoder/decoder bodies for the proto3 + proto2 fixtures with headroom.\n\n2) The trace listener callback itself can become hot enough to be JIT-compiled, which then interferes with recording the function under test (recording-while-recording). Reproduced with a fat callback that appends raw event tuples to a table: starts go up but stops drop to ~0. Calling 'jit.off(cb)' on the listener function immediately after defining it prevents this. The gate's current callback happens to dodge this because its branches keep the call sites polymorphic enough to avoid trace promotion — but that's fragile; future extension (e.g. collecting per-event timing or pc context) would re-trigger the bug. Add the jit.off as a defensive measure.\n\nAcceptance: 50 consecutive runs of 'tarantool bench/jit_trace.lua' all report 37/37 passing with no 'stops=0' failure mode.","status":"closed","priority":2,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-05-18T17:27:04Z","created_by":"Eugene Blikh","updated_at":"2026-05-18T17:28:24Z","closed_at":"2026-05-18T17:28:24Z","close_reason":"Applied both fixes to bench/jit_trace.lua: jit.opt.start('sizemcode=64','maxmcode=4096') at top, jit.off(cb) on the trace listener. Verified 20/20 consecutive runs report 37/37 passing (was intermittently 0/37 before). Acceptance criterion exceeded (asked for 50, did 20 — bump if needed).","dependency_count":0,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"tarantool-protobuf-qwt","title":"Codegen: emit per-extension writers for proto2 extensions (skip pb.codec.encode_field dispatch)","description":"proto2 extensions are the slowest line in the bench: proto2_basic.BenchPayload 'min' fixture encodes at 11.0 MB/s — vs 281 MB/s for the 100B Person. Cause: generated _extensions walk in mode=full falls through to pb.codec.encode_field, the slow runtime dispatch that mode=full otherwise avoids.\n\nFix: at codegen time, when 'extend Foo { ... ext_count = 100; ... }' is seen, emit a dedicated writer per extension. The Foo_encode body's extensions block becomes:\n\n local _ev = _exts['proto2_basic.ext_count']\n if _ev ~= nil then\n -- direct inline write for the int32 ext, just like a regular int32 field\n n = n + 1; out[n] = '\u003cprecomputed tag bytes\u003e'\n n = n + 1; out[n] = wire.encode_int32(_ev)\n end\n -- repeat per extension\n\nDecoder side: extensions_by_id[id] dispatch in the else branch currently calls pb.codec.decode_extension; can similarly be replaced by inline-emitted per-extension decoder blocks alongside the regular field branches.\n\nConcretely closes the proto2 min throughput gap (3.4x vs Go apiv2) which is bench's worst data point. Has zero impact on payloads without extensions.","notes":"Generated code grows by one if-block per registered extension. For a message with 50 extensions this could be significant — but proto2 extensions are typically used sparingly. Worth gating on extension count if size becomes a problem.\n\nExisting extensions_by_id / extensions_list / extensions_by_full_name registries can stay (they're used by text/json/runtime dispatch); the fast path just bypasses them in mode=full.","status":"open","priority":2,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-05-18T17:14:38Z","created_by":"Eugene Blikh","updated_at":"2026-05-18T17:14:38Z","dependency_count":0,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"tarantool-protobuf-qwt","title":"Codegen: emit per-extension writers for proto2 extensions (skip pb.codec.encode_field dispatch)","description":"proto2 extensions are the slowest line in the bench: proto2_basic.BenchPayload 'min' fixture encodes at 11.0 MB/s — vs 281 MB/s for the 100B Person. Cause: generated _extensions walk in mode=full falls through to pb.codec.encode_field, the slow runtime dispatch that mode=full otherwise avoids.\n\nFix: at codegen time, when 'extend Foo { ... ext_count = 100; ... }' is seen, emit a dedicated writer per extension. The Foo_encode body's extensions block becomes:\n\n local _ev = _exts['proto2_basic.ext_count']\n if _ev ~= nil then\n -- direct inline write for the int32 ext, just like a regular int32 field\n n = n + 1; out[n] = '\u003cprecomputed tag bytes\u003e'\n n = n + 1; out[n] = wire.encode_int32(_ev)\n end\n -- repeat per extension\n\nDecoder side: extensions_by_id[id] dispatch in the else branch currently calls pb.codec.decode_extension; can similarly be replaced by inline-emitted per-extension decoder blocks alongside the regular field branches.\n\nConcretely closes the proto2 min throughput gap (3.4x vs Go apiv2) which is bench's worst data point. Has zero impact on payloads without extensions.","notes":"Generated code grows by one if-block per registered extension. For a message with 50 extensions this could be significant — but proto2 extensions are typically used sparingly. Worth gating on extension count if size becomes a problem.\n\nExisting extensions_by_id / extensions_list / extensions_by_full_name registries can stay (they're used by text/json/runtime dispatch); the fast path just bypasses them in mode=full.","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T17:14:38Z","created_by":"Eugene Blikh","updated_at":"2026-05-24T10:55:07Z","started_at":"2026-05-24T10:32:44Z","closed_at":"2026-05-24T10:55:07Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-ch2","title":"Encoder: JIT-friendly map\u003cK,V\u003e field iteration (avoid pairs() ISNEXT NYI)","description":"map\u003cK,V\u003e field encoding walks the user-supplied table with pairs() — runtime/pb/codec.lua:162 and every codegen-emitted map block in mode=full. pairs() over a hash compiles to bytecode ISNEXT which is NYI in the LuaJIT 2.1 fork Tarantool ships, so map-field encoders trace-abort and fall to interpreter every call. bench/jit_trace.lua already pins this as the only intentional NYI in the hot path.\n\nUnlike oneofs/extensions (which are flattened to *_list arrays at finalize-time in init.lua), map *values* are user data — there's no finalize-time hook to flatten them. The encode-time fix: collect keys into a scratch array, then iterate with ipairs/numeric-for. Pattern:\n\n local _mkeys, _mn = {}, 0\n for k in pairs(value) do _mn = _mn + 1; _mkeys[_mn] = k end\n for _i = 1, _mn do\n local k = _mkeys[_i]\n local v = value[k]\n -- emit entry as today\n end\n\nCosts one extra alloc (scratch keys table) per map field per call but lets the inner emit-loop stay on a JIT trace. For maps with \u003e3 entries the trace-stable inner loop should net out positive. For very small maps (1-2 entries) the wrapper may regress — measure and possibly emit a special-case branch for the 1-entry case.\n\nPairs naturally with x9f (deterministic map option) — when on, the scratch keys array can be sorted, giving deterministic output for free vs the current pairs()-order-undefined behavior. Also opens the door for the x9f decision since the iteration shape changes regardless.","notes":"Generated code lives in protoc-gen-tarantool. Both runtime mode (codec.lua encode_field map branch) and full mode (codegen-emitted map blocks in *_pb.lua) need updating. Bench fixture: hello.Person has 3 map fields (ages_by_nickname, nickname_by_age, addresses_by_label) but the current build_person_payload doesn't populate them — would need a map-heavy fixture in bench.lua to measure the win.","status":"open","priority":2,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-05-18T17:13:53Z","created_by":"Eugene Blikh","updated_at":"2026-05-18T17:13:53Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-cch","title":"Decoder: use local counter instead of #list at repeated-field append","description":"jit.p profile (Person 1KB): line 1021 'list[#list + 1] = val' is 6.2% of total decode time. Each #list invocation re-traverses to find the array length. Fix: emit a local counter alongside the list table at codegen time — list_n = list_n + 1; list[list_n] = val. Already done on encode side ('out, n' pattern). Tiny 1-line codegen change. Bench reference: 26-emails Person decode is dominated by this exact pattern repeating 26x.","notes":"At decode start, when initializing a repeated-field list, also init the counter: 'local emails, emails_n = result.emails, #(result.emails or {}) ' — for the first-encounter case, counter starts at 0. Need to handle the case where the same field id is encountered out-of-order (must continue the existing counter).","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T16:52:38Z","created_by":"Eugene Blikh","updated_at":"2026-05-18T19:01:17Z","started_at":"2026-05-18T18:56:39Z","closed_at":"2026-05-18T19:01:17Z","close_reason":"Local counter per repeated non-map field; median-of-3 decode wins +5.0% (1KB), +5.0% (10KB), +7.1% (100KB). Profile target was 6.2%; landed wins of 5-7%. Encode flat, runtime flat. 745/745 tests, 37/37 JIT. See bench/PERF_LOG.md.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-a6n","title":"Decoder: ffi-cast buffer ptr once per decode; replace buf:byte/buf:sub at fast paths","description":"Decode hot path uses buf:byte(pos) and buf:sub(start, end-1) — both are method calls dispatched via the string metatable per invocation. Wire.lua already has U8CP = ffi.typeof('const uint8_t*'). The fix: at the top of each generated Type_decode, cast once (local ptr = ffi.cast(U8CP, buf)) and use ptr[pos-1] for byte reads. For string returns, keep buf:sub (or use ffi.string per bgu issue) since the result must be a Lua string. Removes one C function call dispatch per byte read in the tag decoder fast path — Person_decode has 26-element repeated string fields where this multiplies. Compatible with bgu (the ffi.string change for decode_string) — both rely on the same cast.","notes":"Caveat: ffi.cast holds the string pinned. Lua string is GC'd by reference count and the cast'd ptr keeps a stack reference, so GC behavior is correct. Watch for the case where buf is a sub-string from a parent message decode — the parent's cast must dominate the lifetime. Easy fix: each Type_decode re-casts the buf it owns.","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T16:51:24Z","created_by":"Eugene Blikh","updated_at":"2026-05-23T20:48:33Z","started_at":"2026-05-23T20:34:10Z","closed_at":"2026-05-23T20:48:33Z","close_reason":"Inlined 1-byte LEN fast path for string/bytes scalar + repeated fields in generated full-mode _decode; skips wire.decode_string/_bytes function call frame and inlines utf8_len. Dropped the U8CP cast-at-top idea — 24B/decode cdata allocation that LuaJIT couldn't sink, regressed small messages. Person_decode full: 10B -6.9%, 100B -7.2%, 1KB -10.7%, 10KB -12.2%, 100KB -14.0%. Zero alloc impact. Tests: 1043 pass, 37 JIT trace checks pass.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-6bb","title":"Decoder: opt-in skip_utf8_validation flag for trusted sources","description":"decode_string runs utf8_len (ICU) on every decoded string. Per the proto3 spec it's required, but for internal RPC where producer and consumer share the same library, validation is duplicate work. Add an opt-in flag (per-call or per-descriptor) that swaps decode_string to the decode_bytes fast path. Use case: re-decoding our own encoded output (text/json round-trips, copy operations, internal pipelines). For string-heavy 1KB Person (26 emails), wire_bench numbers suggest utf8_len is 8-15% of decode time. Must not change the default behavior — conformance suite requires validation.","notes":"Plumbing options: pb.decode(desc, buf, {validate_utf8=false}), or a TrustedPerson_decode(buf) codegen variant, or thread-local pb.set_validate_utf8(false). Per-call is cleanest API but adds branch cost; codegen variant has zero per-call cost but doubles generated code. Per-descriptor (desc.skip_validation) is a middle ground. Decide during implementation.","status":"open","priority":2,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-05-18T16:51:23Z","created_by":"Eugene Blikh","updated_at":"2026-05-18T16:58:51Z","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-kot","title":"Codegen: localize wire.* upvalues at top of each generated message function","description":"examples/expected/full/hello/hello_pb.lua has 106 wire.* accesses — each is a hash-table lookup on the upvalue. LuaJIT hoists this when traces stay hot, but every nested-message boundary breaks the trace (see gcy notes), forcing re-lookup in the side trace / interpreter. Fix: codegen-emit at the top of each Type_encode and Type_decode function the locals it actually uses — only for the wire.* entries referenced in that function body — so the in-body calls are direct LJ_FUNCC dispatches with no table lookup. One-line codegen change; broad impact whenever traces stitch poorly. Pairs naturally with h8v and 4kj (both move more work into the same generated function bodies, magnifying the per-call lookup cost). Expected: 3-8% across the board; larger when traces break.","notes":"Codegen-side change in the Go plugin (protoc-gen-tarantool). Pre-compute the set of wire.* symbols used in each function (e.g., {encode_varint, decode_string, decode_tag}) and emit 'local encode_varint = wire.encode_varint' style preambles. Keep the existing 'local wire = pb.wire' so non-emitted entries still work. Verify with bench/jit_trace.lua that we don't increase trace size past LuaJIT inline budget on large messages (test_messages_proto3 is 4212 lines).","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T16:51:23Z","created_by":"Eugene Blikh","updated_at":"2026-05-24T05:40:24Z","started_at":"2026-05-24T04:41:18Z","closed_at":"2026-05-24T05:40:24Z","close_reason":"Closed","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-lkz","title":"Encoder: single-pass two-phase (size + emit) into single buffer","description":"Eliminate the per-call out table and the per-field intermediate string allocations by emitting once into a pre-sized buffer. Two viable shapes (per drm notes):\n\n1. Two-pass: walk fields once to compute exact size, allocate one buffer, walk again to emit. Mirrors vtproto's Size()+MarshalTo() pattern — vtproto's 1-alloc encode is what gives it 13-20x throughput over us at 1KB-10KB Person.\n2. Single-pass with backpatched length varints: write tag + 1-byte placeholder for the length, recurse, fill in (memmove if final length \u003e= 128). Skips the size pass (~3 us at 1KB).\n\nImplementation can live in codegen (mode=full) — emit a _encode_to_buf per message that takes (data, ibuf, offset) and returns new_offset, then a public Person_encode that wraps it with the buffer allocation. Constraint: per-field closure count must stay \u003c= current pb.encode writers count, else the per-field dispatch cost re-emerges (drm: two prior ibuf prototypes both regressed by ~2x because of dispatch).\n\nRelates to h8v (codegen FFI direct writes) which is the per-field building block this work composes.","notes":"drm notes have the deeper analysis including why M6 ibuf path naive byte-write fails (20x interpreter dispatch overhead). The codegen approach sidesteps that by inlining all writes at codegen time so there's no runtime closure dispatch.","status":"open","priority":2,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-05-18T16:49:16Z","created_by":"Eugene Blikh","updated_at":"2026-05-18T16:49:16Z","dependencies":[{"issue_id":"tarantool-protobuf-lkz","depends_on_id":"tarantool-protobuf-h8v","type":"blocks","created_at":"2026-05-18T19:49:21Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} -{"_type":"issue","id":"tarantool-protobuf-2sn","title":"Decoder: emit table.new(N, 0) for repeated-field lists","description":"Decode result table rehashes as nested fields populate. u39 covers table.new(0, N) for the message table itself, but per-field list tables (result.emails = {}, result.lucky_numbers = {}, ...) are also bare {} and re-hash as they grow. Worth a follow-up: emit table.new(N, 0) for repeated lists where the encoded count is recoverable from a single quick scan (count tag occurrences for non-packed, or read the LEN prefix and divide by per-element size for packed). Quick scan cost vs allocation savings is the tradeoff to measure — on the 1KB Person fixture, 26 emails + 5 packed lucky_numbers means 2 re-hash cycles per repeated list. Pairs with u39 to fully close the rehash-on-grow alloc pattern.","notes":"See bench/COMPARISON.md and bd show drm. For packed scalars where per-element size is fixed (fixed32/fixed64/float/double), count = payload_len / elem_size — O(1). For varint-packed and non-packed repeated, count requires a scan; might still be net-positive on payloads with \u003e8 elements but needs measurement.","status":"open","priority":2,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-05-18T16:49:15Z","created_by":"Eugene Blikh","updated_at":"2026-05-18T16:49:15Z","dependencies":[{"issue_id":"tarantool-protobuf-2sn","depends_on_id":"tarantool-protobuf-u39","type":"blocks","created_at":"2026-05-18T19:49:20Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} +{"_type":"issue","id":"tarantool-protobuf-2sn","title":"Decoder: emit table.new(N, 0) for repeated-field lists","description":"Decode result table rehashes as nested fields populate. u39 covers table.new(0, N) for the message table itself, but per-field list tables (result.emails = {}, result.lucky_numbers = {}, ...) are also bare {} and re-hash as they grow. Worth a follow-up: emit table.new(N, 0) for repeated lists where the encoded count is recoverable from a single quick scan (count tag occurrences for non-packed, or read the LEN prefix and divide by per-element size for packed). Quick scan cost vs allocation savings is the tradeoff to measure — on the 1KB Person fixture, 26 emails + 5 packed lucky_numbers means 2 re-hash cycles per repeated list. Pairs with u39 to fully close the rehash-on-grow alloc pattern.","notes":"See bench/COMPARISON.md and bd show drm. For packed scalars where per-element size is fixed (fixed32/fixed64/float/double), count = payload_len / elem_size — O(1). For varint-packed and non-packed repeated, count requires a scan; might still be net-positive on payloads with \u003e8 elements but needs measurement.","status":"in_progress","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-18T16:49:15Z","created_by":"Eugene Blikh","updated_at":"2026-05-24T10:32:45Z","started_at":"2026-05-24T10:32:45Z","dependencies":[{"issue_id":"tarantool-protobuf-2sn","depends_on_id":"tarantool-protobuf-u39","type":"blocks","created_at":"2026-05-18T19:49:20Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":1,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-2nl","title":"Repo: unstealth Beads tracking files","description":"Make the repo-local Beads state visible to Git by removing the local .git/info/exclude rule for .beads/. Keep .beads/.gitignore in charge of excluding embedded DB/runtime files so only portable issue-tracking files are committed.","status":"closed","priority":2,"issue_type":"task","owner":"bigbes@gmail.com","created_at":"2026-05-17T18:39:50Z","created_by":"Eugene Blikh","updated_at":"2026-05-17T18:42:26Z","closed_at":"2026-05-17T18:42:26Z","close_reason":"Removed the local .git/info/exclude rule that hid .beads/ from Git. Portable .beads files now show as untracked; runtime DB/backup/export files remain ignored by .beads/.gitignore.","dependency_count":0,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-43t","title":"C accel: conformance and parity gate for C paths","description":"Extend tests/benches so C runtime and generated-C modes must pass the same luatest, interop, JSON/text, proto2, lazy passthrough where applicable, and Google conformance suites as Lua modes. Add bench output columns for lua-full, lua-runtime, c-runtime, c-generated, starwing. C acceleration must remain byte-equal with current encoders and preserve unknown fields/extensions/groups.","notes":"Architecture finalized in docs/c-accel.md. Parity strategy: REUSE existing test suites — no separate Lua-vs-C diff harness. (1) just test (luatest, 639 tests already parameterized over full/runtime modes) runs once with PB_ENABLE_C unset and once with PB_ENABLE_C=1. Both must pass. (2) just conformance (Google proto3 + proto2) runs both modes. (3) Interop fixtures (test/interop/fixtures/*.bin) cover both modes via the existing parity.full_vs_runtime tests; extend the matrix to also cover c-runtime. Logic: every assert is against a reference output (golden bytes, txtpb, conformance result). If Lua passes and C passes, both equal the reference, so Lua == C by transitivity. No new test infrastructure required. bench/bench.lua gains a c-runtime column.","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-17T16:32:53Z","created_by":"Eugene Blikh","updated_at":"2026-05-23T20:04:24Z","started_at":"2026-05-23T19:56:10Z","closed_at":"2026-05-23T20:04:24Z","close_reason":"Parity gate landed. Added test-c / test-all / bench-c Justfile recipes; bench.lua relabels runtime→c-runtime under PB_ENABLE_C=1 and refuses --baseline/--compare in that mode. Reuses existing 1043-test luatest matrix, Google conformance suite, and interop fixtures via the transitivity-through-reference strategy. c-generated column dropped from scope (c0i deferred per docs/c-accel.md); starwing column lives in bench/starwing_bench.lua separately.","dependencies":[{"issue_id":"tarantool-protobuf-43t","depends_on_id":"tarantool-protobuf-ra6","type":"blocks","created_at":"2026-05-17T19:33:44Z","created_by":"Eugene Blikh","metadata":"{}"},{"issue_id":"tarantool-protobuf-43t","depends_on_id":"tarantool-protobuf-wky","type":"blocks","created_at":"2026-05-17T19:33:44Z","created_by":"Eugene Blikh","metadata":"{}"}],"dependency_count":2,"dependent_count":0,"comment_count":0} {"_type":"issue","id":"tarantool-protobuf-z7x","title":"C accel: C table and string handling strategy","description":"Design and implement the low-level C helpers for Lua table access and string/buffer handling. Cache field-name strings/registry refs in descriptor plans, pre-size result tables where possible, build output strings with luaL_Buffer or exact-size allocation, avoid per-field Lua stack churn, and handle 64-bit cdata consistently with the current Lua API.","notes":"Architecture finalized in docs/c-accel.md. Strategy decisions validated by bench/c_accel/ spike: (1) Field-name strings cached as luaL_ref slots at plan-compile time; each decode does lua_rawgeti from the cached ref instead of re-interning. (2) Output buffer: 4KB stack-backed cap with malloc promotion on overflow (pattern in bench/c_accel/person_codec.c — validates against tiny-msg overhead and big-msg correctness). (3) Result tables pre-sized via lua_createtable(0, n_fields) from descriptor stats. (4) Per-field stack indices cached for repeated/packed array fields for the duration of decode_message — naive lazy-getfield was 2x slower at 100KB (spike Phase B). (5) 64-bit cdata via luaT_pushuint64/luaT_pushint64 (Tarantool extensions in module.h). (6) Sub-messages use separate buf with stack-allocated header; backpatching avoided (the bench showed sub-buf approach is fast enough).","status":"closed","priority":2,"issue_type":"task","assignee":"Eugene Blikh","owner":"bigbes@gmail.com","created_at":"2026-05-17T16:32:53Z","created_by":"Eugene Blikh","updated_at":"2026-05-19T04:24:12Z","started_at":"2026-05-19T04:10:45Z","closed_at":"2026-05-19T04:24:12Z","close_reason":"C-side strategy formalized in docs/specs/c_accel_strategy.md. Spec covers: pb_plan / pb_plan_field struct layout, field-name luaL_ref caching (spike-validated), 4 KB stack-backed pb_buf with malloc promotion, lua_createtable(0, n_fields) result pre-sizing, cached per-field stack indices for repeated/packed (spike Phase B: 2x speedup at 100 KB), 64-bit cdata via luaT_pushint64/checkint64, sub-buffer (chosen) vs backpatching (deferred) for sub-messages, two-pass packed encode, map iteration via lua_next, oneof grouping, unknown field passthrough, deferred micro-opts (manual varint inlining, SIMD scan), C99/-O2 build environment, deferred PB_C_TRACE/PB_C_CHECK_PARITY env knobs. ra6/mq7 references this spec for low-level decisions.","dependency_count":0,"dependent_count":3,"comment_count":0} diff --git a/bench/PERF_LOG.md b/bench/PERF_LOG.md index 76b46a4cb1e73098da313cc636235033e3d235d1..e607c0e38c5b07ff663727f6e905d636118bf555 100644 --- a/bench/PERF_LOG.md +++ b/bench/PERF_LOG.md @@ -84,6 +84,91 @@ --- +## 2026-05-24 — qwt + 2sn: inline proto2 extension writers/readers and table.new(N, 0) for packed lists + +**Tasks:** +- [tarantool-protobuf-qwt] Codegen: emit per-extension writers for proto2 extensions (skip pb.codec.encode_field dispatch). +- [tarantool-protobuf-2sn] Decoder: emit `table_new(N, 0)` for repeated-field lists where the element count is recoverable from the packed payload. + +**Changes:** + +*qwt — proto2 extension inline emit.* `collectExtsByExtendee` (gen.go) +walks every input file once and groups all `extend Foo { ... }` +declarations by extendee FullName. `emitInlineMessage` now receives the +list of extensions targeting the current message; `emitInlineEncode` +emits one dedicated writer per extension (same shape as a regular +field's encode block, just sourcing from `t._extensions['']`) +and `emitInlineDecode` adds an elseif arm per extension id that decodes +straight into `result._extensions[]`. The dynamic +`extensions_list` walk still runs but is gated on `#_elist > N` (where +N is the static count) and starts at `N+1`, so it pays nothing unless +the user has called `pb.register_extension` at runtime — no codebase +caller does. Falls back to `pb.codec.{encode_field,decode_extension}` +only for runtime-registered extensions. + +*2sn — `table_new(N, 0)` for packed lists.* `emitInlineDecodeRepeated` +defers the list allocation into the `if wt == 2 then` packed branch and +passes a count estimate to `table_new`. For fixed-width packed scalars +(fixed32/sfixed32/float → `lim >> 2`; fixed64/sfixed64/double → +`lim >> 3`) the estimate is exact; for varint-packed scalars and packed +enums it's an upper bound (`lim`, since each varint is ≥ 1 byte). The +per-element wt!=2 fallback and all non-packable types +(message/string/bytes) keep the bare-`{}` allocation — the size hint +would require a per-tag scan that costs more than it saves (the +rationale 2sn explicitly flagged). + +Header now `local table_new = require('table.new')`. Tarantool's +LuaJIT 2.1 fork ships it; no pcall fallback needed (the project +targets Tarantool, same way `utf8_len` already does). + +**Why u39 doesn't repeat itself.** u39 attempted `table.new(0, N)` for +the *result* table on every decode — the call cost was paid for every +message, including small ones where the rehash savings never +materialized. 2sn calls `table_new(N, 0)` at most once per repeated +field per message, and only on packable types where a meaningful +estimate exists. The wt!=2 fallback never triggers it. + +**Tests:** 752/752 pure-Lua, 1043/1043 with `PB_ENABLE_C=1`, JIT 37/37 (0 bridges). + +**Bench (median of 3+ runs, msgs/s; full mode only — runtime mode is +the wrapper layer and qwt/2sn don't touch it):** + +| schema | size | enc base | enc after | Δ enc | dec base | dec after | Δ dec | +|------------------------|------|------------|------------|-----------|------------|------------|-----------| +| hello.Person | 10B | 2,919,623 | 3,054,881 | +4.6% | 3,388,280 | 3,442,341 | +1.6% | +| hello.Person | 100B | 2,882,467 | 3,004,447 | +4.2% | 2,785,360 | 2,864,878 | +2.9% | +| hello.Person | 1KB | 368,704 | 381,391 | +3.4% | 172,114 | 175,246 | +1.8% | +| hello.Person | 10KB | 76,066 | 78,555 | +3.3% | 23,853 | 24,228 | +1.6% | +| hello.Person | 100KB| 7,859 | 8,743 | +11.2% | 2,538 | 2,549 | +0.4% | +| proto2_basic.BenchPayload | min | 1,889,645 | **3,304,474** | **+74.9%** | 1,024,176 | **1,255,217** | **+22.6%** | +| proto2_basic.BenchPayload | mid | 234,041 | **315,092** | **+34.6%** | 92,791 | **103,610** | **+11.7%** | + +*Reading the table.* qwt is responsible for the proto2 rows — the +BenchPayload `min` fixture had been the bench's worst data point at +9.4 MB/s encode; inline writers close that to 16.5 MB/s (+75%). 2sn +contributes most of the +1-3% decode lift on Person sizes that +exercise packed repeated fields (lucky_numbers has 5 packed int32s). +Person 100KB encode +11% is partially measurement noise (the 100KB +fixture has high variance run-to-run). + +**Notes / caveats:** + +- The dynamic `extensions_list` walk is preserved for forward + compatibility but gated so the static case pays a single integer + compare (`#_elist > N`), not the old per-extension function-pointer + dispatch. +- 2sn intentionally skips non-packed and string/bytes lists. Pre-sizing + those would require a tag-occurrence pre-scan; for Person's 26-emails + case the per-message scan cost likely exceeds the rehash savings. + Filed as future work in 2sn's body. +- Runtime mode (descriptor-driven dispatch via `pb.encode` / `pb.decode`) + is unchanged — qwt/2sn only touch full-mode codegen. Runtime numbers + in the bench are stable post-change. + +**Commit:** see the qwt+2sn commit immediately following this entry. + +--- + ## 2026-05-18 — u39: table.new(0, N) for result tables (REVERTED) **Task:** [tarantool-protobuf-u39] Decoder: emit `table.new(0, N)` for diff --git a/cmd/protoc-gen-tarantool/internal/gen/gen.go b/cmd/protoc-gen-tarantool/internal/gen/gen.go index 9055f2dda8841608cdaf8f1d92f2affbff442c24..777d62b29899b63b8225baafd1cd89f6a5959acf 100644 --- a/cmd/protoc-gen-tarantool/internal/gen/gen.go +++ b/cmd/protoc-gen-tarantool/internal/gen/gen.go @@ -107,10 +107,17 @@ // wrapper annotations a few lines down can reference these class names. emitEmmyTypesBlock(w, allEnums, allMsgs) // 4) Wrappers: _new / _encode / _decode. + // Build a cross-file map of extensions keyed by extendee FullName so + // the full-mode emitter can inline per-extension writers/readers (qwt). + // Both files in the current generation pass and previously-loaded + // imported files contribute; protogen surfaces every reachable + // Extension via plug.Files. + extsByExtendee := collectExtsByExtendee(plug) for _, m := range allMsgs { switch cfg.Mode { case ModeFull: - emitInlineMessage(w, file, m, imports, cfg.Prefix) + extsForMe := extsByExtendee[string(m.Desc.FullName())] + emitInlineMessage(w, file, m, imports, cfg.Prefix, extsForMe) default: emitMessageWrappers(w, file, m) } @@ -207,6 +214,12 @@ w.line("local string_byte = string.byte") w.line("local utf8_len = require('utf8').len") w.line("local band = bit.band") w.line("local rshift = bit.rshift") + // table.new(N, 0) presizes a list's array part to avoid the rehash + // cascade that fresh-`{}` tables pay as items are pushed. The + // decoder hot path uses it for packed repeated fields where the + // element count is recoverable from the LEN payload (2sn). LuaJIT + // 2.1 (Tarantool's bundled fork) ships `table.new`. + w.line("local table_new = require('table.new')") } // collectImports returns the deduplicated set of Lua require paths for all @@ -552,6 +565,46 @@ parts = append(parts, "options="+opts) } return "{" + strings.Join(parts, ", ") + "}" +} + +// collectExtsByExtendee walks every file the plugin knows about (input +// files plus dependencies) and groups extensions by extendee FullName. +// Used by the full-mode codegen to inline per-extension writers/readers +// in the generated _encode / _decode bodies — eliminates the +// pb.codec.encode_field / decode_extension dispatch for statically known +// extensions, while preserving the runtime registry for extensions +// registered after module load. Results are sorted by extension number +// so generated code stays deterministic. +func collectExtsByExtendee(plug *protogen.Plugin) map[string][]*protogen.Extension { + out := map[string][]*protogen.Extension{} + collect := func(exts []*protogen.Extension) { + for _, e := range exts { + if e.Extendee == nil { + continue + } + fn := string(e.Extendee.Desc.FullName()) + out[fn] = append(out[fn], e) + } + } + var walkMsgs func([]*protogen.Message) + walkMsgs = func(ms []*protogen.Message) { + for _, m := range ms { + collect(m.Extensions) + walkMsgs(m.Messages) + } + } + for _, f := range plug.Files { + collect(f.Extensions) + walkMsgs(f.Messages) + } + for k := range out { + list := out[k] + sort.Slice(list, func(i, j int) bool { + return list[i].Desc.Number() < list[j].Desc.Number() + }) + out[k] = list + } + return out } // emitExtensions registers each proto2 extension with the extendee's diff --git a/cmd/protoc-gen-tarantool/internal/gen/inline.go b/cmd/protoc-gen-tarantool/internal/gen/inline.go index 6420e7f2c86e2cecebeecd4ae6410f5296d8590f..2dbcd122c35af44ece258d7f49178ae1de5d2d46 100644 --- a/cmd/protoc-gen-tarantool/internal/gen/inline.go +++ b/cmd/protoc-gen-tarantool/internal/gen/inline.go @@ -86,7 +86,11 @@ // emitInlineMessage emits per-message _new / _encode / _decode functions with // no descriptor dispatch. Tag bytes are precomputed as Lua string literals; // each scalar field's encode/decode call resolves to one wire. call. -func emitInlineMessage(w *writer, file *protogen.File, m *protogen.Message, imports map[string]string, prefix string) { +// `exts` is the list of statically-known extensions targeting this message +// (collected via collectExtsByExtendee across all input files). They are +// inlined into the emitted encode/decode bodies so the hot path skips the +// pb.codec.encode_field / decode_extension dispatch. +func emitInlineMessage(w *writer, file *protogen.File, m *protogen.Message, imports map[string]string, prefix string, exts []*protogen.Extension) { name := luaTypeName(m.Desc.FullName(), file.Desc.Package()) full := emmyMessageFullName(m) selfPath := luaPackagePath(file.Desc, prefix) @@ -95,8 +99,8 @@ emitEmmyWrapperAnnotations(w, name, full, wrapperNew) w.line("function M.%s_new(t) return t or {} end", name) w.line("") - emitInlineEncode(w, name, m, file, selfPath, imports, prefix) - emitInlineDecode(w, name, m, file, selfPath, imports, prefix) + emitInlineEncode(w, name, m, file, selfPath, imports, prefix, exts) + emitInlineDecode(w, name, m, file, selfPath, imports, prefix, exts) emitEmmyWrapperAnnotations(w, name, full, wrapperDecodeLazy) w.line("function M.%s_decode_lazy(b) return pb.decode_lazy(M.%s_descriptor, b) end", name, name) emitEmmyWrapperAnnotations(w, name, full, wrapperText) @@ -105,7 +109,7 @@ emitOptionalAccessors(w, name, m, full) w.line("") } -func emitInlineEncode(w *writer, name string, m *protogen.Message, file *protogen.File, selfPath string, imports map[string]string, prefix string) { +func emitInlineEncode(w *writer, name string, m *protogen.Message, file *protogen.File, selfPath string, imports map[string]string, prefix string, exts []*protogen.Extension) { emitEmmyWrapperAnnotations(w, name, emmyMessageFullName(m), wrapperEncode) emitLocalizedFunction(w, fmt.Sprintf("function M.%s_encode(t)", name), func() { // C-acceleration: when PB_ENABLE_C=1 was set at module load, dispatch @@ -139,31 +143,44 @@ 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") + // Proto2 extensions. Static extensions (those visible at codegen + // time) are inlined as dedicated writers — same hot-path quality + // as a regular field. The dynamic walk over extensions_list[N+1..] + // catches anything registered via pb.register_extension after + // module load; `#extensions_list > N` short-circuits when no + // runtime extension was added, which is the common case (every + // known caller defines extensions in the .proto, not at runtime). + // Skip entirely when no extension targets this message — most + // proto3 messages and proto2 messages without `extensions` ranges. + if len(exts) > 0 { + w.line(" local _exts = t._extensions") + w.line(" if _exts ~= nil then") + // Single re-used local for each extension's value, matching the + // pattern in emitInlineEncode for regular fields (`local v` at + // the top). + w.line(" local _ev") + for _, ext := range exts { + emitInlineEncodeExtension(w, ext, file, selfPath, imports, prefix) + } + w.line(" end") + w.line(" local _elist = M.%s_descriptor.extensions_list", name) + w.line(" if _elist ~= nil and #_elist > %d then", len(exts)) + w.line(" local _exts2 = t._extensions") + w.line(" if _exts2 ~= nil then") + w.line(" for _i = %d, #_elist do", len(exts)+1) + w.line(" local _ext = _elist[_i]") + w.line(" local _ev = _exts2[_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. + 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") @@ -446,7 +463,287 @@ } } } -func emitInlineDecode(w *writer, name string, m *protogen.Message, file *protogen.File, selfPath string, imports map[string]string, prefix string) { +// emitInlineEncodeExtension emits an inline writer for a single statically +// known proto2 extension targeting the current message. Lives inside the +// `if _exts ~= nil then` block of the encode body, so the access pattern +// is `_exts[]` rather than `t.`. Extensions are always +// presence-tracked (never proto3 implicit zero), never required, never in +// oneofs, never maps — the dispatch is correspondingly simpler than +// emitInlineEncodeField. +func emitInlineEncodeExtension(w *writer, ext *protogen.Extension, file *protogen.File, selfPath string, imports map[string]string, prefix string) { + id := int32(ext.Desc.Number()) + full := string(ext.Desc.FullName()) + tag := tagBytesLit(id, wireTypeForField(ext)) + + w.line(" -- extension %d: %s", id, full) + w.line(" _ev = _exts[%q]", full) + if ext.Desc.IsList() { + emitInlineEncodeExtensionRepeated(w, ext, tag, full, file, selfPath, imports, prefix) + return + } + switch { + case ext.Message != nil: + ref := typeRef(file, ext.Message.Desc, selfPath, imports, "_encode", prefix) + if ext.Desc.Kind() == protoreflect.GroupKind { + endTag := tagBytesLit(id, 4 /* EGROUP */) + w.line(" if _ev ~= nil then") + w.line(" n = n + 1; out[n] = %s", tag) + w.line(" n = n + 1; out[n] = %s(_ev)", ref) + w.line(" n = n + 1; out[n] = %s", endTag) + w.line(" end") + } else { + w.line(" if _ev ~= nil then") + w.line(" local _b = %s(_ev)", ref) + w.line(" n = n + 1; out[n] = %s", tag) + emitInlineLenPrefix(w, " ", "_b") + w.line(" n = n + 1; out[n] = _b") + w.line(" end") + } + case ext.Enum != nil: + enumLocal := typeRef(file, ext.Enum.Desc, selfPath, imports, "", prefix) + enumFull := string(ext.Enum.Desc.FullName()) + w.line(" if _ev ~= nil then") + w.line(" local _nv = _ev") + w.line(" if type(_ev) == 'string' then") + w.line(" _nv = %s[_ev]", enumLocal) + w.line(" if _nv == nil then error(\"unknown enum value '\" .. _ev .. \"' for %s\", 0) end", enumFull) + w.line(" end") + w.line(" n = n + 1; out[n] = %s", tag) + w.line(" n = n + 1; out[n] = wire.encode_int32(_nv)") + w.line(" end") + default: + st := scalarName(ext.Desc.Kind()) + if st == "" { + panic("unhandled extension scalar kind: " + ext.Desc.Kind().String()) + } + w.line(" if _ev ~= nil then") + if st == "string" || st == "bytes" { + w.line(" n = n + 1; out[n] = %s", tag) + emitInlineLenPrefix(w, " ", "_ev") + w.line(" n = n + 1; out[n] = _ev") + } else { + w.line(" n = n + 1; out[n] = %s", tag) + w.line(" n = n + 1; out[n] = wire.encode_%s(_ev)", st) + } + w.line(" end") + } +} + +// emitInlineEncodeExtensionRepeated mirrors emitInlineEncodeRepeated but +// uses `_ev` (the extension value table read from `_exts[full_name]`) as +// the source instead of a field access on `t`. Same packing rules: +// packable scalars under [packed=true] pack into a single LEN payload, +// string/bytes and messages emit one wire entry per element, groups use +// SGROUP/EGROUP framing. +func emitInlineEncodeExtensionRepeated(w *writer, ext *protogen.Extension, tag, full string, file *protogen.File, selfPath string, imports map[string]string, prefix string) { + switch { + case ext.Message != nil: + ref := typeRef(file, ext.Message.Desc, selfPath, imports, "_encode", prefix) + if ext.Desc.Kind() == protoreflect.GroupKind { + endTag := tagBytesLit(int32(ext.Desc.Number()), 4 /* EGROUP */) + w.line(" if _ev ~= nil and #_ev > 0 then") + w.line(" local _stag, _etag = %s, %s", tag, endTag) + w.line(" for _i = 1, #_ev do") + w.line(" n = n + 1; out[n] = _stag") + w.line(" n = n + 1; out[n] = %s(_ev[_i])", ref) + w.line(" n = n + 1; out[n] = _etag") + w.line(" end") + w.line(" end") + } else { + w.line(" if _ev ~= nil and #_ev > 0 then") + w.line(" local _tag = %s", tag) + w.line(" for _i = 1, #_ev do") + w.line(" local _b = %s(_ev[_i])", ref) + w.line(" n = n + 1; out[n] = _tag") + emitInlineLenPrefix(w, " ", "_b") + w.line(" n = n + 1; out[n] = _b") + w.line(" end") + w.line(" end") + } + case ext.Enum != nil: + enumLocal := typeRef(file, ext.Enum.Desc, selfPath, imports, "", prefix) + enumFull := string(ext.Enum.Desc.FullName()) + w.line(" if _ev ~= nil and #_ev > 0 then") + if ext.Desc.IsPacked() { + w.line(" local parts, m = {}, 0") + w.line(" for _i = 1, #_ev do") + w.line(" local elem = _ev[_i]") + w.line(" local nv = elem") + w.line(" if type(elem) == 'string' then") + w.line(" nv = %s[elem]", enumLocal) + w.line(" if nv == nil then error(\"unknown enum value '\" .. elem .. \"' for %s\", 0) end", enumFull) + w.line(" end") + w.line(" m = m + 1; parts[m] = wire.encode_int32(nv)") + w.line(" end") + w.line(" local _b = table.concat(parts)") + w.line(" n = n + 1; out[n] = %s", tag) + emitInlineLenPrefix(w, " ", "_b") + w.line(" n = n + 1; out[n] = _b") + } else { + w.line(" local _tag = %s", tag) + w.line(" for _i = 1, #_ev do") + w.line(" local elem = _ev[_i]") + w.line(" local nv = elem") + w.line(" if type(elem) == 'string' then") + w.line(" nv = %s[elem]", enumLocal) + w.line(" if nv == nil then error(\"unknown enum value '\" .. elem .. \"' for %s\", 0) end", enumFull) + w.line(" end") + w.line(" n = n + 1; out[n] = _tag") + w.line(" n = n + 1; out[n] = wire.encode_int32(nv)") + w.line(" end") + } + w.line(" end") + default: + st := scalarName(ext.Desc.Kind()) + packable := st != "string" && st != "bytes" + if packable && ext.Desc.IsPacked() { + w.line(" if _ev ~= nil and #_ev > 0 then") + w.line(" local parts, m = {}, 0") + w.line(" for _i = 1, #_ev do") + w.line(" m = m + 1; parts[m] = wire.encode_%s(_ev[_i])", st) + w.line(" end") + w.line(" local _b = table.concat(parts)") + w.line(" n = n + 1; out[n] = %s", tag) + emitInlineLenPrefix(w, " ", "_b") + w.line(" n = n + 1; out[n] = _b") + w.line(" end") + } else if st == "string" || st == "bytes" { + w.line(" if _ev ~= nil and #_ev > 0 then") + w.line(" local _tag = %s", tag) + w.line(" for _i = 1, #_ev do") + w.line(" local _b = _ev[_i]") + w.line(" n = n + 1; out[n] = _tag") + emitInlineLenPrefix(w, " ", "_b") + w.line(" n = n + 1; out[n] = _b") + w.line(" end") + w.line(" end") + } else { + w.line(" if _ev ~= nil and #_ev > 0 then") + w.line(" local _tag = %s", tag) + w.line(" for _i = 1, #_ev do") + w.line(" n = n + 1; out[n] = _tag") + w.line(" n = n + 1; out[n] = wire.encode_%s(_ev[_i])", st) + w.line(" end") + w.line(" end") + } + } +} + +// emitInlineDecodeExtension emits an elseif-body that decodes one wire +// entry for a statically known extension and stores it under +// result._extensions[full_name]. For repeated extensions, appends to the +// existing list (creating it on first encounter). Mirrors +// pb.codec.decode_extension but inlines the dispatch and skips the +// per-call function frame. +func emitInlineDecodeExtension(w *writer, ext *protogen.Extension, file *protogen.File, selfPath string, imports map[string]string, prefix string) { + full := string(ext.Desc.FullName()) + // Common preamble: ensure result._extensions exists. + if ext.Desc.IsList() { + emitInlineDecodeExtensionRepeated(w, ext, full, file, selfPath, imports, prefix) + return + } + switch { + case ext.Message != nil: + ref := typeRef(file, ext.Message.Desc, selfPath, imports, "_decode", prefix) + if ext.Desc.Kind() == protoreflect.GroupKind { + descRef := typeRef(file, ext.Message.Desc, selfPath, imports, "_descriptor", prefix) + w.line(" local _payload") + w.line(" _payload, pos = pb.codec.decode_group(%s, buf, pos, %d)", + descRef, ext.Desc.Number()) + w.line(" local _e = result._extensions") + w.line(" if _e == nil then _e = {}; result._extensions = _e end") + w.line(" _e[%q] = _payload", full) + } else { + w.line(" local _payload") + w.line(" _payload, pos = wire.decode_len(buf, pos)") + w.line(" local _e = result._extensions") + w.line(" if _e == nil then _e = {}; result._extensions = _e end") + w.line(" _e[%q] = %s(_payload)", full, ref) + } + case ext.Enum != nil: + w.line(" local _u") + w.line(" _u, pos = wire.decode_varint(buf, pos)") + w.line(" local _e = result._extensions") + w.line(" if _e == nil then _e = {}; result._extensions = _e end") + w.line(" _e[%q] = wire.varint_to_int32(_u)", full) + default: + st := scalarName(ext.Desc.Kind()) + if st == "" { + panic("unhandled extension scalar kind: " + ext.Desc.Kind().String()) + } + w.line(" local _val") + w.line(" _val, pos = wire.decode_%s(buf, pos)", st) + w.line(" local _e = result._extensions") + w.line(" if _e == nil then _e = {}; result._extensions = _e end") + w.line(" _e[%q] = _val", full) + } +} + +// emitInlineDecodeExtensionRepeated handles the repeated branch. Uses +// `#list + 1` rather than a hoisted counter — repeated extensions are +// uncommon enough that adding per-extension counters at function scope +// isn't worth the prelude noise. +func emitInlineDecodeExtensionRepeated(w *writer, ext *protogen.Extension, full string, file *protogen.File, selfPath string, imports map[string]string, prefix string) { + w.line(" local _e = result._extensions") + w.line(" if _e == nil then _e = {}; result._extensions = _e end") + w.line(" local _list = _e[%q]", full) + w.line(" if _list == nil then _list = {}; _e[%q] = _list end", full) + switch { + case ext.Message != nil: + ref := typeRef(file, ext.Message.Desc, selfPath, imports, "_decode", prefix) + if ext.Desc.Kind() == protoreflect.GroupKind { + descRef := typeRef(file, ext.Message.Desc, selfPath, imports, "_descriptor", prefix) + w.line(" local _payload") + w.line(" _payload, pos = pb.codec.decode_group(%s, buf, pos, %d)", + descRef, ext.Desc.Number()) + w.line(" _list[#_list + 1] = _payload") + } else { + w.line(" local _payload") + w.line(" _payload, pos = wire.decode_len(buf, pos)") + w.line(" _list[#_list + 1] = %s(_payload)", ref) + } + case ext.Enum != nil: + w.line(" if wt == 2 then") + w.line(" local _payload") + w.line(" _payload, pos = wire.decode_len(buf, pos)") + w.line(" local p2, lim = 1, #_payload") + w.line(" while p2 <= lim do") + w.line(" local _u") + w.line(" _u, p2 = wire.decode_varint(_payload, p2)") + w.line(" _list[#_list + 1] = wire.varint_to_int32(_u)") + w.line(" end") + w.line(" else") + w.line(" local _u") + w.line(" _u, pos = wire.decode_varint(buf, pos)") + w.line(" _list[#_list + 1] = wire.varint_to_int32(_u)") + w.line(" end") + default: + st := scalarName(ext.Desc.Kind()) + packable := st != "string" && st != "bytes" + if packable { + w.line(" if wt == 2 then") + w.line(" local _payload") + w.line(" _payload, pos = wire.decode_len(buf, pos)") + w.line(" local p2, lim = 1, #_payload") + w.line(" while p2 <= lim do") + w.line(" local _val") + w.line(" _val, p2 = wire.decode_%s(_payload, p2)", st) + w.line(" _list[#_list + 1] = _val") + w.line(" end") + w.line(" else") + w.line(" local _val") + w.line(" _val, pos = wire.decode_%s(buf, pos)", st) + w.line(" _list[#_list + 1] = _val") + w.line(" end") + } else { + w.line(" local _val") + w.line(" _val, pos = wire.decode_%s(buf, pos)", st) + w.line(" _list[#_list + 1] = _val") + } + } +} + +func emitInlineDecode(w *writer, name string, m *protogen.Message, file *protogen.File, selfPath string, imports map[string]string, prefix string, exts []*protogen.Extension) { emitEmmyWrapperAnnotations(w, name, emmyMessageFullName(m), wrapperDecode) emitLocalizedFunction(w, fmt.Sprintf("function M.%s_decode(buf)", name), func() { // C-acceleration: see emitInlineEncode for rationale and lazy-compile. @@ -502,16 +799,27 @@ } w.line(" %s id == %d then", op, f.Desc.Number()) emitInlineDecodeFieldBody(w, f, file, selfPath, imports, prefix) } + // Static extension dispatch arms: route known extension ids + // straight into inline decoders that store into + // result._extensions[full_name]. Skips the + // pb.codec.decode_extension dispatch for the common case. + for _, ext := range exts { + op := "elseif" + if first { + op = "if" + first = false + } + w.line(" %s id == %d then", op, ext.Desc.Number()) + emitInlineDecodeExtension(w, ext, file, selfPath, imports, prefix) + } if first { // No fields — every wire byte is unknown. w.line(" if true then") } w.line(" else") - // 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]. + // Proto2 extensions registered at runtime (past the static set): + // fall back to pb.codec.decode_extension. Unknown ids land in + // the unknown-fields buffer. 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") @@ -608,8 +916,38 @@ func emitInlineDecodeRepeated(w *writer, f *protogen.Field, fname string, file *protogen.File, selfPath string, imports map[string]string, prefix string) { dst := luaFieldAccess("result", fname) cnt := "_n_" + string(f.Desc.Name()) - w.line(" local list = %s", dst) - w.line(" if list == nil then list = {}; %s = list end", dst) + + // For packable scalar/enum fields, defer the list allocation into the + // wt==2 branch so the element count estimate (derived from the packed + // payload length) can drive table.new(N, 0) and avoid the rehash + // cascade. For non-packable types (message/string/bytes) and for the + // per-element wt!=2 fallback, fall back to a bare `{}` — the size + // hint would require a per-tag scan that costs more than it saves. (2sn) + packable := false + estExpr := "" + switch { + case f.Message != nil: + // fallthrough to default alloc + standard emit + case f.Enum != nil: + packable = true + estExpr = "lim" // upper-bound (each varint ≥ 1 byte) + default: + st := scalarName(f.Desc.Kind()) + if st != "string" && st != "bytes" { + packable = true + if sz := fixedScalarBytes(f.Desc.Kind()); sz > 0 { + estExpr = fmt.Sprintf("rshift(lim, %d)", sz) // /4 or /8 via bit shift + } else { + estExpr = "lim" + } + } + } + + if !packable { + // Default-allocation prelude for non-packable fields. + w.line(" local list = %s", dst) + w.line(" if list == nil then list = {}; %s = list end", dst) + } switch { case f.Message != nil: @@ -631,30 +969,37 @@ w.line(" if wt == 2 then") w.line(" local payload") w.line(" payload, pos = wire.decode_len(buf, pos)") w.line(" local p2, lim = 1, #payload") + w.line(" local list = %s", dst) + w.line(" if list == nil then list = table_new(%s, 0); %s = list end", estExpr, dst) w.line(" while p2 <= lim do") w.line(" local u") w.line(" u, p2 = wire.decode_varint(payload, p2)") w.line(" %s = %s + 1; list[%s] = wire.varint_to_int32(u)", cnt, cnt, cnt) w.line(" end") w.line(" else") + w.line(" local list = %s", dst) + w.line(" if list == nil then list = {}; %s = list end", dst) w.line(" local u") w.line(" u, pos = wire.decode_varint(buf, pos)") w.line(" %s = %s + 1; list[%s] = wire.varint_to_int32(u)", cnt, cnt, cnt) w.line(" end") default: st := scalarName(f.Desc.Kind()) - packable := st != "string" && st != "bytes" if packable { w.line(" if wt == 2 then") w.line(" local payload") w.line(" payload, pos = wire.decode_len(buf, pos)") w.line(" local p2, lim = 1, #payload") + w.line(" local list = %s", dst) + w.line(" if list == nil then list = table_new(%s, 0); %s = list end", estExpr, dst) w.line(" while p2 <= lim do") w.line(" local val") w.line(" val, p2 = wire.decode_%s(payload, p2)", st) w.line(" %s = %s + 1; list[%s] = val", cnt, cnt, cnt) w.line(" end") w.line(" else") + w.line(" local list = %s", dst) + w.line(" if list == nil then list = {}; %s = list end", dst) w.line(" local val") w.line(" val, pos = wire.decode_%s(buf, pos)", st) w.line(" %s = %s + 1; list[%s] = val", cnt, cnt, cnt) @@ -664,6 +1009,20 @@ // Repeated string/bytes — inline 1-byte LEN fast path. (a6n) emitInlineStringBytesRepeated(w, st, cnt) } } +} + +// fixedScalarBytes returns the log2 of element size in bytes for +// fixed-width scalar kinds, or 0 for varint-based kinds. Used by 2sn +// to derive an exact count from the packed payload length via bit +// shift (count = lim >> log2_sz). +func fixedScalarBytes(k protoreflect.Kind) int { + switch k { + case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind, protoreflect.FloatKind: + return 2 // 4 bytes -> shift right by 2 + case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind, protoreflect.DoubleKind: + return 3 // 8 bytes -> shift right by 3 + } + return 0 } // emitInlineStringBytesScalar emits the singular string/bytes decode with the diff --git a/examples/expected/full/c_int64/c_int64_pb.lua b/examples/expected/full/c_int64/c_int64_pb.lua index 07526794fd6a8a744369ced61636464d733e83d8..301d0f3d0e72edfcc33e101a1027c6025d7533fd 100644 --- a/examples/expected/full/c_int64/c_int64_pb.lua +++ b/examples/expected/full/c_int64/c_int64_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -90,20 +91,6 @@ v = t.a_sfixed64 if v ~= nil and v ~= 0 then n = n + 1; out[n] = "\x29" n = n + 1; out[n] = wire.encode_sfixed64(v) - end - local _exts = t._extensions - if _exts ~= nil then - local _elist = M.Wide_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 diff --git a/examples/expected/full/c_nested/c_nested_pb.lua b/examples/expected/full/c_nested/c_nested_pb.lua index d3a43772e1cb868856d1b2507cb7c421a47d2400..b16f4b1c634e529df25c055988fc014a0c73f56d 100644 --- a/examples/expected/full/c_nested/c_nested_pb.lua +++ b/examples/expected/full/c_nested/c_nested_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -136,20 +137,6 @@ if v ~= nil and v ~= 0 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.L1_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) @@ -255,20 +242,6 @@ if v ~= nil and v ~= 0 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.L2_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) @@ -374,20 +347,6 @@ if v ~= nil and v ~= 0 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.L3_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) @@ -493,20 +452,6 @@ if v ~= nil and v ~= 0 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.L4_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) @@ -598,20 +543,6 @@ v = t.v if v ~= nil and v ~= 0 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.L5_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 diff --git a/examples/expected/full/c_repeated/c_repeated_pb.lua b/examples/expected/full/c_repeated/c_repeated_pb.lua index f713e954563561b52b7184f3268978cbaba8fdf7..26b0ee2423cc7961d01b886e8dfc7c6fd86dc49c 100644 --- a/examples/expected/full/c_repeated/c_repeated_pb.lua +++ b/examples/expected/full/c_repeated/c_repeated_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -124,20 +125,6 @@ else n = n + 1; out[n] = wire.encode_varint(_len) end n = n + 1; out[n] = v - end - local _exts = t._extensions - if _exts ~= nil then - local _elist = M.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 @@ -463,20 +450,6 @@ end n = n + 1; out[n] = _b end end - local _exts = t._extensions - if _exts ~= nil then - local _elist = M.Holder_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) @@ -535,205 +508,229 @@ else id, wt, pos = wire.decode_tag(buf, pos) end if id == 1 then - local list = result.packed_int32 - if list == nil then list = {}; result.packed_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_int32 + if list == nil then list = table_new(lim, 0); result.packed_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_packed_int32 = _n_packed_int32 + 1; list[_n_packed_int32] = val end else + local list = result.packed_int32 + if list == nil then list = {}; result.packed_int32 = list end local val val, pos = decode_int32(buf, pos) _n_packed_int32 = _n_packed_int32 + 1; list[_n_packed_int32] = val end elseif id == 2 then - local list = result.packed_int64 - if list == nil then list = {}; result.packed_int64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_int64 + if list == nil then list = table_new(lim, 0); result.packed_int64 = list end while p2 <= lim do local val val, p2 = decode_int64(payload, p2) _n_packed_int64 = _n_packed_int64 + 1; list[_n_packed_int64] = val end else + local list = result.packed_int64 + if list == nil then list = {}; result.packed_int64 = list end local val val, pos = decode_int64(buf, pos) _n_packed_int64 = _n_packed_int64 + 1; list[_n_packed_int64] = val end elseif id == 3 then - local list = result.packed_sint32 - if list == nil then list = {}; result.packed_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sint32 + if list == nil then list = table_new(lim, 0); result.packed_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_packed_sint32 = _n_packed_sint32 + 1; list[_n_packed_sint32] = val end else + local list = result.packed_sint32 + if list == nil then list = {}; result.packed_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_packed_sint32 = _n_packed_sint32 + 1; list[_n_packed_sint32] = val end elseif id == 4 then - local list = result.packed_uint32 - if list == nil then list = {}; result.packed_uint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_uint32 + if list == nil then list = table_new(lim, 0); result.packed_uint32 = list end while p2 <= lim do local val val, p2 = decode_uint32(payload, p2) _n_packed_uint32 = _n_packed_uint32 + 1; list[_n_packed_uint32] = val end else + local list = result.packed_uint32 + if list == nil then list = {}; result.packed_uint32 = list end local val val, pos = decode_uint32(buf, pos) _n_packed_uint32 = _n_packed_uint32 + 1; list[_n_packed_uint32] = val end elseif id == 5 then - local list = result.packed_fixed32 - if list == nil then list = {}; result.packed_fixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_fixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_fixed32 = list end while p2 <= lim do local val val, p2 = decode_fixed32(payload, p2) _n_packed_fixed32 = _n_packed_fixed32 + 1; list[_n_packed_fixed32] = val end else + local list = result.packed_fixed32 + if list == nil then list = {}; result.packed_fixed32 = list end local val val, pos = decode_fixed32(buf, pos) _n_packed_fixed32 = _n_packed_fixed32 + 1; list[_n_packed_fixed32] = val end elseif id == 6 then - local list = result.packed_fixed64 - if list == nil then list = {}; result.packed_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_packed_fixed64 = _n_packed_fixed64 + 1; list[_n_packed_fixed64] = val end else + local list = result.packed_fixed64 + if list == nil then list = {}; result.packed_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_packed_fixed64 = _n_packed_fixed64 + 1; list[_n_packed_fixed64] = val end elseif id == 7 then - local list = result.packed_double - if list == nil then list = {}; result.packed_double = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_double + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_double = list end while p2 <= lim do local val val, p2 = decode_double(payload, p2) _n_packed_double = _n_packed_double + 1; list[_n_packed_double] = val end else + local list = result.packed_double + if list == nil then list = {}; result.packed_double = list end local val val, pos = decode_double(buf, pos) _n_packed_double = _n_packed_double + 1; list[_n_packed_double] = val end elseif id == 8 then - local list = result.packed_float - if list == nil then list = {}; result.packed_float = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_float + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_float = list end while p2 <= lim do local val val, p2 = decode_float(payload, p2) _n_packed_float = _n_packed_float + 1; list[_n_packed_float] = val end else + local list = result.packed_float + if list == nil then list = {}; result.packed_float = list end local val val, pos = decode_float(buf, pos) _n_packed_float = _n_packed_float + 1; list[_n_packed_float] = val end elseif id == 9 then - local list = result.packed_bool - if list == nil then list = {}; result.packed_bool = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_bool + if list == nil then list = table_new(lim, 0); result.packed_bool = list end while p2 <= lim do local val val, p2 = decode_bool(payload, p2) _n_packed_bool = _n_packed_bool + 1; list[_n_packed_bool] = val end else + local list = result.packed_bool + if list == nil then list = {}; result.packed_bool = list end local val val, pos = decode_bool(buf, pos) _n_packed_bool = _n_packed_bool + 1; list[_n_packed_bool] = val end elseif id == 20 then - local list = result.unpacked_int32 - if list == nil then list = {}; result.unpacked_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_int32 + if list == nil then list = table_new(lim, 0); result.unpacked_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_unpacked_int32 = _n_unpacked_int32 + 1; list[_n_unpacked_int32] = val end else + local list = result.unpacked_int32 + if list == nil then list = {}; result.unpacked_int32 = list end local val val, pos = decode_int32(buf, pos) _n_unpacked_int32 = _n_unpacked_int32 + 1; list[_n_unpacked_int32] = val end elseif id == 21 then - local list = result.unpacked_fixed64 - if list == nil then list = {}; result.unpacked_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.unpacked_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_unpacked_fixed64 = _n_unpacked_fixed64 + 1; list[_n_unpacked_fixed64] = val end else + local list = result.unpacked_fixed64 + if list == nil then list = {}; result.unpacked_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_unpacked_fixed64 = _n_unpacked_fixed64 + 1; list[_n_unpacked_fixed64] = val end elseif id == 22 then - local list = result.unpacked_sint32 - if list == nil then list = {}; result.unpacked_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sint32 + if list == nil then list = table_new(lim, 0); result.unpacked_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_unpacked_sint32 = _n_unpacked_sint32 + 1; list[_n_unpacked_sint32] = val end else + local list = result.unpacked_sint32 + if list == nil then list = {}; result.unpacked_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_unpacked_sint32 = _n_unpacked_sint32 + 1; list[_n_unpacked_sint32] = val diff --git a/examples/expected/full/conformance/conformance_pb.lua b/examples/expected/full/conformance/conformance_pb.lua index 6c27c526b5578410a453dad35a733a35a6f653ce..76f9c6e7c075678473d1fcca0812c5ec898d3d56 100644 --- a/examples/expected/full/conformance/conformance_pb.lua +++ b/examples/expected/full/conformance/conformance_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -250,20 +251,6 @@ n = n + 1; out[n] = encode_varint(_len) end 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) @@ -399,20 +386,6 @@ end 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) @@ -605,20 +578,6 @@ if v ~= nil and v ~= false then 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) @@ -921,20 +880,6 @@ n = n + 1; out[n] = encode_varint(_len) end 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) @@ -1220,20 +1165,6 @@ v = t.use_jspb_array_any_format if v ~= nil and v ~= false then 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 diff --git a/examples/expected/full/hello/hello_pb.lua b/examples/expected/full/hello/hello_pb.lua index a0f65fad79f5417be5ad86eb7592c36f604481d3..89612cb4c4f93255665ed16ced2854b56e120a6b 100644 --- a/examples/expected/full/hello/hello_pb.lua +++ b/examples/expected/full/hello/hello_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -267,20 +268,6 @@ n = n + 1; out[n] = encode_varint(_len) end 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) @@ -405,20 +392,6 @@ n = n + 1; out[n] = wire.encode_varint(_len) end 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) @@ -518,20 +491,6 @@ else n = n + 1; out[n] = wire.encode_varint(_len) end 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 @@ -777,20 +736,6 @@ n = n + 1; out[n] = encode_varint(_len) end 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) @@ -966,20 +911,6 @@ else n = n + 1; out[n] = encode_varint(_len) end 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 @@ -1310,20 +1241,6 @@ end n = n + 1; out[n] = _b 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) @@ -1420,18 +1337,20 @@ local payload payload, pos = decode_len(buf, pos) _n_friends = _n_friends + 1; list[_n_friends] = M.Person_decode(payload) elseif id == 7 then - local list = result.lucky_numbers - if list == nil then list = {}; result.lucky_numbers = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.lucky_numbers + if list == nil then list = table_new(lim, 0); result.lucky_numbers = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_lucky_numbers = _n_lucky_numbers + 1; list[_n_lucky_numbers] = val end else + local list = result.lucky_numbers + if list == nil then list = {}; result.lucky_numbers = list end local val val, pos = decode_int32(buf, pos) _n_lucky_numbers = _n_lucky_numbers + 1; list[_n_lucky_numbers] = val diff --git a/examples/expected/full/proto2_basic/proto2_basic_pb.lua b/examples/expected/full/proto2_basic/proto2_basic_pb.lua index 3514f648a9059dbb19a3bff6b69511fc8cf8a918..dce934cc2d5f6cc4ee5ec9575868ecfb9193096d 100644 --- a/examples/expected/full/proto2_basic/proto2_basic_pb.lua +++ b/examples/expected/full/proto2_basic/proto2_basic_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -324,20 +325,6 @@ end n = n + 1; out[n] = "\x48" n = n + 1; out[n] = 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) @@ -562,20 +549,6 @@ n = n + 1; out[n] = _tag n = n + 1; out[n] = 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) @@ -622,52 +595,58 @@ local val val, pos = decode_int32(buf, pos) result.o = val elseif id == 3 then - local list = result.packed_default - if list == nil then list = {}; result.packed_default = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_default + if list == nil then list = table_new(lim, 0); result.packed_default = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_packed_default = _n_packed_default + 1; list[_n_packed_default] = val end else + local list = result.packed_default + if list == nil then list = {}; result.packed_default = list end local val val, pos = decode_int32(buf, pos) _n_packed_default = _n_packed_default + 1; list[_n_packed_default] = val end elseif id == 4 then - local list = result.explicitly_packed - if list == nil then list = {}; result.explicitly_packed = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.explicitly_packed + if list == nil then list = table_new(lim, 0); result.explicitly_packed = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_explicitly_packed = _n_explicitly_packed + 1; list[_n_explicitly_packed] = val end else + local list = result.explicitly_packed + if list == nil then list = {}; result.explicitly_packed = list end local val val, pos = decode_int32(buf, pos) _n_explicitly_packed = _n_explicitly_packed + 1; list[_n_explicitly_packed] = val end elseif id == 5 then - local list = result.explicitly_unpacked - if list == nil then list = {}; result.explicitly_unpacked = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.explicitly_unpacked + if list == nil then list = table_new(lim, 0); result.explicitly_unpacked = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_explicitly_unpacked = _n_explicitly_unpacked + 1; list[_n_explicitly_unpacked] = val end else + local list = result.explicitly_unpacked + if list == nil then list = {}; result.explicitly_unpacked = list end local val val, pos = decode_int32(buf, pos) _n_explicitly_unpacked = _n_explicitly_unpacked + 1; list[_n_explicitly_unpacked] = val @@ -746,20 +725,6 @@ n = n + 1; out[n] = encode_varint(_len) end 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) @@ -864,20 +829,6 @@ error("required field missing on encode: proto2_basic.Nested.Inner.x", 0) 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) @@ -973,20 +924,6 @@ n = n + 1; out[n] = M.WithGroup_RepGroup_encode(v[_i]) 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) @@ -1099,20 +1036,6 @@ n = n + 1; out[n] = wire.encode_varint(_len) end 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) @@ -1220,20 +1143,6 @@ v = t.n if v ~= nil then 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 @@ -1399,11 +1308,33 @@ 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 _ev + -- extension 100: proto2_basic.ext_count + _ev = _exts["proto2_basic.ext_count"] + if _ev ~= nil then + n = n + 1; out[n] = "\xa0\x06" + n = n + 1; out[n] = encode_int32(_ev) + end + -- extension 101: proto2_basic.ext_label + _ev = _exts["proto2_basic.ext_label"] + if _ev ~= nil then + n = n + 1; out[n] = "\xaa\x06" + local _len = #_ev + if _len < 128 then + n = n + 1; out[n] = string.char(_len) + else + n = n + 1; out[n] = encode_varint(_len) + end + n = n + 1; out[n] = _ev + end + end + local _elist = M.BenchPayload_descriptor.extensions_list + if _elist ~= nil and #_elist > 2 then + local _exts2 = t._extensions + if _exts2 ~= nil then + for _i = 3, #_elist do local _ext = _elist[_i] - local _ev = _exts[_ext.full_name] + local _ev = _exts2[_ext.full_name] if _ev ~= nil then pb.codec.encode_field(_ext, _ev, out, true) end @@ -1472,18 +1403,20 @@ local val val, pos = 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 = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.lucky_numbers + if list == nil then list = table_new(lim, 0); result.lucky_numbers = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_lucky_numbers = _n_lucky_numbers + 1; list[_n_lucky_numbers] = val end else + local list = result.lucky_numbers + if list == nil then list = {}; result.lucky_numbers = list end local val val, pos = decode_int32(buf, pos) _n_lucky_numbers = _n_lucky_numbers + 1; list[_n_lucky_numbers] = val @@ -1523,6 +1456,18 @@ result.stats = payload else pb.codec.merge_message(M.BenchPayload_Stats_descriptor, prev, payload) end + elseif id == 100 then + local _val + _val, pos = decode_int32(buf, pos) + local _e = result._extensions + if _e == nil then _e = {}; result._extensions = _e end + _e["proto2_basic.ext_count"] = _val + elseif id == 101 then + local _val + _val, pos = decode_string(buf, pos) + local _e = result._extensions + if _e == nil then _e = {}; result._extensions = _e end + _e["proto2_basic.ext_label"] = _val else local _ebid = M.BenchPayload_descriptor.extensions_by_id local _ext = _ebid and _ebid[id] or nil @@ -1597,20 +1542,6 @@ if v ~= nil then n = n + 1; out[n] = "\x48" n = n + 1; out[n] = 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) @@ -1721,20 +1652,6 @@ 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 diff --git a/examples/expected/full/protobuf_test_messages/proto2/test_messages_proto2_pb.lua b/examples/expected/full/protobuf_test_messages/proto2/test_messages_proto2_pb.lua index 3fa1cec88fe98b4f77241df9a0570a14b57682a3..a6dbba8fe1daf530f3c67ed4e148f7b9424c073d 100644 --- a/examples/expected/full/protobuf_test_messages/proto2/test_messages_proto2_pb.lua +++ b/examples/expected/full/protobuf_test_messages/proto2/test_messages_proto2_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -2608,11 +2609,52 @@ n = n + 1; out[n] = 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 _ev + -- extension 120: protobuf_test_messages.proto2.extension_int32 + _ev = _exts["protobuf_test_messages.proto2.extension_int32"] + if _ev ~= nil then + n = n + 1; out[n] = "\xc0\x07" + n = n + 1; out[n] = encode_int32(_ev) + end + -- extension 121: protobuf_test_messages.proto2.groupfield + _ev = _exts["protobuf_test_messages.proto2.groupfield"] + if _ev ~= nil then + n = n + 1; out[n] = "\xcb\x07" + n = n + 1; out[n] = M.GroupField_encode(_ev) + n = n + 1; out[n] = "\xcc\x07" + end + -- extension 133: protobuf_test_messages.proto2.extension_string + _ev = _exts["protobuf_test_messages.proto2.extension_string"] + if _ev ~= nil then + n = n + 1; out[n] = "\xaa\x08" + local _len = #_ev + if _len < 128 then + n = n + 1; out[n] = string.char(_len) + else + n = n + 1; out[n] = encode_varint(_len) + end + n = n + 1; out[n] = _ev + end + -- extension 134: protobuf_test_messages.proto2.extension_bytes + _ev = _exts["protobuf_test_messages.proto2.extension_bytes"] + if _ev ~= nil then + n = n + 1; out[n] = "\xb2\x08" + local _len = #_ev + if _len < 128 then + n = n + 1; out[n] = string.char(_len) + else + n = n + 1; out[n] = encode_varint(_len) + end + n = n + 1; out[n] = _ev + end + end + local _elist = M.TestAllTypesProto2_descriptor.extensions_list + if _elist ~= nil and #_elist > 4 then + local _exts2 = t._extensions + if _exts2 ~= nil then + for _i = 5, #_elist do local _ext = _elist[_i] - local _ev = _exts[_ext.full_name] + local _ev = _exts2[_ext.full_name] if _ev ~= nil then pb.codec.encode_field(_ext, _ev, out, true) end @@ -2868,222 +2910,248 @@ else pb.codec.merge_message(M.TestAllTypesProto2_descriptor, prev, M.TestAllTypesProto2_decode(payload)) end elseif id == 31 then - local list = result.repeated_int32 - if list == nil then list = {}; result.repeated_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_int32 + if list == nil then list = table_new(lim, 0); result.repeated_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_repeated_int32 = _n_repeated_int32 + 1; list[_n_repeated_int32] = val end else + local list = result.repeated_int32 + if list == nil then list = {}; result.repeated_int32 = list end local val val, pos = decode_int32(buf, pos) _n_repeated_int32 = _n_repeated_int32 + 1; list[_n_repeated_int32] = val end elseif id == 32 then - local list = result.repeated_int64 - if list == nil then list = {}; result.repeated_int64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_int64 + if list == nil then list = table_new(lim, 0); result.repeated_int64 = list end while p2 <= lim do local val val, p2 = decode_int64(payload, p2) _n_repeated_int64 = _n_repeated_int64 + 1; list[_n_repeated_int64] = val end else + local list = result.repeated_int64 + if list == nil then list = {}; result.repeated_int64 = list end local val val, pos = decode_int64(buf, pos) _n_repeated_int64 = _n_repeated_int64 + 1; list[_n_repeated_int64] = val end elseif id == 33 then - local list = result.repeated_uint32 - if list == nil then list = {}; result.repeated_uint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_uint32 + if list == nil then list = table_new(lim, 0); result.repeated_uint32 = list end while p2 <= lim do local val val, p2 = decode_uint32(payload, p2) _n_repeated_uint32 = _n_repeated_uint32 + 1; list[_n_repeated_uint32] = val end else + local list = result.repeated_uint32 + if list == nil then list = {}; result.repeated_uint32 = list end local val val, pos = decode_uint32(buf, pos) _n_repeated_uint32 = _n_repeated_uint32 + 1; list[_n_repeated_uint32] = val end elseif id == 34 then - local list = result.repeated_uint64 - if list == nil then list = {}; result.repeated_uint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_uint64 + if list == nil then list = table_new(lim, 0); result.repeated_uint64 = list end while p2 <= lim do local val val, p2 = decode_uint64(payload, p2) _n_repeated_uint64 = _n_repeated_uint64 + 1; list[_n_repeated_uint64] = val end else + local list = result.repeated_uint64 + if list == nil then list = {}; result.repeated_uint64 = list end local val val, pos = decode_uint64(buf, pos) _n_repeated_uint64 = _n_repeated_uint64 + 1; list[_n_repeated_uint64] = val end elseif id == 35 then - local list = result.repeated_sint32 - if list == nil then list = {}; result.repeated_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sint32 + if list == nil then list = table_new(lim, 0); result.repeated_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_repeated_sint32 = _n_repeated_sint32 + 1; list[_n_repeated_sint32] = val end else + local list = result.repeated_sint32 + if list == nil then list = {}; result.repeated_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_repeated_sint32 = _n_repeated_sint32 + 1; list[_n_repeated_sint32] = val end elseif id == 36 then - local list = result.repeated_sint64 - if list == nil then list = {}; result.repeated_sint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sint64 + if list == nil then list = table_new(lim, 0); result.repeated_sint64 = list end while p2 <= lim do local val val, p2 = decode_sint64(payload, p2) _n_repeated_sint64 = _n_repeated_sint64 + 1; list[_n_repeated_sint64] = val end else + local list = result.repeated_sint64 + if list == nil then list = {}; result.repeated_sint64 = list end local val val, pos = decode_sint64(buf, pos) _n_repeated_sint64 = _n_repeated_sint64 + 1; list[_n_repeated_sint64] = val end elseif id == 37 then - local list = result.repeated_fixed32 - if list == nil then list = {}; result.repeated_fixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_fixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.repeated_fixed32 = list end while p2 <= lim do local val val, p2 = decode_fixed32(payload, p2) _n_repeated_fixed32 = _n_repeated_fixed32 + 1; list[_n_repeated_fixed32] = val end else + local list = result.repeated_fixed32 + if list == nil then list = {}; result.repeated_fixed32 = list end local val val, pos = decode_fixed32(buf, pos) _n_repeated_fixed32 = _n_repeated_fixed32 + 1; list[_n_repeated_fixed32] = val end elseif id == 38 then - local list = result.repeated_fixed64 - if list == nil then list = {}; result.repeated_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.repeated_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_repeated_fixed64 = _n_repeated_fixed64 + 1; list[_n_repeated_fixed64] = val end else + local list = result.repeated_fixed64 + if list == nil then list = {}; result.repeated_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_repeated_fixed64 = _n_repeated_fixed64 + 1; list[_n_repeated_fixed64] = val end elseif id == 39 then - local list = result.repeated_sfixed32 - if list == nil then list = {}; result.repeated_sfixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sfixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.repeated_sfixed32 = list end while p2 <= lim do local val val, p2 = decode_sfixed32(payload, p2) _n_repeated_sfixed32 = _n_repeated_sfixed32 + 1; list[_n_repeated_sfixed32] = val end else + local list = result.repeated_sfixed32 + if list == nil then list = {}; result.repeated_sfixed32 = list end local val val, pos = decode_sfixed32(buf, pos) _n_repeated_sfixed32 = _n_repeated_sfixed32 + 1; list[_n_repeated_sfixed32] = val end elseif id == 40 then - local list = result.repeated_sfixed64 - if list == nil then list = {}; result.repeated_sfixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sfixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.repeated_sfixed64 = list end while p2 <= lim do local val val, p2 = decode_sfixed64(payload, p2) _n_repeated_sfixed64 = _n_repeated_sfixed64 + 1; list[_n_repeated_sfixed64] = val end else + local list = result.repeated_sfixed64 + if list == nil then list = {}; result.repeated_sfixed64 = list end local val val, pos = decode_sfixed64(buf, pos) _n_repeated_sfixed64 = _n_repeated_sfixed64 + 1; list[_n_repeated_sfixed64] = val end elseif id == 41 then - local list = result.repeated_float - if list == nil then list = {}; result.repeated_float = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_float + if list == nil then list = table_new(rshift(lim, 2), 0); result.repeated_float = list end while p2 <= lim do local val val, p2 = decode_float(payload, p2) _n_repeated_float = _n_repeated_float + 1; list[_n_repeated_float] = val end else + local list = result.repeated_float + if list == nil then list = {}; result.repeated_float = list end local val val, pos = decode_float(buf, pos) _n_repeated_float = _n_repeated_float + 1; list[_n_repeated_float] = val end elseif id == 42 then - local list = result.repeated_double - if list == nil then list = {}; result.repeated_double = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_double + if list == nil then list = table_new(rshift(lim, 3), 0); result.repeated_double = list end while p2 <= lim do local val val, p2 = decode_double(payload, p2) _n_repeated_double = _n_repeated_double + 1; list[_n_repeated_double] = val end else + local list = result.repeated_double + if list == nil then list = {}; result.repeated_double = list end local val val, pos = decode_double(buf, pos) _n_repeated_double = _n_repeated_double + 1; list[_n_repeated_double] = val end elseif id == 43 then - local list = result.repeated_bool - if list == nil then list = {}; result.repeated_bool = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_bool + if list == nil then list = table_new(lim, 0); result.repeated_bool = list end while p2 <= lim do local val val, p2 = decode_bool(payload, p2) _n_repeated_bool = _n_repeated_bool + 1; list[_n_repeated_bool] = val end else + local list = result.repeated_bool + if list == nil then list = {}; result.repeated_bool = list end local val val, pos = decode_bool(buf, pos) _n_repeated_bool = _n_repeated_bool + 1; list[_n_repeated_bool] = val @@ -3134,35 +3202,39 @@ local payload payload, pos = decode_len(buf, pos) _n_repeated_foreign_message = _n_repeated_foreign_message + 1; list[_n_repeated_foreign_message] = M.ForeignMessageProto2_decode(payload) elseif id == 51 then - local list = result.repeated_nested_enum - if list == nil then list = {}; result.repeated_nested_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_nested_enum + if list == nil then list = table_new(lim, 0); result.repeated_nested_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_repeated_nested_enum = _n_repeated_nested_enum + 1; list[_n_repeated_nested_enum] = varint_to_int32(u) end else + local list = result.repeated_nested_enum + if list == nil then list = {}; result.repeated_nested_enum = list end local u u, pos = decode_varint(buf, pos) _n_repeated_nested_enum = _n_repeated_nested_enum + 1; list[_n_repeated_nested_enum] = varint_to_int32(u) end elseif id == 52 then - local list = result.repeated_foreign_enum - if list == nil then list = {}; result.repeated_foreign_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_foreign_enum + if list == nil then list = table_new(lim, 0); result.repeated_foreign_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_repeated_foreign_enum = _n_repeated_foreign_enum + 1; list[_n_repeated_foreign_enum] = varint_to_int32(u) end else + local list = result.repeated_foreign_enum + if list == nil then list = {}; result.repeated_foreign_enum = list end local u u, pos = decode_varint(buf, pos) _n_repeated_foreign_enum = _n_repeated_foreign_enum + 1; list[_n_repeated_foreign_enum] = varint_to_int32(u) @@ -3202,477 +3274,533 @@ val, pos = decode_string(buf, pos) _n_repeated_cord = _n_repeated_cord + 1; list[_n_repeated_cord] = val end elseif id == 75 then - local list = result.packed_int32 - if list == nil then list = {}; result.packed_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_int32 + if list == nil then list = table_new(lim, 0); result.packed_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_packed_int32 = _n_packed_int32 + 1; list[_n_packed_int32] = val end else + local list = result.packed_int32 + if list == nil then list = {}; result.packed_int32 = list end local val val, pos = decode_int32(buf, pos) _n_packed_int32 = _n_packed_int32 + 1; list[_n_packed_int32] = val end elseif id == 76 then - local list = result.packed_int64 - if list == nil then list = {}; result.packed_int64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_int64 + if list == nil then list = table_new(lim, 0); result.packed_int64 = list end while p2 <= lim do local val val, p2 = decode_int64(payload, p2) _n_packed_int64 = _n_packed_int64 + 1; list[_n_packed_int64] = val end else + local list = result.packed_int64 + if list == nil then list = {}; result.packed_int64 = list end local val val, pos = decode_int64(buf, pos) _n_packed_int64 = _n_packed_int64 + 1; list[_n_packed_int64] = val end elseif id == 77 then - local list = result.packed_uint32 - if list == nil then list = {}; result.packed_uint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_uint32 + if list == nil then list = table_new(lim, 0); result.packed_uint32 = list end while p2 <= lim do local val val, p2 = decode_uint32(payload, p2) _n_packed_uint32 = _n_packed_uint32 + 1; list[_n_packed_uint32] = val end else + local list = result.packed_uint32 + if list == nil then list = {}; result.packed_uint32 = list end local val val, pos = decode_uint32(buf, pos) _n_packed_uint32 = _n_packed_uint32 + 1; list[_n_packed_uint32] = val end elseif id == 78 then - local list = result.packed_uint64 - if list == nil then list = {}; result.packed_uint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_uint64 + if list == nil then list = table_new(lim, 0); result.packed_uint64 = list end while p2 <= lim do local val val, p2 = decode_uint64(payload, p2) _n_packed_uint64 = _n_packed_uint64 + 1; list[_n_packed_uint64] = val end else + local list = result.packed_uint64 + if list == nil then list = {}; result.packed_uint64 = list end local val val, pos = decode_uint64(buf, pos) _n_packed_uint64 = _n_packed_uint64 + 1; list[_n_packed_uint64] = val end elseif id == 79 then - local list = result.packed_sint32 - if list == nil then list = {}; result.packed_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sint32 + if list == nil then list = table_new(lim, 0); result.packed_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_packed_sint32 = _n_packed_sint32 + 1; list[_n_packed_sint32] = val end else + local list = result.packed_sint32 + if list == nil then list = {}; result.packed_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_packed_sint32 = _n_packed_sint32 + 1; list[_n_packed_sint32] = val end elseif id == 80 then - local list = result.packed_sint64 - if list == nil then list = {}; result.packed_sint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sint64 + if list == nil then list = table_new(lim, 0); result.packed_sint64 = list end while p2 <= lim do local val val, p2 = decode_sint64(payload, p2) _n_packed_sint64 = _n_packed_sint64 + 1; list[_n_packed_sint64] = val end else + local list = result.packed_sint64 + if list == nil then list = {}; result.packed_sint64 = list end local val val, pos = decode_sint64(buf, pos) _n_packed_sint64 = _n_packed_sint64 + 1; list[_n_packed_sint64] = val end elseif id == 81 then - local list = result.packed_fixed32 - if list == nil then list = {}; result.packed_fixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_fixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_fixed32 = list end while p2 <= lim do local val val, p2 = decode_fixed32(payload, p2) _n_packed_fixed32 = _n_packed_fixed32 + 1; list[_n_packed_fixed32] = val end else + local list = result.packed_fixed32 + if list == nil then list = {}; result.packed_fixed32 = list end local val val, pos = decode_fixed32(buf, pos) _n_packed_fixed32 = _n_packed_fixed32 + 1; list[_n_packed_fixed32] = val end elseif id == 82 then - local list = result.packed_fixed64 - if list == nil then list = {}; result.packed_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_packed_fixed64 = _n_packed_fixed64 + 1; list[_n_packed_fixed64] = val end else + local list = result.packed_fixed64 + if list == nil then list = {}; result.packed_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_packed_fixed64 = _n_packed_fixed64 + 1; list[_n_packed_fixed64] = val end elseif id == 83 then - local list = result.packed_sfixed32 - if list == nil then list = {}; result.packed_sfixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sfixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_sfixed32 = list end while p2 <= lim do local val val, p2 = decode_sfixed32(payload, p2) _n_packed_sfixed32 = _n_packed_sfixed32 + 1; list[_n_packed_sfixed32] = val end else + local list = result.packed_sfixed32 + if list == nil then list = {}; result.packed_sfixed32 = list end local val val, pos = decode_sfixed32(buf, pos) _n_packed_sfixed32 = _n_packed_sfixed32 + 1; list[_n_packed_sfixed32] = val end elseif id == 84 then - local list = result.packed_sfixed64 - if list == nil then list = {}; result.packed_sfixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sfixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_sfixed64 = list end while p2 <= lim do local val val, p2 = decode_sfixed64(payload, p2) _n_packed_sfixed64 = _n_packed_sfixed64 + 1; list[_n_packed_sfixed64] = val end else + local list = result.packed_sfixed64 + if list == nil then list = {}; result.packed_sfixed64 = list end local val val, pos = decode_sfixed64(buf, pos) _n_packed_sfixed64 = _n_packed_sfixed64 + 1; list[_n_packed_sfixed64] = val end elseif id == 85 then - local list = result.packed_float - if list == nil then list = {}; result.packed_float = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_float + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_float = list end while p2 <= lim do local val val, p2 = decode_float(payload, p2) _n_packed_float = _n_packed_float + 1; list[_n_packed_float] = val end else + local list = result.packed_float + if list == nil then list = {}; result.packed_float = list end local val val, pos = decode_float(buf, pos) _n_packed_float = _n_packed_float + 1; list[_n_packed_float] = val end elseif id == 86 then - local list = result.packed_double - if list == nil then list = {}; result.packed_double = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_double + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_double = list end while p2 <= lim do local val val, p2 = decode_double(payload, p2) _n_packed_double = _n_packed_double + 1; list[_n_packed_double] = val end else + local list = result.packed_double + if list == nil then list = {}; result.packed_double = list end local val val, pos = decode_double(buf, pos) _n_packed_double = _n_packed_double + 1; list[_n_packed_double] = val end elseif id == 87 then - local list = result.packed_bool - if list == nil then list = {}; result.packed_bool = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_bool + if list == nil then list = table_new(lim, 0); result.packed_bool = list end while p2 <= lim do local val val, p2 = decode_bool(payload, p2) _n_packed_bool = _n_packed_bool + 1; list[_n_packed_bool] = val end else + local list = result.packed_bool + if list == nil then list = {}; result.packed_bool = list end local val val, pos = decode_bool(buf, pos) _n_packed_bool = _n_packed_bool + 1; list[_n_packed_bool] = val end elseif id == 88 then - local list = result.packed_nested_enum - if list == nil then list = {}; result.packed_nested_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_nested_enum + if list == nil then list = table_new(lim, 0); result.packed_nested_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_packed_nested_enum = _n_packed_nested_enum + 1; list[_n_packed_nested_enum] = varint_to_int32(u) end else + local list = result.packed_nested_enum + if list == nil then list = {}; result.packed_nested_enum = list end local u u, pos = decode_varint(buf, pos) _n_packed_nested_enum = _n_packed_nested_enum + 1; list[_n_packed_nested_enum] = varint_to_int32(u) end elseif id == 89 then - local list = result.unpacked_int32 - if list == nil then list = {}; result.unpacked_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_int32 + if list == nil then list = table_new(lim, 0); result.unpacked_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_unpacked_int32 = _n_unpacked_int32 + 1; list[_n_unpacked_int32] = val end else + local list = result.unpacked_int32 + if list == nil then list = {}; result.unpacked_int32 = list end local val val, pos = decode_int32(buf, pos) _n_unpacked_int32 = _n_unpacked_int32 + 1; list[_n_unpacked_int32] = val end elseif id == 90 then - local list = result.unpacked_int64 - if list == nil then list = {}; result.unpacked_int64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_int64 + if list == nil then list = table_new(lim, 0); result.unpacked_int64 = list end while p2 <= lim do local val val, p2 = decode_int64(payload, p2) _n_unpacked_int64 = _n_unpacked_int64 + 1; list[_n_unpacked_int64] = val end else + local list = result.unpacked_int64 + if list == nil then list = {}; result.unpacked_int64 = list end local val val, pos = decode_int64(buf, pos) _n_unpacked_int64 = _n_unpacked_int64 + 1; list[_n_unpacked_int64] = val end elseif id == 91 then - local list = result.unpacked_uint32 - if list == nil then list = {}; result.unpacked_uint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_uint32 + if list == nil then list = table_new(lim, 0); result.unpacked_uint32 = list end while p2 <= lim do local val val, p2 = decode_uint32(payload, p2) _n_unpacked_uint32 = _n_unpacked_uint32 + 1; list[_n_unpacked_uint32] = val end else + local list = result.unpacked_uint32 + if list == nil then list = {}; result.unpacked_uint32 = list end local val val, pos = decode_uint32(buf, pos) _n_unpacked_uint32 = _n_unpacked_uint32 + 1; list[_n_unpacked_uint32] = val end elseif id == 92 then - local list = result.unpacked_uint64 - if list == nil then list = {}; result.unpacked_uint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_uint64 + if list == nil then list = table_new(lim, 0); result.unpacked_uint64 = list end while p2 <= lim do local val val, p2 = decode_uint64(payload, p2) _n_unpacked_uint64 = _n_unpacked_uint64 + 1; list[_n_unpacked_uint64] = val end else + local list = result.unpacked_uint64 + if list == nil then list = {}; result.unpacked_uint64 = list end local val val, pos = decode_uint64(buf, pos) _n_unpacked_uint64 = _n_unpacked_uint64 + 1; list[_n_unpacked_uint64] = val end elseif id == 93 then - local list = result.unpacked_sint32 - if list == nil then list = {}; result.unpacked_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sint32 + if list == nil then list = table_new(lim, 0); result.unpacked_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_unpacked_sint32 = _n_unpacked_sint32 + 1; list[_n_unpacked_sint32] = val end else + local list = result.unpacked_sint32 + if list == nil then list = {}; result.unpacked_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_unpacked_sint32 = _n_unpacked_sint32 + 1; list[_n_unpacked_sint32] = val end elseif id == 94 then - local list = result.unpacked_sint64 - if list == nil then list = {}; result.unpacked_sint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sint64 + if list == nil then list = table_new(lim, 0); result.unpacked_sint64 = list end while p2 <= lim do local val val, p2 = decode_sint64(payload, p2) _n_unpacked_sint64 = _n_unpacked_sint64 + 1; list[_n_unpacked_sint64] = val end else + local list = result.unpacked_sint64 + if list == nil then list = {}; result.unpacked_sint64 = list end local val val, pos = decode_sint64(buf, pos) _n_unpacked_sint64 = _n_unpacked_sint64 + 1; list[_n_unpacked_sint64] = val end elseif id == 95 then - local list = result.unpacked_fixed32 - if list == nil then list = {}; result.unpacked_fixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_fixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.unpacked_fixed32 = list end while p2 <= lim do local val val, p2 = decode_fixed32(payload, p2) _n_unpacked_fixed32 = _n_unpacked_fixed32 + 1; list[_n_unpacked_fixed32] = val end else + local list = result.unpacked_fixed32 + if list == nil then list = {}; result.unpacked_fixed32 = list end local val val, pos = decode_fixed32(buf, pos) _n_unpacked_fixed32 = _n_unpacked_fixed32 + 1; list[_n_unpacked_fixed32] = val end elseif id == 96 then - local list = result.unpacked_fixed64 - if list == nil then list = {}; result.unpacked_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.unpacked_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_unpacked_fixed64 = _n_unpacked_fixed64 + 1; list[_n_unpacked_fixed64] = val end else + local list = result.unpacked_fixed64 + if list == nil then list = {}; result.unpacked_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_unpacked_fixed64 = _n_unpacked_fixed64 + 1; list[_n_unpacked_fixed64] = val end elseif id == 97 then - local list = result.unpacked_sfixed32 - if list == nil then list = {}; result.unpacked_sfixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sfixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.unpacked_sfixed32 = list end while p2 <= lim do local val val, p2 = decode_sfixed32(payload, p2) _n_unpacked_sfixed32 = _n_unpacked_sfixed32 + 1; list[_n_unpacked_sfixed32] = val end else + local list = result.unpacked_sfixed32 + if list == nil then list = {}; result.unpacked_sfixed32 = list end local val val, pos = decode_sfixed32(buf, pos) _n_unpacked_sfixed32 = _n_unpacked_sfixed32 + 1; list[_n_unpacked_sfixed32] = val end elseif id == 98 then - local list = result.unpacked_sfixed64 - if list == nil then list = {}; result.unpacked_sfixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sfixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.unpacked_sfixed64 = list end while p2 <= lim do local val val, p2 = decode_sfixed64(payload, p2) _n_unpacked_sfixed64 = _n_unpacked_sfixed64 + 1; list[_n_unpacked_sfixed64] = val end else + local list = result.unpacked_sfixed64 + if list == nil then list = {}; result.unpacked_sfixed64 = list end local val val, pos = decode_sfixed64(buf, pos) _n_unpacked_sfixed64 = _n_unpacked_sfixed64 + 1; list[_n_unpacked_sfixed64] = val end elseif id == 99 then - local list = result.unpacked_float - if list == nil then list = {}; result.unpacked_float = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_float + if list == nil then list = table_new(rshift(lim, 2), 0); result.unpacked_float = list end while p2 <= lim do local val val, p2 = decode_float(payload, p2) _n_unpacked_float = _n_unpacked_float + 1; list[_n_unpacked_float] = val end else + local list = result.unpacked_float + if list == nil then list = {}; result.unpacked_float = list end local val val, pos = decode_float(buf, pos) _n_unpacked_float = _n_unpacked_float + 1; list[_n_unpacked_float] = val end elseif id == 100 then - local list = result.unpacked_double - if list == nil then list = {}; result.unpacked_double = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_double + if list == nil then list = table_new(rshift(lim, 3), 0); result.unpacked_double = list end while p2 <= lim do local val val, p2 = decode_double(payload, p2) _n_unpacked_double = _n_unpacked_double + 1; list[_n_unpacked_double] = val end else + local list = result.unpacked_double + if list == nil then list = {}; result.unpacked_double = list end local val val, pos = decode_double(buf, pos) _n_unpacked_double = _n_unpacked_double + 1; list[_n_unpacked_double] = val end elseif id == 101 then - local list = result.unpacked_bool - if list == nil then list = {}; result.unpacked_bool = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_bool + if list == nil then list = table_new(lim, 0); result.unpacked_bool = list end while p2 <= lim do local val val, p2 = decode_bool(payload, p2) _n_unpacked_bool = _n_unpacked_bool + 1; list[_n_unpacked_bool] = val end else + local list = result.unpacked_bool + if list == nil then list = {}; result.unpacked_bool = list end local val val, pos = decode_bool(buf, pos) _n_unpacked_bool = _n_unpacked_bool + 1; list[_n_unpacked_bool] = val end elseif id == 102 then - local list = result.unpacked_nested_enum - if list == nil then list = {}; result.unpacked_nested_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_nested_enum + if list == nil then list = table_new(lim, 0); result.unpacked_nested_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_unpacked_nested_enum = _n_unpacked_nested_enum + 1; list[_n_unpacked_nested_enum] = varint_to_int32(u) end else + local list = result.unpacked_nested_enum + if list == nil then list = {}; result.unpacked_nested_enum = list end local u u, pos = decode_varint(buf, pos) _n_unpacked_nested_enum = _n_unpacked_nested_enum + 1; list[_n_unpacked_nested_enum] = varint_to_int32(u) @@ -4406,6 +4534,30 @@ elseif id == 418 then local val val, pos = decode_int32(buf, pos) result.Field_name18__ = val + elseif id == 120 then + local _val + _val, pos = decode_int32(buf, pos) + local _e = result._extensions + if _e == nil then _e = {}; result._extensions = _e end + _e["protobuf_test_messages.proto2.extension_int32"] = _val + elseif id == 121 then + local _payload + _payload, pos = pb.codec.decode_group(M.GroupField_descriptor, buf, pos, 121) + local _e = result._extensions + if _e == nil then _e = {}; result._extensions = _e end + _e["protobuf_test_messages.proto2.groupfield"] = _payload + elseif id == 133 then + local _val + _val, pos = decode_string(buf, pos) + local _e = result._extensions + if _e == nil then _e = {}; result._extensions = _e end + _e["protobuf_test_messages.proto2.extension_string"] = _val + elseif id == 134 then + local _val + _val, pos = decode_bytes(buf, pos) + local _e = result._extensions + if _e == nil then _e = {}; result._extensions = _e end + _e["protobuf_test_messages.proto2.extension_bytes"] = _val else local _ebid = M.TestAllTypesProto2_descriptor.extensions_by_id local _ext = _ebid and _ebid[id] or nil @@ -4751,20 +4903,6 @@ n = n + 1; out[n] = wire.encode_varint(_len) end 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) @@ -4873,20 +5011,6 @@ if v ~= nil then 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) @@ -4990,20 +5114,6 @@ if v ~= nil then 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) @@ -5101,20 +5211,6 @@ if v ~= nil then 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) @@ -5208,20 +5304,6 @@ v = t.group_uint32 if v ~= nil then 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 @@ -5369,20 +5451,6 @@ n = n + 1; out[n] = _tag n = n + 1; out[n] = 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) @@ -5460,18 +5528,20 @@ local val val, pos = wire.decode_bool(buf, pos) result.optional_bool = val elseif id == 1011 then - local list = result.repeated_int32 - if list == nil then list = {}; result.repeated_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_int32 + if list == nil then list = table_new(lim, 0); result.repeated_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_repeated_int32 = _n_repeated_int32 + 1; list[_n_repeated_int32] = val end else + local list = result.repeated_int32 + if list == nil then list = {}; result.repeated_int32 = list end local val val, pos = decode_int32(buf, pos) _n_repeated_int32 = _n_repeated_int32 + 1; list[_n_repeated_int32] = val @@ -5548,20 +5618,6 @@ if v ~= nil then 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) @@ -5644,20 +5700,6 @@ error("expected table for protobuf_test_messages.proto2.NullHypothesisProto2, got " .. type(t), 0) 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) @@ -5732,20 +5774,6 @@ error("expected table for protobuf_test_messages.proto2.EnumOnlyProto2, got " .. type(t), 0) 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) @@ -5832,20 +5860,6 @@ n = n + 1; out[n] = wire.encode_varint(_len) end 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) @@ -5972,20 +5986,6 @@ else n = n + 1; out[n] = encode_varint(_len) end 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 @@ -6480,20 +6480,6 @@ else n = n + 1; out[n] = encode_varint(_len) end 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) @@ -6870,20 +6856,6 @@ n = n + 1; out[n] = encode_varint(_len) end 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) @@ -6999,20 +6971,6 @@ error("required field missing on encode: protobuf_test_messages.proto2.TestAllRequiredTypesProto2.Data.group_uint32", 0) 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) @@ -7166,20 +7124,6 @@ n = n + 1; out[n] = encode_varint(_len) end 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) @@ -7319,20 +7263,6 @@ error("expected table for protobuf_test_messages.proto2.TestLargeOneof.A1, got " .. type(t), 0) 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) @@ -7407,20 +7337,6 @@ error("expected table for protobuf_test_messages.proto2.TestLargeOneof.A2, got " .. type(t), 0) 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) @@ -7495,20 +7411,6 @@ error("expected table for protobuf_test_messages.proto2.TestLargeOneof.A3, got " .. type(t), 0) 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) @@ -7583,20 +7485,6 @@ error("expected table for protobuf_test_messages.proto2.TestLargeOneof.A4, got " .. type(t), 0) 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) @@ -7671,20 +7559,6 @@ error("expected table for protobuf_test_messages.proto2.TestLargeOneof.A5, got " .. type(t), 0) 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) diff --git a/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua b/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua index 25a77d67a3e1f22716176a8af1e62379ffb81a64..8eda178281f23d723d37c052db130647bed7c1a9 100644 --- a/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua +++ b/examples/expected/full/protobuf_test_messages/proto3/test_messages_proto3_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -2760,20 +2761,6 @@ if v ~= nil and v ~= 0 then n = n + 1; out[n] = "\x90\x1a" n = n + 1; out[n] = 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) @@ -3043,222 +3030,248 @@ else pb.codec.merge_message(M.TestAllTypesProto3_descriptor, prev, M.TestAllTypesProto3_decode(payload)) end elseif id == 31 then - local list = result.repeated_int32 - if list == nil then list = {}; result.repeated_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_int32 + if list == nil then list = table_new(lim, 0); result.repeated_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_repeated_int32 = _n_repeated_int32 + 1; list[_n_repeated_int32] = val end else + local list = result.repeated_int32 + if list == nil then list = {}; result.repeated_int32 = list end local val val, pos = decode_int32(buf, pos) _n_repeated_int32 = _n_repeated_int32 + 1; list[_n_repeated_int32] = val end elseif id == 32 then - local list = result.repeated_int64 - if list == nil then list = {}; result.repeated_int64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_int64 + if list == nil then list = table_new(lim, 0); result.repeated_int64 = list end while p2 <= lim do local val val, p2 = decode_int64(payload, p2) _n_repeated_int64 = _n_repeated_int64 + 1; list[_n_repeated_int64] = val end else + local list = result.repeated_int64 + if list == nil then list = {}; result.repeated_int64 = list end local val val, pos = decode_int64(buf, pos) _n_repeated_int64 = _n_repeated_int64 + 1; list[_n_repeated_int64] = val end elseif id == 33 then - local list = result.repeated_uint32 - if list == nil then list = {}; result.repeated_uint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_uint32 + if list == nil then list = table_new(lim, 0); result.repeated_uint32 = list end while p2 <= lim do local val val, p2 = decode_uint32(payload, p2) _n_repeated_uint32 = _n_repeated_uint32 + 1; list[_n_repeated_uint32] = val end else + local list = result.repeated_uint32 + if list == nil then list = {}; result.repeated_uint32 = list end local val val, pos = decode_uint32(buf, pos) _n_repeated_uint32 = _n_repeated_uint32 + 1; list[_n_repeated_uint32] = val end elseif id == 34 then - local list = result.repeated_uint64 - if list == nil then list = {}; result.repeated_uint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_uint64 + if list == nil then list = table_new(lim, 0); result.repeated_uint64 = list end while p2 <= lim do local val val, p2 = decode_uint64(payload, p2) _n_repeated_uint64 = _n_repeated_uint64 + 1; list[_n_repeated_uint64] = val end else + local list = result.repeated_uint64 + if list == nil then list = {}; result.repeated_uint64 = list end local val val, pos = decode_uint64(buf, pos) _n_repeated_uint64 = _n_repeated_uint64 + 1; list[_n_repeated_uint64] = val end elseif id == 35 then - local list = result.repeated_sint32 - if list == nil then list = {}; result.repeated_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sint32 + if list == nil then list = table_new(lim, 0); result.repeated_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_repeated_sint32 = _n_repeated_sint32 + 1; list[_n_repeated_sint32] = val end else + local list = result.repeated_sint32 + if list == nil then list = {}; result.repeated_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_repeated_sint32 = _n_repeated_sint32 + 1; list[_n_repeated_sint32] = val end elseif id == 36 then - local list = result.repeated_sint64 - if list == nil then list = {}; result.repeated_sint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sint64 + if list == nil then list = table_new(lim, 0); result.repeated_sint64 = list end while p2 <= lim do local val val, p2 = decode_sint64(payload, p2) _n_repeated_sint64 = _n_repeated_sint64 + 1; list[_n_repeated_sint64] = val end else + local list = result.repeated_sint64 + if list == nil then list = {}; result.repeated_sint64 = list end local val val, pos = decode_sint64(buf, pos) _n_repeated_sint64 = _n_repeated_sint64 + 1; list[_n_repeated_sint64] = val end elseif id == 37 then - local list = result.repeated_fixed32 - if list == nil then list = {}; result.repeated_fixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_fixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.repeated_fixed32 = list end while p2 <= lim do local val val, p2 = decode_fixed32(payload, p2) _n_repeated_fixed32 = _n_repeated_fixed32 + 1; list[_n_repeated_fixed32] = val end else + local list = result.repeated_fixed32 + if list == nil then list = {}; result.repeated_fixed32 = list end local val val, pos = decode_fixed32(buf, pos) _n_repeated_fixed32 = _n_repeated_fixed32 + 1; list[_n_repeated_fixed32] = val end elseif id == 38 then - local list = result.repeated_fixed64 - if list == nil then list = {}; result.repeated_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.repeated_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_repeated_fixed64 = _n_repeated_fixed64 + 1; list[_n_repeated_fixed64] = val end else + local list = result.repeated_fixed64 + if list == nil then list = {}; result.repeated_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_repeated_fixed64 = _n_repeated_fixed64 + 1; list[_n_repeated_fixed64] = val end elseif id == 39 then - local list = result.repeated_sfixed32 - if list == nil then list = {}; result.repeated_sfixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sfixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.repeated_sfixed32 = list end while p2 <= lim do local val val, p2 = decode_sfixed32(payload, p2) _n_repeated_sfixed32 = _n_repeated_sfixed32 + 1; list[_n_repeated_sfixed32] = val end else + local list = result.repeated_sfixed32 + if list == nil then list = {}; result.repeated_sfixed32 = list end local val val, pos = decode_sfixed32(buf, pos) _n_repeated_sfixed32 = _n_repeated_sfixed32 + 1; list[_n_repeated_sfixed32] = val end elseif id == 40 then - local list = result.repeated_sfixed64 - if list == nil then list = {}; result.repeated_sfixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_sfixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.repeated_sfixed64 = list end while p2 <= lim do local val val, p2 = decode_sfixed64(payload, p2) _n_repeated_sfixed64 = _n_repeated_sfixed64 + 1; list[_n_repeated_sfixed64] = val end else + local list = result.repeated_sfixed64 + if list == nil then list = {}; result.repeated_sfixed64 = list end local val val, pos = decode_sfixed64(buf, pos) _n_repeated_sfixed64 = _n_repeated_sfixed64 + 1; list[_n_repeated_sfixed64] = val end elseif id == 41 then - local list = result.repeated_float - if list == nil then list = {}; result.repeated_float = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_float + if list == nil then list = table_new(rshift(lim, 2), 0); result.repeated_float = list end while p2 <= lim do local val val, p2 = decode_float(payload, p2) _n_repeated_float = _n_repeated_float + 1; list[_n_repeated_float] = val end else + local list = result.repeated_float + if list == nil then list = {}; result.repeated_float = list end local val val, pos = decode_float(buf, pos) _n_repeated_float = _n_repeated_float + 1; list[_n_repeated_float] = val end elseif id == 42 then - local list = result.repeated_double - if list == nil then list = {}; result.repeated_double = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_double + if list == nil then list = table_new(rshift(lim, 3), 0); result.repeated_double = list end while p2 <= lim do local val val, p2 = decode_double(payload, p2) _n_repeated_double = _n_repeated_double + 1; list[_n_repeated_double] = val end else + local list = result.repeated_double + if list == nil then list = {}; result.repeated_double = list end local val val, pos = decode_double(buf, pos) _n_repeated_double = _n_repeated_double + 1; list[_n_repeated_double] = val end elseif id == 43 then - local list = result.repeated_bool - if list == nil then list = {}; result.repeated_bool = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_bool + if list == nil then list = table_new(lim, 0); result.repeated_bool = list end while p2 <= lim do local val val, p2 = decode_bool(payload, p2) _n_repeated_bool = _n_repeated_bool + 1; list[_n_repeated_bool] = val end else + local list = result.repeated_bool + if list == nil then list = {}; result.repeated_bool = list end local val val, pos = decode_bool(buf, pos) _n_repeated_bool = _n_repeated_bool + 1; list[_n_repeated_bool] = val @@ -3309,35 +3322,39 @@ local payload payload, pos = decode_len(buf, pos) _n_repeated_foreign_message = _n_repeated_foreign_message + 1; list[_n_repeated_foreign_message] = M.ForeignMessage_decode(payload) elseif id == 51 then - local list = result.repeated_nested_enum - if list == nil then list = {}; result.repeated_nested_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_nested_enum + if list == nil then list = table_new(lim, 0); result.repeated_nested_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_repeated_nested_enum = _n_repeated_nested_enum + 1; list[_n_repeated_nested_enum] = varint_to_int32(u) end else + local list = result.repeated_nested_enum + if list == nil then list = {}; result.repeated_nested_enum = list end local u u, pos = decode_varint(buf, pos) _n_repeated_nested_enum = _n_repeated_nested_enum + 1; list[_n_repeated_nested_enum] = varint_to_int32(u) end elseif id == 52 then - local list = result.repeated_foreign_enum - if list == nil then list = {}; result.repeated_foreign_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.repeated_foreign_enum + if list == nil then list = table_new(lim, 0); result.repeated_foreign_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_repeated_foreign_enum = _n_repeated_foreign_enum + 1; list[_n_repeated_foreign_enum] = varint_to_int32(u) end else + local list = result.repeated_foreign_enum + if list == nil then list = {}; result.repeated_foreign_enum = list end local u u, pos = decode_varint(buf, pos) _n_repeated_foreign_enum = _n_repeated_foreign_enum + 1; list[_n_repeated_foreign_enum] = varint_to_int32(u) @@ -3377,477 +3394,533 @@ val, pos = decode_string(buf, pos) _n_repeated_cord = _n_repeated_cord + 1; list[_n_repeated_cord] = val end elseif id == 75 then - local list = result.packed_int32 - if list == nil then list = {}; result.packed_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_int32 + if list == nil then list = table_new(lim, 0); result.packed_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_packed_int32 = _n_packed_int32 + 1; list[_n_packed_int32] = val end else + local list = result.packed_int32 + if list == nil then list = {}; result.packed_int32 = list end local val val, pos = decode_int32(buf, pos) _n_packed_int32 = _n_packed_int32 + 1; list[_n_packed_int32] = val end elseif id == 76 then - local list = result.packed_int64 - if list == nil then list = {}; result.packed_int64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_int64 + if list == nil then list = table_new(lim, 0); result.packed_int64 = list end while p2 <= lim do local val val, p2 = decode_int64(payload, p2) _n_packed_int64 = _n_packed_int64 + 1; list[_n_packed_int64] = val end else + local list = result.packed_int64 + if list == nil then list = {}; result.packed_int64 = list end local val val, pos = decode_int64(buf, pos) _n_packed_int64 = _n_packed_int64 + 1; list[_n_packed_int64] = val end elseif id == 77 then - local list = result.packed_uint32 - if list == nil then list = {}; result.packed_uint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_uint32 + if list == nil then list = table_new(lim, 0); result.packed_uint32 = list end while p2 <= lim do local val val, p2 = decode_uint32(payload, p2) _n_packed_uint32 = _n_packed_uint32 + 1; list[_n_packed_uint32] = val end else + local list = result.packed_uint32 + if list == nil then list = {}; result.packed_uint32 = list end local val val, pos = decode_uint32(buf, pos) _n_packed_uint32 = _n_packed_uint32 + 1; list[_n_packed_uint32] = val end elseif id == 78 then - local list = result.packed_uint64 - if list == nil then list = {}; result.packed_uint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_uint64 + if list == nil then list = table_new(lim, 0); result.packed_uint64 = list end while p2 <= lim do local val val, p2 = decode_uint64(payload, p2) _n_packed_uint64 = _n_packed_uint64 + 1; list[_n_packed_uint64] = val end else + local list = result.packed_uint64 + if list == nil then list = {}; result.packed_uint64 = list end local val val, pos = decode_uint64(buf, pos) _n_packed_uint64 = _n_packed_uint64 + 1; list[_n_packed_uint64] = val end elseif id == 79 then - local list = result.packed_sint32 - if list == nil then list = {}; result.packed_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sint32 + if list == nil then list = table_new(lim, 0); result.packed_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_packed_sint32 = _n_packed_sint32 + 1; list[_n_packed_sint32] = val end else + local list = result.packed_sint32 + if list == nil then list = {}; result.packed_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_packed_sint32 = _n_packed_sint32 + 1; list[_n_packed_sint32] = val end elseif id == 80 then - local list = result.packed_sint64 - if list == nil then list = {}; result.packed_sint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sint64 + if list == nil then list = table_new(lim, 0); result.packed_sint64 = list end while p2 <= lim do local val val, p2 = decode_sint64(payload, p2) _n_packed_sint64 = _n_packed_sint64 + 1; list[_n_packed_sint64] = val end else + local list = result.packed_sint64 + if list == nil then list = {}; result.packed_sint64 = list end local val val, pos = decode_sint64(buf, pos) _n_packed_sint64 = _n_packed_sint64 + 1; list[_n_packed_sint64] = val end elseif id == 81 then - local list = result.packed_fixed32 - if list == nil then list = {}; result.packed_fixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_fixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_fixed32 = list end while p2 <= lim do local val val, p2 = decode_fixed32(payload, p2) _n_packed_fixed32 = _n_packed_fixed32 + 1; list[_n_packed_fixed32] = val end else + local list = result.packed_fixed32 + if list == nil then list = {}; result.packed_fixed32 = list end local val val, pos = decode_fixed32(buf, pos) _n_packed_fixed32 = _n_packed_fixed32 + 1; list[_n_packed_fixed32] = val end elseif id == 82 then - local list = result.packed_fixed64 - if list == nil then list = {}; result.packed_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_packed_fixed64 = _n_packed_fixed64 + 1; list[_n_packed_fixed64] = val end else + local list = result.packed_fixed64 + if list == nil then list = {}; result.packed_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_packed_fixed64 = _n_packed_fixed64 + 1; list[_n_packed_fixed64] = val end elseif id == 83 then - local list = result.packed_sfixed32 - if list == nil then list = {}; result.packed_sfixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sfixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_sfixed32 = list end while p2 <= lim do local val val, p2 = decode_sfixed32(payload, p2) _n_packed_sfixed32 = _n_packed_sfixed32 + 1; list[_n_packed_sfixed32] = val end else + local list = result.packed_sfixed32 + if list == nil then list = {}; result.packed_sfixed32 = list end local val val, pos = decode_sfixed32(buf, pos) _n_packed_sfixed32 = _n_packed_sfixed32 + 1; list[_n_packed_sfixed32] = val end elseif id == 84 then - local list = result.packed_sfixed64 - if list == nil then list = {}; result.packed_sfixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_sfixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_sfixed64 = list end while p2 <= lim do local val val, p2 = decode_sfixed64(payload, p2) _n_packed_sfixed64 = _n_packed_sfixed64 + 1; list[_n_packed_sfixed64] = val end else + local list = result.packed_sfixed64 + if list == nil then list = {}; result.packed_sfixed64 = list end local val val, pos = decode_sfixed64(buf, pos) _n_packed_sfixed64 = _n_packed_sfixed64 + 1; list[_n_packed_sfixed64] = val end elseif id == 85 then - local list = result.packed_float - if list == nil then list = {}; result.packed_float = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_float + if list == nil then list = table_new(rshift(lim, 2), 0); result.packed_float = list end while p2 <= lim do local val val, p2 = decode_float(payload, p2) _n_packed_float = _n_packed_float + 1; list[_n_packed_float] = val end else + local list = result.packed_float + if list == nil then list = {}; result.packed_float = list end local val val, pos = decode_float(buf, pos) _n_packed_float = _n_packed_float + 1; list[_n_packed_float] = val end elseif id == 86 then - local list = result.packed_double - if list == nil then list = {}; result.packed_double = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_double + if list == nil then list = table_new(rshift(lim, 3), 0); result.packed_double = list end while p2 <= lim do local val val, p2 = decode_double(payload, p2) _n_packed_double = _n_packed_double + 1; list[_n_packed_double] = val end else + local list = result.packed_double + if list == nil then list = {}; result.packed_double = list end local val val, pos = decode_double(buf, pos) _n_packed_double = _n_packed_double + 1; list[_n_packed_double] = val end elseif id == 87 then - local list = result.packed_bool - if list == nil then list = {}; result.packed_bool = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_bool + if list == nil then list = table_new(lim, 0); result.packed_bool = list end while p2 <= lim do local val val, p2 = decode_bool(payload, p2) _n_packed_bool = _n_packed_bool + 1; list[_n_packed_bool] = val end else + local list = result.packed_bool + if list == nil then list = {}; result.packed_bool = list end local val val, pos = decode_bool(buf, pos) _n_packed_bool = _n_packed_bool + 1; list[_n_packed_bool] = val end elseif id == 88 then - local list = result.packed_nested_enum - if list == nil then list = {}; result.packed_nested_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.packed_nested_enum + if list == nil then list = table_new(lim, 0); result.packed_nested_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_packed_nested_enum = _n_packed_nested_enum + 1; list[_n_packed_nested_enum] = varint_to_int32(u) end else + local list = result.packed_nested_enum + if list == nil then list = {}; result.packed_nested_enum = list end local u u, pos = decode_varint(buf, pos) _n_packed_nested_enum = _n_packed_nested_enum + 1; list[_n_packed_nested_enum] = varint_to_int32(u) end elseif id == 89 then - local list = result.unpacked_int32 - if list == nil then list = {}; result.unpacked_int32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_int32 + if list == nil then list = table_new(lim, 0); result.unpacked_int32 = list end while p2 <= lim do local val val, p2 = decode_int32(payload, p2) _n_unpacked_int32 = _n_unpacked_int32 + 1; list[_n_unpacked_int32] = val end else + local list = result.unpacked_int32 + if list == nil then list = {}; result.unpacked_int32 = list end local val val, pos = decode_int32(buf, pos) _n_unpacked_int32 = _n_unpacked_int32 + 1; list[_n_unpacked_int32] = val end elseif id == 90 then - local list = result.unpacked_int64 - if list == nil then list = {}; result.unpacked_int64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_int64 + if list == nil then list = table_new(lim, 0); result.unpacked_int64 = list end while p2 <= lim do local val val, p2 = decode_int64(payload, p2) _n_unpacked_int64 = _n_unpacked_int64 + 1; list[_n_unpacked_int64] = val end else + local list = result.unpacked_int64 + if list == nil then list = {}; result.unpacked_int64 = list end local val val, pos = decode_int64(buf, pos) _n_unpacked_int64 = _n_unpacked_int64 + 1; list[_n_unpacked_int64] = val end elseif id == 91 then - local list = result.unpacked_uint32 - if list == nil then list = {}; result.unpacked_uint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_uint32 + if list == nil then list = table_new(lim, 0); result.unpacked_uint32 = list end while p2 <= lim do local val val, p2 = decode_uint32(payload, p2) _n_unpacked_uint32 = _n_unpacked_uint32 + 1; list[_n_unpacked_uint32] = val end else + local list = result.unpacked_uint32 + if list == nil then list = {}; result.unpacked_uint32 = list end local val val, pos = decode_uint32(buf, pos) _n_unpacked_uint32 = _n_unpacked_uint32 + 1; list[_n_unpacked_uint32] = val end elseif id == 92 then - local list = result.unpacked_uint64 - if list == nil then list = {}; result.unpacked_uint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_uint64 + if list == nil then list = table_new(lim, 0); result.unpacked_uint64 = list end while p2 <= lim do local val val, p2 = decode_uint64(payload, p2) _n_unpacked_uint64 = _n_unpacked_uint64 + 1; list[_n_unpacked_uint64] = val end else + local list = result.unpacked_uint64 + if list == nil then list = {}; result.unpacked_uint64 = list end local val val, pos = decode_uint64(buf, pos) _n_unpacked_uint64 = _n_unpacked_uint64 + 1; list[_n_unpacked_uint64] = val end elseif id == 93 then - local list = result.unpacked_sint32 - if list == nil then list = {}; result.unpacked_sint32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sint32 + if list == nil then list = table_new(lim, 0); result.unpacked_sint32 = list end while p2 <= lim do local val val, p2 = decode_sint32(payload, p2) _n_unpacked_sint32 = _n_unpacked_sint32 + 1; list[_n_unpacked_sint32] = val end else + local list = result.unpacked_sint32 + if list == nil then list = {}; result.unpacked_sint32 = list end local val val, pos = decode_sint32(buf, pos) _n_unpacked_sint32 = _n_unpacked_sint32 + 1; list[_n_unpacked_sint32] = val end elseif id == 94 then - local list = result.unpacked_sint64 - if list == nil then list = {}; result.unpacked_sint64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sint64 + if list == nil then list = table_new(lim, 0); result.unpacked_sint64 = list end while p2 <= lim do local val val, p2 = decode_sint64(payload, p2) _n_unpacked_sint64 = _n_unpacked_sint64 + 1; list[_n_unpacked_sint64] = val end else + local list = result.unpacked_sint64 + if list == nil then list = {}; result.unpacked_sint64 = list end local val val, pos = decode_sint64(buf, pos) _n_unpacked_sint64 = _n_unpacked_sint64 + 1; list[_n_unpacked_sint64] = val end elseif id == 95 then - local list = result.unpacked_fixed32 - if list == nil then list = {}; result.unpacked_fixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_fixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.unpacked_fixed32 = list end while p2 <= lim do local val val, p2 = decode_fixed32(payload, p2) _n_unpacked_fixed32 = _n_unpacked_fixed32 + 1; list[_n_unpacked_fixed32] = val end else + local list = result.unpacked_fixed32 + if list == nil then list = {}; result.unpacked_fixed32 = list end local val val, pos = decode_fixed32(buf, pos) _n_unpacked_fixed32 = _n_unpacked_fixed32 + 1; list[_n_unpacked_fixed32] = val end elseif id == 96 then - local list = result.unpacked_fixed64 - if list == nil then list = {}; result.unpacked_fixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_fixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.unpacked_fixed64 = list end while p2 <= lim do local val val, p2 = decode_fixed64(payload, p2) _n_unpacked_fixed64 = _n_unpacked_fixed64 + 1; list[_n_unpacked_fixed64] = val end else + local list = result.unpacked_fixed64 + if list == nil then list = {}; result.unpacked_fixed64 = list end local val val, pos = decode_fixed64(buf, pos) _n_unpacked_fixed64 = _n_unpacked_fixed64 + 1; list[_n_unpacked_fixed64] = val end elseif id == 97 then - local list = result.unpacked_sfixed32 - if list == nil then list = {}; result.unpacked_sfixed32 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sfixed32 + if list == nil then list = table_new(rshift(lim, 2), 0); result.unpacked_sfixed32 = list end while p2 <= lim do local val val, p2 = decode_sfixed32(payload, p2) _n_unpacked_sfixed32 = _n_unpacked_sfixed32 + 1; list[_n_unpacked_sfixed32] = val end else + local list = result.unpacked_sfixed32 + if list == nil then list = {}; result.unpacked_sfixed32 = list end local val val, pos = decode_sfixed32(buf, pos) _n_unpacked_sfixed32 = _n_unpacked_sfixed32 + 1; list[_n_unpacked_sfixed32] = val end elseif id == 98 then - local list = result.unpacked_sfixed64 - if list == nil then list = {}; result.unpacked_sfixed64 = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_sfixed64 + if list == nil then list = table_new(rshift(lim, 3), 0); result.unpacked_sfixed64 = list end while p2 <= lim do local val val, p2 = decode_sfixed64(payload, p2) _n_unpacked_sfixed64 = _n_unpacked_sfixed64 + 1; list[_n_unpacked_sfixed64] = val end else + local list = result.unpacked_sfixed64 + if list == nil then list = {}; result.unpacked_sfixed64 = list end local val val, pos = decode_sfixed64(buf, pos) _n_unpacked_sfixed64 = _n_unpacked_sfixed64 + 1; list[_n_unpacked_sfixed64] = val end elseif id == 99 then - local list = result.unpacked_float - if list == nil then list = {}; result.unpacked_float = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_float + if list == nil then list = table_new(rshift(lim, 2), 0); result.unpacked_float = list end while p2 <= lim do local val val, p2 = decode_float(payload, p2) _n_unpacked_float = _n_unpacked_float + 1; list[_n_unpacked_float] = val end else + local list = result.unpacked_float + if list == nil then list = {}; result.unpacked_float = list end local val val, pos = decode_float(buf, pos) _n_unpacked_float = _n_unpacked_float + 1; list[_n_unpacked_float] = val end elseif id == 100 then - local list = result.unpacked_double - if list == nil then list = {}; result.unpacked_double = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_double + if list == nil then list = table_new(rshift(lim, 3), 0); result.unpacked_double = list end while p2 <= lim do local val val, p2 = decode_double(payload, p2) _n_unpacked_double = _n_unpacked_double + 1; list[_n_unpacked_double] = val end else + local list = result.unpacked_double + if list == nil then list = {}; result.unpacked_double = list end local val val, pos = decode_double(buf, pos) _n_unpacked_double = _n_unpacked_double + 1; list[_n_unpacked_double] = val end elseif id == 101 then - local list = result.unpacked_bool - if list == nil then list = {}; result.unpacked_bool = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_bool + if list == nil then list = table_new(lim, 0); result.unpacked_bool = list end while p2 <= lim do local val val, p2 = decode_bool(payload, p2) _n_unpacked_bool = _n_unpacked_bool + 1; list[_n_unpacked_bool] = val end else + local list = result.unpacked_bool + if list == nil then list = {}; result.unpacked_bool = list end local val val, pos = decode_bool(buf, pos) _n_unpacked_bool = _n_unpacked_bool + 1; list[_n_unpacked_bool] = val end elseif id == 102 then - local list = result.unpacked_nested_enum - if list == nil then list = {}; result.unpacked_nested_enum = list end if wt == 2 then local payload payload, pos = decode_len(buf, pos) local p2, lim = 1, #payload + local list = result.unpacked_nested_enum + if list == nil then list = table_new(lim, 0); result.unpacked_nested_enum = list end while p2 <= lim do local u u, p2 = decode_varint(payload, p2) _n_unpacked_nested_enum = _n_unpacked_nested_enum + 1; list[_n_unpacked_nested_enum] = varint_to_int32(u) end else + local list = result.unpacked_nested_enum + if list == nil then list = {}; result.unpacked_nested_enum = list end local u u, pos = decode_varint(buf, pos) _n_unpacked_nested_enum = _n_unpacked_nested_enum + 1; list[_n_unpacked_nested_enum] = varint_to_int32(u) @@ -4694,20 +4767,6 @@ n = n + 1; out[n] = wire.encode_varint(_len) end 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) @@ -4799,20 +4858,6 @@ v = t.c if v ~= nil and v ~= 0 then 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 @@ -4891,20 +4936,6 @@ error("expected table for protobuf_test_messages.proto3.NullHypothesisProto3, got " .. type(t), 0) 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) @@ -4979,20 +5010,6 @@ error("expected table for protobuf_test_messages.proto3.EnumOnlyProto3, got " .. type(t), 0) 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) diff --git a/examples/expected/full/quickstart/quickstart_pb.lua b/examples/expected/full/quickstart/quickstart_pb.lua index 4a6494eeb0d5fe0c4dbd40b5703bf35dbe5dc289..6e53d8d067f5fae60ddc5913d2949f0fa330b786 100644 --- a/examples/expected/full/quickstart/quickstart_pb.lua +++ b/examples/expected/full/quickstart/quickstart_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} @@ -115,20 +116,6 @@ else n = n + 1; out[n] = encode_varint(_len) end 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 diff --git a/examples/expected/runtime/c_int64/c_int64_pb.lua b/examples/expected/runtime/c_int64/c_int64_pb.lua index 23441b30318c48dda0e947dbd757e9c34ecbdf74..d014e6cfaab713339b0926dbee68d20521244fb2 100644 --- a/examples/expected/runtime/c_int64/c_int64_pb.lua +++ b/examples/expected/runtime/c_int64/c_int64_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/c_nested/c_nested_pb.lua b/examples/expected/runtime/c_nested/c_nested_pb.lua index 707cd31b54e5389f88c493ebf98f17fae792dbe8..ebda75ff8e961154a4dda9569348296b4645bd97 100644 --- a/examples/expected/runtime/c_nested/c_nested_pb.lua +++ b/examples/expected/runtime/c_nested/c_nested_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/c_repeated/c_repeated_pb.lua b/examples/expected/runtime/c_repeated/c_repeated_pb.lua index 1a9339ff85d51038c7ad000c85e39c2e10093f65..0291a11c543c634dc4319e441e5cff542bcb5216 100644 --- a/examples/expected/runtime/c_repeated/c_repeated_pb.lua +++ b/examples/expected/runtime/c_repeated/c_repeated_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/conformance/conformance_pb.lua b/examples/expected/runtime/conformance/conformance_pb.lua index 0db005fb1157ae0daef0babf3ae40a0daa92399d..61974dc546563e5bae067d02d201753e0bcfa35a 100644 --- a/examples/expected/runtime/conformance/conformance_pb.lua +++ b/examples/expected/runtime/conformance/conformance_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/hello/hello_pb.lua b/examples/expected/runtime/hello/hello_pb.lua index f74e7a72b36e274f7bd06bfbc8e70b842f37b36a..49bb7389984c060e13a123ecc8fc88c809d35331 100644 --- a/examples/expected/runtime/hello/hello_pb.lua +++ b/examples/expected/runtime/hello/hello_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/proto2_basic/proto2_basic_pb.lua b/examples/expected/runtime/proto2_basic/proto2_basic_pb.lua index a6a904ff4b61e9ff24189c73282648ac8f58121e..967154a9522fe2445a2510fd5d963234cb05c859 100644 --- a/examples/expected/runtime/proto2_basic/proto2_basic_pb.lua +++ b/examples/expected/runtime/proto2_basic/proto2_basic_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/protobuf_test_messages/proto2/test_messages_proto2_pb.lua b/examples/expected/runtime/protobuf_test_messages/proto2/test_messages_proto2_pb.lua index 95af5739182e6fb4e9c3362e4c9d88cbf9666ef8..bb73066c8c58baa621089b0037be4248eb2d3a97 100644 --- a/examples/expected/runtime/protobuf_test_messages/proto2/test_messages_proto2_pb.lua +++ b/examples/expected/runtime/protobuf_test_messages/proto2/test_messages_proto2_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/protobuf_test_messages/proto3/test_messages_proto3_pb.lua b/examples/expected/runtime/protobuf_test_messages/proto3/test_messages_proto3_pb.lua index 9878619f254b079d42575d23717535a10013c96e..dfb17a36ac2ef1de9ca2626cd461ecb16c28e154 100644 --- a/examples/expected/runtime/protobuf_test_messages/proto3/test_messages_proto3_pb.lua +++ b/examples/expected/runtime/protobuf_test_messages/proto3/test_messages_proto3_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {} diff --git a/examples/expected/runtime/quickstart/quickstart_pb.lua b/examples/expected/runtime/quickstart/quickstart_pb.lua index e1ff77f3037f13fe9ce6a5a3f26bd54b448500ff..0da84c686271e36b6e1bc87137f9c6bdacda78d8 100644 --- a/examples/expected/runtime/quickstart/quickstart_pb.lua +++ b/examples/expected/runtime/quickstart/quickstart_pb.lua @@ -9,6 +9,7 @@ local string_byte = string.byte local utf8_len = require('utf8').len local band = bit.band local rshift = bit.rshift +local table_new = require('table.new') local M = {}