1// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package main
6
7import (
8	"text/template"
9)
10
11func generateImplCodec() string {
12	return mustExecute(implCodecTemplate, ProtoKinds)
13}
14
15var implCodecTemplate = template.Must(template.New("").Parse(`
16{{- /*
17  IsZero is an expression testing if 'v' is the zero value.
18*/ -}}
19{{- define "IsZero" -}}
20{{if eq .WireType "Bytes" -}}
21len(v) == 0
22{{- else if or (eq .Name "Double") (eq .Name "Float") -}}
23v == 0 && !math.Signbit(float64(v))
24{{- else -}}
25v == {{.GoType.Zero}}
26{{- end -}}
27{{- end -}}
28
29{{- /*
30  Size is an expression computing the size of 'v'.
31*/ -}}
32{{- define "Size" -}}
33{{- if .WireType.ConstSize -}}
34protowire.Size{{.WireType}}()
35{{- else if eq .WireType "Bytes" -}}
36protowire.SizeBytes(len({{.FromGoType}}))
37{{- else -}}
38protowire.Size{{.WireType}}({{.FromGoType}})
39{{- end -}}
40{{- end -}}
41
42{{- define "SizeValue" -}}
43{{- if .WireType.ConstSize -}}
44protowire.Size{{.WireType}}()
45{{- else if eq .WireType "Bytes" -}}
46protowire.SizeBytes(len({{.FromValue}}))
47{{- else -}}
48protowire.Size{{.WireType}}({{.FromValue}})
49{{- end -}}
50{{- end -}}
51
52{{- /*
53  Append is a set of statements appending 'v' to 'b'.
54*/ -}}
55{{- define "Append" -}}
56{{- if eq .Name "String" -}}
57b = protowire.AppendString(b, {{.FromGoType}})
58{{- else -}}
59b = protowire.Append{{.WireType}}(b, {{.FromGoType}})
60{{- end -}}
61{{- end -}}
62
63{{- define "AppendValue" -}}
64{{- if eq .Name "String" -}}
65b = protowire.AppendString(b, {{.FromValue}})
66{{- else -}}
67b = protowire.Append{{.WireType}}(b, {{.FromValue}})
68{{- end -}}
69{{- end -}}
70
71{{- define "Consume" -}}
72{{- if eq .WireType "Varint" -}}
73var v uint64
74var n int
75if len(b) >= 1 && b[0] < 0x80 {
76	v = uint64(b[0])
77	n = 1
78} else if len(b) >= 2 && b[1] < 128 {
79	v = uint64(b[0]&0x7f) + uint64(b[1])<<7
80	n = 2
81} else {
82	v, n = protowire.ConsumeVarint(b)
83}
84{{- else -}}
85v, n := protowire.Consume{{.WireType}}(b)
86{{- end -}}
87{{- end -}}
88
89{{- range .}}
90
91{{- if .FromGoType }}
92// size{{.Name}} returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}.
93func size{{.Name}}(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
94	{{if not .WireType.ConstSize -}}
95	v := *p.{{.GoType.PointerMethod}}()
96	{{- end}}
97	return f.tagsize + {{template "Size" .}}
98}
99
100// append{{.Name}} wire encodes a {{.GoType}} pointer as a {{.Name}}.
101func append{{.Name}}(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
102	v := *p.{{.GoType.PointerMethod}}()
103	b = protowire.AppendVarint(b, f.wiretag)
104	{{template "Append" .}}
105	return b, nil
106}
107
108// consume{{.Name}} wire decodes a {{.GoType}} pointer as a {{.Name}}.
109func consume{{.Name}}(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
110	if wtyp != {{.WireType.Expr}} {
111		return out, errUnknown
112	}
113	{{template "Consume" .}}
114	if n < 0 {
115		return out, errDecode
116	}
117	*p.{{.GoType.PointerMethod}}() = {{.ToGoType}}
118	out.n = n
119	return out, nil
120}
121
122var coder{{.Name}} = pointerCoderFuncs{
123	size:      size{{.Name}},
124	marshal:   append{{.Name}},
125	unmarshal: consume{{.Name}},
126	merge:     merge{{.GoType.PointerMethod}},
127}
128
129{{if or (eq .Name "Bytes") (eq .Name "String")}}
130// append{{.Name}}ValidateUTF8 wire encodes a {{.GoType}} pointer as a {{.Name}}.
131func append{{.Name}}ValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
132	v := *p.{{.GoType.PointerMethod}}()
133	b = protowire.AppendVarint(b, f.wiretag)
134	{{template "Append" .}}
135	if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
136		return b, errInvalidUTF8{}
137	}
138	return b, nil
139}
140
141// consume{{.Name}}ValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}.
142func consume{{.Name}}ValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
143	if wtyp != {{.WireType.Expr}} {
144		return out, errUnknown
145	}
146	{{template "Consume" .}}
147	if n < 0 {
148		return out, errDecode
149	}
150	if !utf8.Valid(v) {
151		return out, errInvalidUTF8{}
152	}
153	*p.{{.GoType.PointerMethod}}() = {{.ToGoType}}
154	out.n = n
155	return out, nil
156}
157
158var coder{{.Name}}ValidateUTF8 = pointerCoderFuncs{
159	size:      size{{.Name}},
160	marshal:   append{{.Name}}ValidateUTF8,
161	unmarshal: consume{{.Name}}ValidateUTF8,
162	merge:     merge{{.GoType.PointerMethod}},
163}
164{{end}}
165
166// size{{.Name}}NoZero returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}.
167// The zero value is not encoded.
168func size{{.Name}}NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
169	v := *p.{{.GoType.PointerMethod}}()
170	if {{template "IsZero" .}} {
171		return 0
172	}
173	return f.tagsize + {{template "Size" .}}
174}
175
176// append{{.Name}}NoZero wire encodes a {{.GoType}} pointer as a {{.Name}}.
177// The zero value is not encoded.
178func append{{.Name}}NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
179	v := *p.{{.GoType.PointerMethod}}()
180	if {{template "IsZero" .}} {
181		return b, nil
182	}
183	b = protowire.AppendVarint(b, f.wiretag)
184	{{template "Append" .}}
185	return b, nil
186}
187
188{{if .ToGoTypeNoZero}}
189// consume{{.Name}}NoZero wire decodes a {{.GoType}} pointer as a {{.Name}}.
190// The zero value is not decoded.
191func consume{{.Name}}NoZero(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
192	if wtyp != {{.WireType.Expr}} {
193		return out, errUnknown
194	}
195	{{template "Consume" .}}
196	if n < 0 {
197		return out, errDecode
198	}
199	*p.{{.GoType.PointerMethod}}() = {{.ToGoTypeNoZero}}
200	out.n = n
201	return out, nil
202}
203{{end}}
204
205var coder{{.Name}}NoZero = pointerCoderFuncs{
206	size:      size{{.Name}}NoZero,
207	marshal:   append{{.Name}}NoZero,
208	unmarshal: consume{{.Name}}{{if .ToGoTypeNoZero}}NoZero{{end}},
209	merge:     merge{{.GoType.PointerMethod}}NoZero,
210}
211
212{{if or (eq .Name "Bytes") (eq .Name "String")}}
213// append{{.Name}}NoZeroValidateUTF8 wire encodes a {{.GoType}} pointer as a {{.Name}}.
214// The zero value is not encoded.
215func append{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
216	v := *p.{{.GoType.PointerMethod}}()
217	if {{template "IsZero" .}} {
218		return b, nil
219	}
220	b = protowire.AppendVarint(b, f.wiretag)
221	{{template "Append" .}}
222	if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
223		return b, errInvalidUTF8{}
224	}
225	return b, nil
226}
227
228{{if .ToGoTypeNoZero}}
229// consume{{.Name}}NoZeroValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}.
230func consume{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
231	if wtyp != {{.WireType.Expr}} {
232		return out, errUnknown
233	}
234	{{template "Consume" .}}
235	if n < 0 {
236		return out, errDecode
237	}
238	if !utf8.Valid(v) {
239		return out, errInvalidUTF8{}
240	}
241	*p.{{.GoType.PointerMethod}}() = {{.ToGoTypeNoZero}}
242	out.n = n
243	return out, nil
244}
245{{end}}
246
247var coder{{.Name}}NoZeroValidateUTF8 = pointerCoderFuncs{
248	size:      size{{.Name}}NoZero,
249	marshal:   append{{.Name}}NoZeroValidateUTF8,
250	unmarshal: consume{{.Name}}{{if .ToGoTypeNoZero}}NoZero{{end}}ValidateUTF8,
251	merge:     merge{{.GoType.PointerMethod}}NoZero,
252}
253{{end}}
254
255{{- if not .NoPointer}}
256// size{{.Name}}Ptr returns the size of wire encoding a *{{.GoType}} pointer as a {{.Name}}.
257// It panics if the pointer is nil.
258func size{{.Name}}Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
259	{{if not .WireType.ConstSize -}}
260	v := **p.{{.GoType.PointerMethod}}Ptr()
261	{{end -}}
262	return f.tagsize + {{template "Size" .}}
263}
264
265// append{{.Name}}Ptr wire encodes a *{{.GoType}} pointer as a {{.Name}}.
266// It panics if the pointer is nil.
267func append{{.Name}}Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
268	v := **p.{{.GoType.PointerMethod}}Ptr()
269	b = protowire.AppendVarint(b, f.wiretag)
270	{{template "Append" .}}
271	return b, nil
272}
273
274// consume{{.Name}}Ptr wire decodes a *{{.GoType}} pointer as a {{.Name}}.
275func consume{{.Name}}Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
276	if wtyp != {{.WireType.Expr}} {
277		return out, errUnknown
278	}
279	{{template "Consume" .}}
280	if n < 0 {
281		return out, errDecode
282	}
283	vp := p.{{.GoType.PointerMethod}}Ptr()
284	if *vp == nil {
285		*vp = new({{.GoType}})
286	}
287	**vp = {{.ToGoType}}
288	out.n = n
289	return out, nil
290}
291
292var coder{{.Name}}Ptr = pointerCoderFuncs{
293	size:      size{{.Name}}Ptr,
294	marshal:   append{{.Name}}Ptr,
295	unmarshal: consume{{.Name}}Ptr,
296	merge:     merge{{.GoType.PointerMethod}}Ptr,
297}
298{{end}}
299
300{{if (eq .Name "String")}}
301// append{{.Name}}PtrValidateUTF8 wire encodes a *{{.GoType}} pointer as a {{.Name}}.
302// It panics if the pointer is nil.
303func append{{.Name}}PtrValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
304	v := **p.{{.GoType.PointerMethod}}Ptr()
305	b = protowire.AppendVarint(b, f.wiretag)
306	{{template "Append" .}}
307	if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
308		return b, errInvalidUTF8{}
309	}
310	return b, nil
311}
312
313// consume{{.Name}}PtrValidateUTF8 wire decodes a *{{.GoType}} pointer as a {{.Name}}.
314func consume{{.Name}}PtrValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
315	if wtyp != {{.WireType.Expr}} {
316		return out, errUnknown
317	}
318	{{template "Consume" .}}
319	if n < 0 {
320		return out, errDecode
321	}
322	if !utf8.Valid(v) {
323		return out, errInvalidUTF8{}
324	}
325	vp := p.{{.GoType.PointerMethod}}Ptr()
326	if *vp == nil {
327		*vp = new({{.GoType}})
328	}
329	**vp = {{.ToGoType}}
330	out.n = n
331	return out, nil
332}
333
334var coder{{.Name}}PtrValidateUTF8 = pointerCoderFuncs{
335	size:      size{{.Name}}Ptr,
336	marshal:   append{{.Name}}PtrValidateUTF8,
337	unmarshal: consume{{.Name}}PtrValidateUTF8,
338	merge:     merge{{.GoType.PointerMethod}}Ptr,
339}
340{{end}}
341
342// size{{.Name}}Slice returns the size of wire encoding a []{{.GoType}} pointer as a repeated {{.Name}}.
343func size{{.Name}}Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
344	s := *p.{{.GoType.PointerMethod}}Slice()
345	{{if .WireType.ConstSize -}}
346	size = len(s) * (f.tagsize + {{template "Size" .}})
347	{{- else -}}
348	for _, v := range s {
349		size += f.tagsize + {{template "Size" .}}
350	}
351	{{- end}}
352	return size
353}
354
355// append{{.Name}}Slice encodes a []{{.GoType}} pointer as a repeated {{.Name}}.
356func append{{.Name}}Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
357	s := *p.{{.GoType.PointerMethod}}Slice()
358	for _, v := range s {
359		b = protowire.AppendVarint(b, f.wiretag)
360		{{template "Append" .}}
361	}
362	return b, nil
363}
364
365// consume{{.Name}}Slice wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}.
366func consume{{.Name}}Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
367	sp := p.{{.GoType.PointerMethod}}Slice()
368	{{- if .WireType.Packable}}
369	if wtyp == protowire.BytesType {
370		s := *sp
371		b, n := protowire.ConsumeBytes(b)
372		if n < 0 {
373			return out, errDecode
374		}
375		for len(b) > 0 {
376			{{template "Consume" .}}
377			if n < 0 {
378				return out, errDecode
379			}
380			s = append(s, {{.ToGoType}})
381			b = b[n:]
382		}
383		*sp = s
384		out.n = n
385		return out, nil
386	}
387	{{- end}}
388	if wtyp != {{.WireType.Expr}} {
389		return out, errUnknown
390	}
391	{{template "Consume" .}}
392	if n < 0 {
393		return out, errDecode
394	}
395	*sp = append(*sp, {{.ToGoType}})
396	out.n = n
397	return out, nil
398}
399
400var coder{{.Name}}Slice = pointerCoderFuncs{
401	size:      size{{.Name}}Slice,
402	marshal:   append{{.Name}}Slice,
403	unmarshal: consume{{.Name}}Slice,
404	merge:     merge{{.GoType.PointerMethod}}Slice,
405}
406
407{{if or (eq .Name "Bytes") (eq .Name "String")}}
408// append{{.Name}}SliceValidateUTF8 encodes a []{{.GoType}} pointer as a repeated {{.Name}}.
409func append{{.Name}}SliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
410	s := *p.{{.GoType.PointerMethod}}Slice()
411	for _, v := range s {
412		b = protowire.AppendVarint(b, f.wiretag)
413		{{template "Append" .}}
414		if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
415			return b, errInvalidUTF8{}
416		}
417	}
418	return b, nil
419}
420
421// consume{{.Name}}SliceValidateUTF8 wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}.
422func consume{{.Name}}SliceValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
423	if wtyp != {{.WireType.Expr}} {
424		return out, errUnknown
425	}
426	{{template "Consume" .}}
427	if n < 0 {
428		return out, errDecode
429	}
430	if !utf8.Valid(v) {
431		return out, errInvalidUTF8{}
432	}
433	sp := p.{{.GoType.PointerMethod}}Slice()
434	*sp = append(*sp, {{.ToGoType}})
435	out.n = n
436	return out, nil
437}
438
439var coder{{.Name}}SliceValidateUTF8 = pointerCoderFuncs{
440	size:      size{{.Name}}Slice,
441	marshal:   append{{.Name}}SliceValidateUTF8,
442	unmarshal: consume{{.Name}}SliceValidateUTF8,
443	merge:     merge{{.GoType.PointerMethod}}Slice,
444}
445{{end}}
446
447{{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}}
448// size{{.Name}}PackedSlice returns the size of wire encoding a []{{.GoType}} pointer as a packed repeated {{.Name}}.
449func size{{.Name}}PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
450	s := *p.{{.GoType.PointerMethod}}Slice()
451	if len(s) == 0 {
452		return 0
453	}
454	{{if .WireType.ConstSize -}}
455	n := len(s) * {{template "Size" .}}
456	{{- else -}}
457	n := 0
458	for _, v := range s {
459		n += {{template "Size" .}}
460	}
461	{{- end}}
462	return f.tagsize + protowire.SizeBytes(n)
463}
464
465// append{{.Name}}PackedSlice encodes a []{{.GoType}} pointer as a packed repeated {{.Name}}.
466func append{{.Name}}PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
467	s := *p.{{.GoType.PointerMethod}}Slice()
468	if len(s) == 0 {
469		return b, nil
470	}
471	b = protowire.AppendVarint(b, f.wiretag)
472	{{if .WireType.ConstSize -}}
473	n := len(s) * {{template "Size" .}}
474	{{- else -}}
475	n := 0
476	for _, v := range s {
477		n += {{template "Size" .}}
478	}
479	{{- end}}
480	b = protowire.AppendVarint(b, uint64(n))
481	for _, v := range s {
482		{{template "Append" .}}
483	}
484	return b, nil
485}
486
487var coder{{.Name}}PackedSlice = pointerCoderFuncs{
488	size:      size{{.Name}}PackedSlice,
489	marshal:   append{{.Name}}PackedSlice,
490	unmarshal: consume{{.Name}}Slice,
491	merge:     merge{{.GoType.PointerMethod}}Slice,
492}
493{{end}}
494
495{{end -}}
496
497{{- if not .NoValueCodec}}
498// size{{.Name}}Value returns the size of wire encoding a {{.GoType}} value as a {{.Name}}.
499func size{{.Name}}Value(v protoreflect.Value, tagsize int, opts marshalOptions) int {
500	return tagsize + {{template "SizeValue" .}}
501}
502
503// append{{.Name}}Value encodes a {{.GoType}} value as a {{.Name}}.
504func append{{.Name}}Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
505	b = protowire.AppendVarint(b, wiretag)
506	{{template "AppendValue" .}}
507	return b, nil
508}
509
510// consume{{.Name}}Value decodes a {{.GoType}} value as a {{.Name}}.
511func consume{{.Name}}Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
512	if wtyp != {{.WireType.Expr}} {
513		return protoreflect.Value{}, out, errUnknown
514	}
515	{{template "Consume" .}}
516	if n < 0 {
517		return protoreflect.Value{}, out, errDecode
518	}
519	out.n = n
520	return {{.ToValue}}, out, nil
521}
522
523var coder{{.Name}}Value = valueCoderFuncs{
524	size:      size{{.Name}}Value,
525	marshal:   append{{.Name}}Value,
526	unmarshal: consume{{.Name}}Value,
527{{- if (eq .Name "Bytes")}}
528	merge:     mergeBytesValue,
529{{- else}}
530	merge:     mergeScalarValue,
531{{- end}}
532}
533
534{{if (eq .Name "String")}}
535// append{{.Name}}ValueValidateUTF8 encodes a {{.GoType}} value as a {{.Name}}.
536func append{{.Name}}ValueValidateUTF8(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
537	b = protowire.AppendVarint(b, wiretag)
538	{{template "AppendValue" .}}
539	if !utf8.ValidString({{.FromValue}}) {
540		return b, errInvalidUTF8{}
541	}
542	return b, nil
543}
544
545// consume{{.Name}}ValueValidateUTF8 decodes a {{.GoType}} value as a {{.Name}}.
546func consume{{.Name}}ValueValidateUTF8(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
547	if wtyp != {{.WireType.Expr}} {
548		return protoreflect.Value{}, out, errUnknown
549	}
550	{{template "Consume" .}}
551	if n < 0 {
552		return protoreflect.Value{}, out, errDecode
553	}
554	if !utf8.Valid(v) {
555		return protoreflect.Value{}, out, errInvalidUTF8{}
556	}
557	out.n = n
558	return {{.ToValue}}, out, nil
559}
560
561var coder{{.Name}}ValueValidateUTF8 = valueCoderFuncs{
562	size:      size{{.Name}}Value,
563	marshal:   append{{.Name}}ValueValidateUTF8,
564	unmarshal: consume{{.Name}}ValueValidateUTF8,
565	merge:     mergeScalarValue,
566}
567{{end}}
568
569// size{{.Name}}SliceValue returns the size of wire encoding a []{{.GoType}} value as a repeated {{.Name}}.
570func size{{.Name}}SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) {
571	list := listv.List()
572	{{if .WireType.ConstSize -}}
573	size = list.Len() * (tagsize + {{template "SizeValue" .}})
574	{{- else -}}
575	for i, llen := 0, list.Len(); i < llen; i++ {
576		v := list.Get(i)
577		size += tagsize + {{template "SizeValue" .}}
578	}
579	{{- end}}
580	return size
581}
582
583// append{{.Name}}SliceValue encodes a []{{.GoType}} value as a repeated {{.Name}}.
584func append{{.Name}}SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
585	list := listv.List()
586	for i, llen := 0, list.Len(); i < llen; i++ {
587		v := list.Get(i)
588		b = protowire.AppendVarint(b, wiretag)
589		{{template "AppendValue" .}}
590	}
591	return b, nil
592}
593
594// consume{{.Name}}SliceValue wire decodes a []{{.GoType}} value as a repeated {{.Name}}.
595func consume{{.Name}}SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
596	list := listv.List()
597	{{- if .WireType.Packable}}
598	if wtyp == protowire.BytesType {
599		b, n := protowire.ConsumeBytes(b)
600		if n < 0 {
601			return protoreflect.Value{}, out, errDecode
602		}
603		for len(b) > 0 {
604			{{template "Consume" .}}
605			if n < 0 {
606				return protoreflect.Value{}, out, errDecode
607			}
608			list.Append({{.ToValue}})
609			b = b[n:]
610		}
611		out.n = n
612		return listv, out, nil
613	}
614	{{- end}}
615	if wtyp != {{.WireType.Expr}} {
616		return protoreflect.Value{}, out, errUnknown
617	}
618	{{template "Consume" .}}
619	if n < 0 {
620		return protoreflect.Value{}, out, errDecode
621	}
622	list.Append({{.ToValue}})
623	out.n = n
624	return listv, out, nil
625}
626
627var coder{{.Name}}SliceValue = valueCoderFuncs{
628	size:      size{{.Name}}SliceValue,
629	marshal:   append{{.Name}}SliceValue,
630	unmarshal: consume{{.Name}}SliceValue,
631{{- if (eq .Name "Bytes")}}
632	merge:     mergeBytesListValue,
633{{- else}}
634	merge:     mergeListValue,
635{{- end}}
636}
637
638{{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}}
639// size{{.Name}}PackedSliceValue returns the size of wire encoding a []{{.GoType}} value as a packed repeated {{.Name}}.
640func size{{.Name}}PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) {
641	list := listv.List()
642	llen := list.Len()
643	if llen == 0 {
644		return 0
645	}
646	{{if .WireType.ConstSize -}}
647	n := llen * {{template "SizeValue" .}}
648	{{- else -}}
649	n := 0
650	for i, llen := 0, llen; i < llen; i++ {
651		v := list.Get(i)
652		n += {{template "SizeValue" .}}
653	}
654	{{- end}}
655	return tagsize + protowire.SizeBytes(n)
656}
657
658// append{{.Name}}PackedSliceValue encodes a []{{.GoType}} value as a packed repeated {{.Name}}.
659func append{{.Name}}PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
660	list := listv.List()
661	llen := list.Len()
662	if llen == 0 {
663		return b, nil
664	}
665	b = protowire.AppendVarint(b, wiretag)
666	{{if .WireType.ConstSize -}}
667	n := llen * {{template "SizeValue" .}}
668	{{- else -}}
669	n := 0
670	for i := 0; i < llen; i++ {
671		v := list.Get(i)
672		n += {{template "SizeValue" .}}
673	}
674	{{- end}}
675	b = protowire.AppendVarint(b, uint64(n))
676	for i := 0; i < llen; i++ {
677		v := list.Get(i)
678		{{template "AppendValue" .}}
679	}
680	return b, nil
681}
682
683var coder{{.Name}}PackedSliceValue = valueCoderFuncs{
684	size:      size{{.Name}}PackedSliceValue,
685	marshal:   append{{.Name}}PackedSliceValue,
686	unmarshal: consume{{.Name}}SliceValue,
687	merge:     mergeListValue,
688}
689{{end}}
690
691{{- end}}{{/* if not .NoValueCodec */}}
692
693{{end -}}
694
695// We append to an empty array rather than a nil []byte to get non-nil zero-length byte slices.
696var emptyBuf [0]byte
697
698var wireTypes = map[protoreflect.Kind]protowire.Type{
699{{range . -}}
700	protoreflect.{{.Name}}Kind: {{.WireType.Expr}},
701{{end}}
702}
703`))
704
705func generateImplMessage() string {
706	return mustExecute(implMessageTemplate, []string{"messageState", "messageReflectWrapper"})
707}
708
709var implMessageTemplate = template.Must(template.New("").Parse(`
710{{range . -}}
711func (m *{{.}}) Descriptor() protoreflect.MessageDescriptor {
712	return m.messageInfo().Desc
713}
714func (m *{{.}}) Type() protoreflect.MessageType {
715	return m.messageInfo()
716}
717func (m *{{.}}) New() protoreflect.Message {
718	return m.messageInfo().New()
719}
720func (m *{{.}}) Interface() protoreflect.ProtoMessage {
721	{{if eq . "messageState" -}}
722	return m.protoUnwrap().(protoreflect.ProtoMessage)
723	{{- else -}}
724	if m, ok := m.protoUnwrap().(protoreflect.ProtoMessage); ok {
725		return m
726	}
727	return (*messageIfaceWrapper)(m)
728	{{- end -}}
729}
730func (m *{{.}}) protoUnwrap() interface{} {
731	return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem())
732}
733func (m *{{.}}) ProtoMethods() *protoiface.Methods {
734	m.messageInfo().init()
735	return &m.messageInfo().methods
736}
737
738// ProtoMessageInfo is a pseudo-internal API for allowing the v1 code
739// to be able to retrieve a v2 MessageInfo struct.
740//
741// WARNING: This method is exempt from the compatibility promise and
742// may be removed in the future without warning.
743func (m *{{.}}) ProtoMessageInfo() *MessageInfo {
744	return m.messageInfo()
745}
746
747func (m *{{.}}) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
748	m.messageInfo().init()
749	for _, ri := range m.messageInfo().rangeInfos {
750		switch ri := ri.(type) {
751		case *fieldInfo:
752			if ri.has(m.pointer()) {
753				if !f(ri.fieldDesc, ri.get(m.pointer())) {
754					return
755				}
756			}
757		case *oneofInfo:
758			if n := ri.which(m.pointer()); n > 0 {
759				fi := m.messageInfo().fields[n]
760				if !f(fi.fieldDesc, fi.get(m.pointer())) {
761					return
762				}
763			}
764		}
765	}
766	m.messageInfo().extensionMap(m.pointer()).Range(f)
767}
768func (m *{{.}}) Has(fd protoreflect.FieldDescriptor) bool {
769	m.messageInfo().init()
770	if fi, xt := m.messageInfo().checkField(fd); fi != nil {
771		return fi.has(m.pointer())
772	} else {
773		return m.messageInfo().extensionMap(m.pointer()).Has(xt)
774	}
775}
776func (m *{{.}}) Clear(fd protoreflect.FieldDescriptor) {
777	m.messageInfo().init()
778	if fi, xt := m.messageInfo().checkField(fd); fi != nil {
779		fi.clear(m.pointer())
780	} else {
781		m.messageInfo().extensionMap(m.pointer()).Clear(xt)
782	}
783}
784func (m *{{.}}) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
785	m.messageInfo().init()
786	if fi, xt := m.messageInfo().checkField(fd); fi != nil {
787		return fi.get(m.pointer())
788	} else {
789		return m.messageInfo().extensionMap(m.pointer()).Get(xt)
790	}
791}
792func (m *{{.}}) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
793	m.messageInfo().init()
794	if fi, xt := m.messageInfo().checkField(fd); fi != nil {
795		fi.set(m.pointer(), v)
796	} else {
797		m.messageInfo().extensionMap(m.pointer()).Set(xt, v)
798	}
799}
800func (m *{{.}}) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
801	m.messageInfo().init()
802	if fi, xt := m.messageInfo().checkField(fd); fi != nil {
803		return fi.mutable(m.pointer())
804	} else {
805		return m.messageInfo().extensionMap(m.pointer()).Mutable(xt)
806	}
807}
808func (m *{{.}}) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
809	m.messageInfo().init()
810	if fi, xt := m.messageInfo().checkField(fd); fi != nil {
811		return fi.newField()
812	} else {
813		return xt.New()
814	}
815}
816func (m *{{.}}) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
817	m.messageInfo().init()
818	if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
819		return od.Fields().ByNumber(oi.which(m.pointer()))
820	}
821	panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName()))
822}
823func (m *{{.}}) GetUnknown() protoreflect.RawFields {
824	m.messageInfo().init()
825	return m.messageInfo().getUnknown(m.pointer())
826}
827func (m *{{.}}) SetUnknown(b protoreflect.RawFields) {
828	m.messageInfo().init()
829	m.messageInfo().setUnknown(m.pointer(), b)
830}
831func (m *{{.}}) IsValid() bool {
832	return !m.pointer().IsNil()
833}
834
835{{end}}
836`))
837
838func generateImplMerge() string {
839	return mustExecute(implMergeTemplate, GoTypes)
840}
841
842var implMergeTemplate = template.Must(template.New("").Parse(`
843{{range .}}
844{{if ne . "[]byte"}}
845func merge{{.PointerMethod}}(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
846	*dst.{{.PointerMethod}}() = *src.{{.PointerMethod}}()
847}
848
849func merge{{.PointerMethod}}NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
850	v := *src.{{.PointerMethod}}()
851	if v != {{.Zero}} {
852		*dst.{{.PointerMethod}}() = v
853	}
854}
855
856func merge{{.PointerMethod}}Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
857	p := *src.{{.PointerMethod}}Ptr()
858	if p != nil {
859		v := *p
860		*dst.{{.PointerMethod}}Ptr() = &v
861	}
862}
863
864func merge{{.PointerMethod}}Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
865	ds := dst.{{.PointerMethod}}Slice()
866	ss := src.{{.PointerMethod}}Slice()
867	*ds = append(*ds, *ss...)
868}
869
870{{end}}
871{{end}}
872`))
873