~bigbes/tarantool

tarantool-protobuf

ref: b624a6bf75cfdf7ff59c14073e6b1ecc21f9f143 tarantool-protobuf/cmd/protoc-gen-tarantool/internal/gen/inline.go -rw-r--r-- 38.6 KiB
b624a6bf — Eugene Blikh beads: close bgu (ffi.string decode disproven) + memory note on buffer-reuse trap 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
package gen

import (
	"fmt"
	"strings"

	"google.golang.org/protobuf/compiler/protogen"
	"google.golang.org/protobuf/reflect/protoreflect"
)

// 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.<typed> call.
func emitInlineMessage(w *writer, file *protogen.File, m *protogen.Message, imports map[string]string, prefix string) {
	name := luaTypeName(m.Desc.FullName(), file.Desc.Package())
	full := emmyMessageFullName(m)
	selfPath := luaPackagePath(file.Desc, prefix)

	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)
	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)
	w.line("function M.%s_text(t, opts) return pb.text.encode(M.%s_descriptor, t, opts) end", name, name)
	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) {
	emitEmmyWrapperAnnotations(w, name, emmyMessageFullName(m), wrapperEncode)
	w.line("function M.%s_encode(t)", name)
	// C-acceleration: when PB_ENABLE_C=1 was set at module load, dispatch
	// into pb.c_runtime.encode. Plan compilation is lazy on first call —
	// eager compile would chase sub-message refs that aren't filled in
	// yet when finalize_message runs at module load (see init.lua). On
	// the default pure-Lua build pb.c_runtime is nil and the branch is a
	// single nil-compare.
	w.line("    local _d = M.%s_descriptor", name)
	w.line("    if pb.c_runtime ~= nil then")
	w.line("        local _p = _d.c_plan or pb.c_runtime.compile_plan(_d)")
	w.line("        return pb.c_runtime.encode(_p, t)")
	w.line("    end")
	w.line("    if type(t) ~= 'table' then")
	w.line("        error(\"expected table for %s, got \" .. type(t), 0)", m.Desc.FullName())
	w.line("    end")
	w.line("    local out, n = {}, 0")
	w.line("    local v")

	// Oneof pre-pass: pick the active branch per oneof (last-set wins).
	for _, oo := range realOneofs(m) {
		w.line("    local %s", oneofVar(string(oo.Desc.Name())))
		for _, f := range oo.Fields {
			w.line("    if %s ~= nil then %s = %q end",
				luaFieldAccess("t", string(f.Desc.Name())),
				oneofVar(string(oo.Desc.Name())),
				string(f.Desc.Name()))
		}
	}

	for _, f := range m.Fields {
		emitInlineEncodeField(w, f, file, selfPath, imports, prefix)
	}
	// Proto2 extensions: delegate to pb.codec.encode_field once per set
	// entry. We don't inline an extension-specific writer here because
	// extensions are runtime-mutable — a user can register more after the
	// module loads — so the canonical iteration source is the descriptor's
	// extensions_list. The walk is JIT-stable (array, not pairs over a
	// hash). Skip entirely when extensions_list is nil (most proto3 messages
	// and proto2 messages without `extensions` ranges) so the hot path
	// pays nothing.
	w.line("    local _exts = t._extensions")
	w.line("    if _exts ~= nil then")
	w.line("        local _elist = M.%s_descriptor.extensions_list", name)
	w.line("        if _elist ~= nil then")
	w.line("            for _i = 1, #_elist do")
	w.line("                local _ext = _elist[_i]")
	w.line("                local _ev = _exts[_ext.full_name]")
	w.line("                if _ev ~= nil then")
	w.line("                    pb.codec.encode_field(_ext, _ev, out, true)")
	w.line("                end")
	w.line("            end")
	// encode_field uses out[#out + 1] = … and doesn't know about our
	// local `n` cursor — resync so the unknown-fields append below lands
	// after the extension bytes, not on top of them.
	w.line("            n = #out")
	w.line("        end")
	w.line("    end")
	// Preserve unknown fields captured at decode time.
	w.line("    local _uf = t._unknown_fields")
	w.line("    if _uf ~= nil and _uf ~= '' then n = n + 1; out[n] = _uf end")
	w.line("    return table.concat(out)")
	w.line("end")
	w.line("")
}

// emitInlineLenPrefix emits the length-prefix append for a length-delimited
// field (LEN wire type: string, bytes, message body, packed scalars).
//
// Lifts the 1-byte varint fast path out of wire.encode_varint and inlines it
// at the call site. Eliminates the function call + dispatch on the dominant
// short-payload case (length < 128). encode_varint dispatch alone was ~17%
// of encode time on the hello.Person 1KB benchmark before this; the
// surrounding `out[n] = wire.encode_varint(#_b)` was another ~33%.
//
// `indent` is the Lua indentation string (e.g. "    " or "        ") that
// each emitted line starts with. `bodyExpr` is the Lua expression for the
// payload local (typically "v" or "_b"); its length is read once into a
// local so `#bodyExpr` doesn't re-evaluate. Caller is responsible for
// emitting the tag and the body itself around this call.
func emitInlineLenPrefix(w *writer, indent, bodyExpr string) {
	w.line("%slocal _len = #%s", indent, bodyExpr)
	w.line("%sif _len < 128 then", indent)
	w.line("%s    n = n + 1; out[n] = string.char(_len)", indent)
	w.line("%selse", indent)
	w.line("%s    n = n + 1; out[n] = wire.encode_varint(_len)", indent)
	w.line("%send", indent)
}

// realOneofs returns the message's non-synthetic oneofs (skips the ones
// proto3 expands explicit `optional` into).
func realOneofs(m *protogen.Message) []*protogen.Oneof {
	var out []*protogen.Oneof
	for _, oo := range m.Oneofs {
		if oo.Fields[0].Desc.HasOptionalKeyword() {
			continue
		}
		out = append(out, oo)
	}
	return out
}

func oneofVar(name string) string { return "_of_" + name }

// fieldRealOneof returns the oneof name a field belongs to, or "" if the
// field is not in a real oneof (i.e. either standalone or in a synthetic
// proto3 explicit-optional oneof).
func fieldRealOneof(f *protogen.Field) string {
	if f.Oneof == nil || f.Desc.HasOptionalKeyword() {
		return ""
	}
	return string(f.Oneof.Desc.Name())
}

func emitInlineEncodeField(w *writer, f *protogen.Field, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	id := int32(f.Desc.Number())
	tag := tagBytesLit(id, wireTypeForField(f))
	fname := string(f.Desc.Name())

	w.line("    -- field %d: %s", id, fname)
	w.line("    v = %s", luaFieldAccess("t", fname))

	// Proto2 `required`: error on encode if missing, never elide. Mutually
	// exclusive with oneof and repeated, so the rest of the branching below
	// stays unchanged for non-required fields.
	if f.Desc.Cardinality() == protoreflect.Required {
		emitInlineEncodeRequiredField(w, f, tag, file, selfPath, imports, prefix)
		return
	}

	oneof := fieldRealOneof(f)
	// Default presence gate: a regular nil check. For message fields we
	// also need to accept box.NULL (which == nil via Tarantool's cdata
	// metamethod) because google.protobuf.Value uses it as the canonical
	// null_value sentinel.
	gate := "v ~= nil"
	if oneof != "" {
		gate = fmt.Sprintf("%s == %q", oneofVar(oneof), fname)
	} else if f.Message != nil {
		gate = "v ~= nil or type(v) == 'cdata'"
	}
	// Presence semantics: oneof branches, proto3 explicit `optional`, and
	// every proto2 singular field (`optional` keyword). No default elision.
	hasPresence := oneof != "" || f.Desc.HasOptionalKeyword()

	switch {
	case f.Desc.IsMap():
		emitInlineEncodeMap(w, f, tag, file, selfPath, imports, prefix)
	case f.Desc.IsList():
		emitInlineEncodeRepeated(w, f, tag, fname, file, selfPath, imports, prefix)
	case f.Message != nil:
		ref := typeRef(file, f.Message.Desc, selfPath, imports, "_encode", prefix)
		if f.Desc.Kind() == protoreflect.GroupKind {
			// Proto2 group: SGROUP tag + body + EGROUP tag. No length
			// prefix — the receiver reads until the matching EGROUP id.
			endTag := tagBytesLit(int32(f.Desc.Number()), 4 /* EGROUP */)
			w.line("    if %s then", gate)
			w.line("        n = n + 1; out[n] = %s", tag)
			w.line("        n = n + 1; out[n] = %s(v)", ref)
			w.line("        n = n + 1; out[n] = %s", endTag)
			w.line("    end")
		} else {
			// Split the length-delimited payload into separate `out`
			// slots: emit tag, varint(#body), body. Avoids the per-field
			// concat that wire.encode_len would do.
			w.line("    if %s then", gate)
			w.line("        local _b = %s(v)", 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 f.Enum != nil:
		enumLocal := typeRef(file, f.Enum.Desc, selfPath, imports, "", prefix)
		fullName := string(f.Enum.Desc.FullName())
		// Presence (oneof or optional): emit even when value is the enum default.
		w.line("    if %s then", gate)
		w.line("        local nv = v")
		w.line("        if type(v) == 'string' then")
		w.line("            nv = %s[v]", enumLocal)
		w.line("            if nv == nil then error(\"unknown enum value '\" .. v .. \"' for %s\", 0) end", fullName)
		w.line("        end")
		if !hasPresence {
			w.line("        if nv ~= 0 then")
			w.line("            n = n + 1; out[n] = %s", tag)
			w.line("            n = n + 1; out[n] = wire.encode_int32(nv)")
			w.line("        end")
		} else {
			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(f.Desc.Kind())
		if st == "" {
			panic("unhandled scalar kind: " + f.Desc.Kind().String())
		}
		if !hasPresence {
			w.line("    if v ~= nil and %s then", scalarNotDefaultExpr(st, "v"))
		} else {
			w.line("    if %s then", gate)
		}
		if st == "string" || st == "bytes" {
			// Length-delimited scalar: same split rationale as nested
			// messages above. `encode_string` / `encode_bytes` would
			// concatenate the length prefix and body — emit them as
			// separate `out` slots instead and let table.concat join.
			w.line("        n = n + 1; out[n] = %s", tag)
			emitInlineLenPrefix(w, "        ", "v")
			w.line("        n = n + 1; out[n] = v")
		} else {
			w.line("        n = n + 1; out[n] = %s", tag)
			w.line("        n = n + 1; out[n] = wire.encode_%s(v)", st)
		}
		w.line("    end")
	}
}

// emitInlineEncodeRequiredField generates the encode body for a proto2
// `required` field: error if missing, always emit (no default elision).
func emitInlineEncodeRequiredField(w *writer, f *protogen.Field, tag string, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	fullName := string(f.Desc.FullName())
	w.line("    if v == nil then")
	w.line("        error(%q, 0)", "required field missing on encode: "+fullName)
	w.line("    end")
	switch {
	case f.Message != nil:
		ref := typeRef(file, f.Message.Desc, selfPath, imports, "_encode", prefix)
		w.line("    local _b = %s(v)", ref)
		w.line("    n = n + 1; out[n] = %s", tag)
		emitInlineLenPrefix(w, "    ", "_b")
		w.line("    n = n + 1; out[n] = _b")
	case f.Enum != nil:
		enumLocal := typeRef(file, f.Enum.Desc, selfPath, imports, "", prefix)
		enumFull := string(f.Enum.Desc.FullName())
		w.line("    do")
		w.line("        local nv = v")
		w.line("        if type(v) == 'string' then")
		w.line("            nv = %s[v]", enumLocal)
		w.line("            if nv == nil then error(\"unknown enum value '\" .. v .. \"' 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(f.Desc.Kind())
		if st == "" {
			panic("unhandled scalar kind: " + f.Desc.Kind().String())
		}
		if st == "string" || st == "bytes" {
			w.line("    n = n + 1; out[n] = %s", tag)
			emitInlineLenPrefix(w, "    ", "v")
			w.line("    n = n + 1; out[n] = v")
		} else {
			w.line("    n = n + 1; out[n] = %s", tag)
			w.line("    n = n + 1; out[n] = wire.encode_%s(v)", st)
		}
	}
}

func emitInlineEncodeRepeated(w *writer, f *protogen.Field, tag, fname string, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	switch {
	case f.Message != nil:
		ref := typeRef(file, f.Message.Desc, selfPath, imports, "_encode", prefix)
		if f.Desc.Kind() == protoreflect.GroupKind {
			endTag := tagBytesLit(int32(f.Desc.Number()), 4 /* EGROUP */)
			w.line("    if v ~= nil and #v > 0 then")
			w.line("        local _stag = %s", tag)
			w.line("        local _etag = %s", endTag)
			w.line("        for _i = 1, #v do")
			w.line("            n = n + 1; out[n] = _stag")
			w.line("            n = n + 1; out[n] = %s(v[_i])", ref)
			w.line("            n = n + 1; out[n] = _etag")
			w.line("        end")
			w.line("    end")
		} else {
			w.line("    if v ~= nil and #v > 0 then")
			w.line("        local _tag = %s", tag)
			w.line("        for _i = 1, #v do")
			w.line("            local _b = %s(v[_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 f.Enum != nil:
		enumLocal := typeRef(file, f.Enum.Desc, selfPath, imports, "", prefix)
		fullName := string(f.Enum.Desc.FullName())
		w.line("    if v ~= nil and #v > 0 then")
		w.line("        local parts, m = {}, 0")
		w.line("        for _i = 1, #v do")
		w.line("            local elem = v[_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", fullName)
		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")
		w.line("    end")
	default:
		st := scalarName(f.Desc.Kind())
		packable := st != "string" && st != "bytes"
		if packable && f.Desc.IsPacked() {
			w.line("    if v ~= nil and #v > 0 then")
			w.line("        local parts, m = {}, 0")
			w.line("        for _i = 1, #v do")
			w.line("            m = m + 1; parts[m] = wire.encode_%s(v[_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 v ~= nil and #v > 0 then")
			w.line("        local _tag = %s", tag)
			w.line("        for _i = 1, #v do")
			w.line("            local _b = v[_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 v ~= nil and #v > 0 then")
			w.line("        local _tag = %s", tag)
			w.line("        for _i = 1, #v do")
			w.line("            n = n + 1; out[n] = _tag")
			w.line("            n = n + 1; out[n] = wire.encode_%s(v[_i])", st)
			w.line("        end")
			w.line("    end")
		}
	}
}

func emitInlineDecode(w *writer, name string, m *protogen.Message, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	emitEmmyWrapperAnnotations(w, name, emmyMessageFullName(m), wrapperDecode)
	w.line("function M.%s_decode(buf)", name)
	// C-acceleration: see emitInlineEncode for rationale and lazy-compile.
	w.line("    local _d = M.%s_descriptor", name)
	w.line("    if pb.c_runtime ~= nil then")
	w.line("        local _p = _d.c_plan or pb.c_runtime.compile_plan(_d)")
	w.line("        return pb.c_runtime.decode(_p, buf)")
	w.line("    end")
	w.line("    if type(buf) ~= 'string' then")
	w.line("        error(\"expected string for %s decode, got \" .. type(buf), 0)", m.Desc.FullName())
	w.line("    end")
	w.line("    local result = {}")
	w.line("    local pos, len = 1, #buf")
	w.line("    local _uf")
	// Per-repeated-field counters. Replace `#list + 1` (re-traverses
	// the list every append) with `_n_<fname> = _n_<fname> + 1`. The
	// counter survives across loop iterations, so out-of-order wire
	// entries for the same field continue counting from the existing
	// position without re-scanning. Map fields don't need a counter
	// (hash keys, not array indices).
	for _, f := range m.Fields {
		if f.Desc.IsList() && !f.Desc.IsMap() {
			w.line("    local _n_%s = 0", string(f.Desc.Name()))
		}
	}
	w.line("    while pos <= len do")
	w.line("        local _tag_start = pos")
	w.line("        local id, wt")
	// Inline the 1-byte tag fast path. The protobuf spec encodes field
	// numbers 1..15 (with any wire type) in a single byte, and the
	// codegen orderings + our test corpora keep nearly every dispatch
	// here on the fast branch. Removes the wire.decode_tag function
	// frame for the dominant case; multi-byte tags fall back to the
	// generic decoder.
	w.line("        local _b = string_byte(buf, pos)")
	w.line("        if _b ~= nil and _b < 0x80 then")
	w.line("            wt = band(_b, 7)")
	w.line("            if wt >= 6 then error(\"illegal wire type \" .. wt, 0) end")
	w.line("            id = rshift(_b, 3)")
	w.line("            if id == 0 then error(\"illegal field number 0\", 0) end")
	w.line("            pos = pos + 1")
	w.line("        else")
	w.line("            id, wt, pos = wire.decode_tag(buf, pos)")
	w.line("        end")

	first := true
	for _, f := range m.Fields {
		op := "elseif"
		if first {
			op = "if"
			first = false
		}
		w.line("        %s id == %d then", op, f.Desc.Number())
		emitInlineDecodeFieldBody(w, f, 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].
	w.line("            local _ebid = M.%s_descriptor.extensions_by_id", name)
	w.line("            local _ext = _ebid and _ebid[id] or nil")
	w.line("            if _ext ~= nil then")
	w.line("                pos = pb.codec.decode_extension(_ext, buf, pos, wt, result)")
	w.line("            else")
	w.line("                pos = wire.skip_field(buf, pos, wt, id)")
	w.line("                if _uf == nil then _uf = {} end")
	w.line("                _uf[#_uf + 1] = buf:sub(_tag_start, pos - 1)")
	w.line("            end")
	w.line("        end")
	w.line("    end")
	w.line("    if _uf ~= nil then result._unknown_fields = table.concat(_uf) end")
	w.line("    return result")
	w.line("end")
	w.line("")
}

func emitInlineDecodeFieldBody(w *writer, f *protogen.Field, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	fname := string(f.Desc.Name())
	switch {
	case f.Desc.IsMap():
		emitInlineDecodeMap(w, f, fname, file, selfPath, imports, prefix)
	case f.Desc.IsList():
		emitInlineDecodeRepeated(w, f, fname, file, selfPath, imports, prefix)
	case f.Message != nil:
		ref := typeRef(file, f.Message.Desc, selfPath, imports, "_decode", prefix)
		dst := luaFieldAccess("result", fname)
		descRef := typeRef(file, f.Message.Desc, selfPath, imports, "_descriptor", prefix)
		if f.Desc.Kind() == protoreflect.GroupKind {
			// Group: no length prefix. The codec reads body fields until
			// it hits an EGROUP tag matching this field's id; returns the
			// decoded table and the new position.
			w.line("            local payload")
			w.line("            payload, pos = pb.codec.decode_group(%s, buf, pos, %d)",
				descRef, f.Desc.Number())
			w.line("            local prev = %s", dst)
			w.line("            if prev == nil then")
			w.line("                %s = payload", dst)
			w.line("            else")
			w.line("                pb.codec.merge_message(%s, prev, payload)", descRef)
			w.line("            end")
		} else {
			w.line("            local payload")
			w.line("            payload, pos = wire.decode_len(buf, pos)")
			if isWellKnownTypeFile(f.Message.Desc.ParentFile()) {
				// WKT decoders return unwrapped values (datetime, number, string),
				// not Lua tables — there is nothing to merge into. Replace.
				w.line("            %s = %s(payload)", dst, ref)
			} else {
				// Per proto3 spec, repeated occurrences of a singular message
				// field merge recursively. This holds for oneof branches too;
				// sibling clearing below enforces oneof exclusivity.
				w.line("            local prev = %s", dst)
				w.line("            if prev == nil then")
				w.line("                %s = %s(payload)", dst, ref)
				w.line("            else")
				w.line("                pb.codec.merge_message(%s, prev, %s(payload))",
					descRef, ref)
				w.line("            end")
			}
		}
	case f.Enum != nil:
		w.line("            local u")
		w.line("            u, pos = wire.decode_varint(buf, pos)")
		w.line("            %s = wire.varint_to_int32(u)", luaFieldAccess("result", fname))
	default:
		st := scalarName(f.Desc.Kind())
		if st == "string" || st == "bytes" {
			// Inline the 1-byte LEN fast path (length < 128). Skips the
			// `wire.decode_string` / `wire.decode_bytes` function call
			// frame for the typical short-string case; the resulting
			// straight-line code stays inside the parent JIT trace
			// instead of stitching through a child trace. (a6n)
			dst := luaFieldAccess("result", fname)
			emitInlineStringBytesScalar(w, st, dst)
		} else {
			w.line("            local val")
			w.line("            val, pos = wire.decode_%s(buf, pos)", st)
			w.line("            %s = val", luaFieldAccess("result", fname))
		}
	}

	// Oneof: clear sibling branches so callers see exactly one set field.
	if oneof := fieldRealOneof(f); oneof != "" {
		for _, sib := range f.Oneof.Fields {
			if sib == f {
				continue
			}
			w.line("            %s = nil",
				luaFieldAccess("result", string(sib.Desc.Name())))
		}
	}
}

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)

	switch {
	case f.Message != nil:
		ref := typeRef(file, f.Message.Desc, selfPath, imports, "_decode", prefix)
		if f.Desc.Kind() == protoreflect.GroupKind {
			descRef := typeRef(file, f.Message.Desc, selfPath, imports, "_descriptor", prefix)
			w.line("            local payload")
			w.line("            payload, pos = pb.codec.decode_group(%s, buf, pos, %d)",
				descRef, f.Desc.Number())
			w.line("            %s = %s + 1; list[%s] = payload", cnt, cnt, cnt)
		} else {
			w.line("            local payload")
			w.line("            payload, pos = wire.decode_len(buf, pos)")
			w.line("            %s = %s + 1; list[%s] = %s(payload)", cnt, cnt, cnt, ref)
		}
	case f.Enum != nil:
		// Enums are packable (proto3 default). Accept both packed and per-element.
		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("                    %s = %s + 1; list[%s] = wire.varint_to_int32(u)", cnt, cnt, cnt)
		w.line("                end")
		w.line("            else")
		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("                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 val")
			w.line("                val, pos = wire.decode_%s(buf, pos)", st)
			w.line("                %s = %s + 1; list[%s] = val", cnt, cnt, cnt)
			w.line("            end")
		} else {
			// Repeated string/bytes — inline 1-byte LEN fast path. (a6n)
			emitInlineStringBytesRepeated(w, st, cnt)
		}
	}
}

// emitInlineStringBytesScalar emits the singular string/bytes decode with the
// 1-byte LEN fast path inlined. Falls back to `wire.decode_<st>` for lengths
// >= 128. UTF-8 validation runs only for `string`, not `bytes`. (a6n)
func emitInlineStringBytesScalar(w *writer, st, dst string) {
	w.line("            local _lb = string_byte(buf, pos)")
	w.line("            if _lb ~= nil and _lb < 0x80 then")
	w.line("                local _np = pos + 1")
	w.line("                local _epos = _np + _lb")
	w.line("                if _epos - 1 > len then error(\"truncated LEN at offset \" .. pos, 0) end")
	w.line("                local _s = buf:sub(_np, _epos - 1)")
	if st == "string" {
		w.line("                if utf8_len(_s) == nil then error(\"invalid UTF-8 in string field at offset \" .. pos, 0) end")
	}
	w.line("                %s = _s", dst)
	w.line("                pos = _epos")
	w.line("            else")
	w.line("                local val")
	w.line("                val, pos = wire.decode_%s(buf, pos)", st)
	w.line("                %s = val", dst)
	w.line("            end")
}

// emitInlineStringBytesRepeated mirrors emitInlineStringBytesScalar but
// appends to the per-field list via the `_n_<f>` counter. (a6n)
func emitInlineStringBytesRepeated(w *writer, st, cnt string) {
	w.line("            local _lb = string_byte(buf, pos)")
	w.line("            if _lb ~= nil and _lb < 0x80 then")
	w.line("                local _np = pos + 1")
	w.line("                local _epos = _np + _lb")
	w.line("                if _epos - 1 > len then error(\"truncated LEN at offset \" .. pos, 0) end")
	w.line("                local _s = buf:sub(_np, _epos - 1)")
	if st == "string" {
		w.line("                if utf8_len(_s) == nil then error(\"invalid UTF-8 in string field at offset \" .. pos, 0) end")
	}
	w.line("                %s = %s + 1; list[%s] = _s", cnt, cnt, cnt)
	w.line("                pos = _epos")
	w.line("            else")
	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)
	w.line("            end")
}

// ----------------------------------------------------------------------------
// Map field codegen
// ----------------------------------------------------------------------------

// emitInlineEncodeMap emits the encode block for a map<K,V> field. Map fields
// are wire-equivalent to `repeated <Field>Entry`, where the synthetic Entry
// message has key=field 1 and value=field 2.
func emitInlineEncodeMap(w *writer, f *protogen.Field, tag string, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	keyF, valF := f.Message.Fields[0], f.Message.Fields[1]

	keyTag := tagBytesLit(1, mapSubFieldWireType(keyF))
	valTag := tagBytesLit(2, mapSubFieldWireType(valF))

	w.line("    if v ~= nil and next(v) ~= nil then")
	w.line("        local _tag, _ktag, _vtag = %s, %s, %s", tag, keyTag, valTag)
	w.line("        for _k, _val in pairs(v) do")
	w.line("            local entry, _m = {}, 0")

	// Key emit
	keyDef := mapKeyDefaultExpr(keyF)
	w.line("            if _k ~= %s then", keyDef)
	emitMapPiece(w, "entry", "_m", "_ktag", "_k", keyF, file, selfPath, imports, prefix)
	w.line("            end")

	// Value emit
	emitMapValueGuard(w, valF, "_val")
	emitMapPiece(w, "entry", "_m", "_vtag", "_val", valF, file, selfPath, imports, prefix)
	w.line("            end")

	w.line("            n = n + 1; out[n] = _tag")
	w.line("            local _b = table.concat(entry)")
	emitInlineLenPrefix(w, "            ", "_b")
	w.line("            n = n + 1; out[n] = _b")
	w.line("        end")
	w.line("    end")
}

// emitMapPiece emits the two-line append:
//
//	<list>[<idx> + 1] = <tag>; <list>[<idx> + 2] = wire.encode_<typed>(<expr>)
//
// (or the message form). Increments <idx> by 2 in two separate statements.
func emitMapPiece(w *writer, list, idx, tag, valExpr string, f *protogen.Field, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	switch {
	case f.Message != nil:
		ref := typeRef(file, f.Message.Desc, selfPath, imports, "_encode", prefix)
		w.line("                %s = %s + 1; %s[%s] = %s",
			idx, idx, list, idx, tag)
		w.line("                %s = %s + 1; %s[%s] = wire.encode_len(%s(%s))",
			idx, idx, list, idx, ref, valExpr)
	case f.Enum != nil:
		// For enum value: input may be string name; resolve.
		enumLocal := typeRef(file, f.Enum.Desc, selfPath, imports, "", prefix)
		fullName := string(f.Enum.Desc.FullName())
		w.line("                local _nv = %s", valExpr)
		w.line("                if type(%s) == 'string' then", valExpr)
		w.line("                    _nv = %s[%s]", enumLocal, valExpr)
		w.line("                    if _nv == nil then error(\"unknown enum value '\" .. %s .. \"' for %s\", 0) end",
			valExpr, fullName)
		w.line("                end")
		w.line("                %s = %s + 1; %s[%s] = %s", idx, idx, list, idx, tag)
		w.line("                %s = %s + 1; %s[%s] = wire.encode_int32(_nv)", idx, idx, list, idx)
	default:
		st := scalarName(f.Desc.Kind())
		w.line("                %s = %s + 1; %s[%s] = %s", idx, idx, list, idx, tag)
		w.line("                %s = %s + 1; %s[%s] = wire.encode_%s(%s)",
			idx, idx, list, idx, st, valExpr)
	}
}

// emitMapValueGuard emits an `if <not-default> then` guarding the value emit
// for default-elision in map entries. Closing `end` is the caller's job.
func emitMapValueGuard(w *writer, f *protogen.Field, valExpr string) {
	switch {
	case f.Message != nil:
		// Messages have no notion of "default value" elision in this position;
		// emit unconditionally (nil is excluded by the outer iteration anyway).
		w.line("            if %s ~= nil then", valExpr)
	case f.Enum != nil:
		// Need to resolve string -> int first, but we delay that. The cheap
		// guard here is only for default elision, so check `~= 0` once it's
		// been resolved. To keep things simple, always emit and let the proto
		// receiver re-resolve to default. (Defaults round-trip correctly.)
		w.line("            do")
	default:
		st := scalarName(f.Desc.Kind())
		w.line("            if %s then", scalarNotDefaultExpr(st, valExpr))
	}
}

// mapKeyDefaultExpr returns the Lua literal for the proto3 default of a map key.
// Only string + integer + bool keys are valid in maps.
func mapKeyDefaultExpr(f *protogen.Field) string {
	switch f.Desc.Kind() {
	case protoreflect.StringKind:
		return "''"
	case protoreflect.BoolKind:
		return "false"
	}
	return "0"
}

// mapSubFieldWireType returns the wire type for a map entry's key or value
// (both are singular and never packed).
func mapSubFieldWireType(f *protogen.Field) int {
	switch {
	case f.Message != nil:
		return 2 // LEN
	case f.Enum != nil:
		return 0 // VARINT
	}
	switch f.Desc.Kind() {
	case protoreflect.Int32Kind, protoreflect.Int64Kind,
		protoreflect.Uint32Kind, protoreflect.Uint64Kind,
		protoreflect.Sint32Kind, protoreflect.Sint64Kind,
		protoreflect.BoolKind:
		return 0 // VARINT
	case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind, protoreflect.FloatKind:
		return 5 // I32
	case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind, protoreflect.DoubleKind:
		return 1 // I64
	case protoreflect.StringKind, protoreflect.BytesKind:
		return 2 // LEN
	}
	panic("unhandled map sub-field kind: " + f.Desc.Kind().String())
}

// emitInlineDecodeMap emits the decode block for a map<K,V> field.
func emitInlineDecodeMap(w *writer, f *protogen.Field, fname string, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	keyF, valF := f.Message.Fields[0], f.Message.Fields[1]

	dst := luaFieldAccess("result", fname)
	w.line("            local map = %s", dst)
	w.line("            if map == nil then map = {}; %s = map end", dst)
	w.line("            local payload")
	w.line("            payload, pos = wire.decode_len(buf, pos)")
	w.line("            local _ep, _elim = 1, #payload")
	w.line("            local _key, _val = %s, %s",
		mapDefaultExpr(keyF), mapDefaultExpr(valF))
	w.line("            while _ep <= _elim do")
	w.line("                local eid, ewt")
	w.line("                eid, ewt, _ep = wire.decode_tag(payload, _ep)")
	w.line("                if eid == 1 then")
	emitMapDecode(w, "_key", keyF, file, selfPath, imports, prefix)
	w.line("                elseif eid == 2 then")
	emitMapDecode(w, "_val", valF, file, selfPath, imports, prefix)
	w.line("                else")
	w.line("                    _ep = wire.skip_field(payload, _ep, ewt, eid)")
	w.line("                end")
	w.line("            end")
	if mapKeyNeedsCdataDedup(keyF) {
		// 64-bit int keys are LuaJIT cdata; LuaJIT hashes cdata by pointer,
		// so duplicate-key wire entries land in different hash buckets even
		// though __eq matches. Walk once to find a canonical key and
		// preserve proto3 "last value wins" semantics. Only emitted for
		// cdata-yielding key types so string/int32-keyed maps stay on the
		// JIT trace.
		w.line("            for _k in pairs(map) do")
		w.line("                if _k == _key then _key = _k; break end")
		w.line("            end")
	}
	w.line("            map[_key] = _val")
}

// mapKeyNeedsCdataDedup reports whether a map key type yields LuaJIT
// cdata and therefore needs pointer-vs-value dedup on decode. Mirrors the
// runtime gate set up in pb.finalize_message.
func mapKeyNeedsCdataDedup(keyF *protogen.Field) bool {
	switch keyF.Desc.Kind() {
	case protoreflect.Int64Kind, protoreflect.Uint64Kind,
		protoreflect.Sint64Kind, protoreflect.Fixed64Kind,
		protoreflect.Sfixed64Kind:
		return true
	}
	return false
}

// mapDefaultExpr returns the Lua expression for a map sub-field's default.
func mapDefaultExpr(f *protogen.Field) string {
	switch {
	case f.Message != nil:
		return "{}"
	case f.Enum != nil:
		return "0"
	}
	switch f.Desc.Kind() {
	case protoreflect.StringKind, protoreflect.BytesKind:
		return "''"
	case protoreflect.BoolKind:
		return "false"
	}
	return "0"
}

// emitMapDecode emits the per-sub-field decode body inside the map entry's
// while-loop. Stores into <dst>; advances _ep.
func emitMapDecode(w *writer, dst string, f *protogen.Field, file *protogen.File, selfPath string, imports map[string]string, prefix string) {
	switch {
	case f.Message != nil:
		ref := typeRef(file, f.Message.Desc, selfPath, imports, "_decode", prefix)
		w.line("                    local _payload")
		w.line("                    _payload, _ep = wire.decode_len(payload, _ep)")
		w.line("                    %s = %s(_payload)", dst, ref)
	case f.Enum != nil:
		w.line("                    local _u")
		w.line("                    _u, _ep = wire.decode_varint(payload, _ep)")
		w.line("                    %s = wire.varint_to_int32(_u)", dst)
	default:
		st := scalarName(f.Desc.Kind())
		w.line("                    %s, _ep = wire.decode_%s(payload, _ep)", dst, st)
	}
}

// ----------------------------------------------------------------------------
// Helpers
// ----------------------------------------------------------------------------

// wireTypeForField returns the proto wire type used to encode this field.
//
// For repeated packable fields with packed=true (proto3 default for primitive
// scalars and enums), the *element* tag is LEN — caller still calls this with
// care. We return the singular-element wire type and let the emit logic decide
// when to swap it to LEN for packed encoding.
func wireTypeForField(f *protogen.Field) int {
	switch {
	case f.Message != nil:
		// Proto2 groups: the *opening* tag carries SGROUP (3). The
		// closing tag is emitted separately as EGROUP (4) at the end of
		// the field body.
		if f.Desc.Kind() == protoreflect.GroupKind {
			return 3 // SGROUP
		}
		return 2 // LEN
	case f.Enum != nil:
		// Repeated packed enums use LEN tag; non-packed elements use VARINT.
		if f.Desc.IsList() && f.Desc.IsPacked() {
			return 2
		}
		return 0 // VARINT
	}
	switch f.Desc.Kind() {
	case protoreflect.Int32Kind, protoreflect.Int64Kind,
		protoreflect.Uint32Kind, protoreflect.Uint64Kind,
		protoreflect.Sint32Kind, protoreflect.Sint64Kind,
		protoreflect.BoolKind:
		// Repeated packed primitives use LEN tag.
		if f.Desc.IsList() && f.Desc.IsPacked() {
			return 2
		}
		return 0 // VARINT
	case protoreflect.Fixed32Kind, protoreflect.Sfixed32Kind, protoreflect.FloatKind:
		if f.Desc.IsList() && f.Desc.IsPacked() {
			return 2
		}
		return 5 // I32
	case protoreflect.Fixed64Kind, protoreflect.Sfixed64Kind, protoreflect.DoubleKind:
		if f.Desc.IsList() && f.Desc.IsPacked() {
			return 2
		}
		return 1 // I64
	case protoreflect.StringKind, protoreflect.BytesKind:
		return 2 // LEN (never packable)
	}
	panic("unhandled kind: " + f.Desc.Kind().String())
}

// tagBytesLit returns a Lua string literal (e.g. "\"\\x0a\"") encoding the
// varint for tag = (id << 3) | wireType. Tags are 1 byte for ids ≤ 15 with
// VARINT/I32/I64, 1 byte for ids ≤ 31 with LEN, 2 bytes for ids ≤ 2047,
// and so on.
func tagBytesLit(id int32, wireType int) string {
	tag := uint64(id)*8 + uint64(wireType)
	var b []byte
	for tag >= 128 {
		b = append(b, byte(tag&0x7f)|0x80)
		tag >>= 7
	}
	b = append(b, byte(tag))
	return luaByteString(b)
}

func luaByteString(b []byte) string {
	var sb strings.Builder
	sb.WriteByte('"')
	for _, c := range b {
		sb.WriteString(fmt.Sprintf("\\x%02x", c))
	}
	sb.WriteByte('"')
	return sb.String()
}

// scalarNotDefaultExpr returns a Lua expression that evaluates true when
// the value `v` is NOT the proto3 default for the given scalar type.
// Default is elided on encode.
//
// Floats and doubles need a sign-bit guard: -0.0 == 0.0 in IEEE, but
// they aren't the proto3 default (the wire bytes differ, and the
// TextFormatInput conformance corpus pins this). `1/v == -math.huge`
// is the standard sign-bit probe — division by +0 yields +inf, by -0
// yields -inf, and any non-zero value short-circuits via `v ~= 0`.
func scalarNotDefaultExpr(scalar, v string) string {
	switch scalar {
	case "string", "bytes":
		return v + ` ~= ''`
	case "bool":
		return v + ` ~= false`
	case "float", "double":
		return "(" + v + ` ~= 0 or 1/` + v + " == -math.huge)"
	}
	return v + ` ~= 0`
}