blob: 96996f21d49de867dce5fa131ce6093fbe231255 [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"text/template"
)
func generateImplCodec() string {
return mustExecute(implCodecTemplate, ProtoKinds)
}
var implCodecTemplate = template.Must(template.New("").Parse(`
{{- /*
IsZero is an expression testing if 'v' is the zero value.
*/ -}}
{{- define "IsZero" -}}
{{if eq .WireType "Bytes" -}}
len(v) == 0
{{- else if or (eq .Name "Double") (eq .Name "Float") -}}
v == 0 && !math.Signbit(float64(v))
{{- else -}}
v == {{.GoType.Zero}}
{{- end -}}
{{- end -}}
{{- /*
Size is an expression computing the size of 'v'.
*/ -}}
{{- define "Size" -}}
{{- if .WireType.ConstSize -}}
protowire.Size{{.WireType}}()
{{- else if eq .WireType "Bytes" -}}
protowire.SizeBytes(len({{.FromGoType}}))
{{- else -}}
protowire.Size{{.WireType}}({{.FromGoType}})
{{- end -}}
{{- end -}}
{{- define "SizeValue" -}}
{{- if .WireType.ConstSize -}}
protowire.Size{{.WireType}}()
{{- else if eq .WireType "Bytes" -}}
protowire.SizeBytes(len({{.FromValue}}))
{{- else -}}
protowire.Size{{.WireType}}({{.FromValue}})
{{- end -}}
{{- end -}}
{{- /*
Append is a set of statements appending 'v' to 'b'.
*/ -}}
{{- define "Append" -}}
{{- if eq .Name "String" -}}
b = protowire.AppendString(b, {{.FromGoType}})
{{- else -}}
b = protowire.Append{{.WireType}}(b, {{.FromGoType}})
{{- end -}}
{{- end -}}
{{- define "AppendValue" -}}
{{- if eq .Name "String" -}}
b = protowire.AppendString(b, {{.FromValue}})
{{- else -}}
b = protowire.Append{{.WireType}}(b, {{.FromValue}})
{{- end -}}
{{- end -}}
{{- define "Consume" -}}
{{- if eq .Name "String" -}}
v, n := protowire.ConsumeString(b)
{{- else if eq .WireType "Varint" -}}
var v uint64
var n int
if len(b) >= 1 && b[0] < 0x80 {
v = uint64(b[0])
n = 1
} else if len(b) >= 2 && b[1] < 128 {
v = uint64(b[0]&0x7f) + uint64(b[1])<<7
n = 2
} else {
v, n = protowire.ConsumeVarint(b)
}
{{- else -}}
v, n := protowire.Consume{{.WireType}}(b)
{{- end -}}
{{- end -}}
{{- range .}}
{{- if .FromGoType }}
// size{{.Name}} returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}.
func size{{.Name}}(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
{{if not .WireType.ConstSize -}}
v := *p.{{.GoType.PointerMethod}}()
{{- end}}
return f.tagsize + {{template "Size" .}}
}
// append{{.Name}} wire encodes a {{.GoType}} pointer as a {{.Name}}.
func append{{.Name}}(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
return b, nil
}
// consume{{.Name}} wire decodes a {{.GoType}} pointer as a {{.Name}}.
func consume{{.Name}}(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
*p.{{.GoType.PointerMethod}}() = {{.ToGoType}}
out.n = n
return out, nil
}
var coder{{.Name}} = pointerCoderFuncs{
size: size{{.Name}},
marshal: append{{.Name}},
unmarshal: consume{{.Name}},
merge: merge{{.GoType.PointerMethod}},
}
{{if or (eq .Name "Bytes") (eq .Name "String")}}
// append{{.Name}}ValidateUTF8 wire encodes a {{.GoType}} pointer as a {{.Name}}.
func append{{.Name}}ValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return b, errInvalidUTF8{}
}
return b, nil
}
// consume{{.Name}}ValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}.
func consume{{.Name}}ValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return out, errInvalidUTF8{}
}
*p.{{.GoType.PointerMethod}}() = {{.ToGoType}}
out.n = n
return out, nil
}
var coder{{.Name}}ValidateUTF8 = pointerCoderFuncs{
size: size{{.Name}},
marshal: append{{.Name}}ValidateUTF8,
unmarshal: consume{{.Name}}ValidateUTF8,
merge: merge{{.GoType.PointerMethod}},
}
{{end}}
// size{{.Name}}NoZero returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}.
// The zero value is not encoded.
func size{{.Name}}NoZero(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
v := *p.{{.GoType.PointerMethod}}()
if {{template "IsZero" .}} {
return 0
}
return f.tagsize + {{template "Size" .}}
}
// append{{.Name}}NoZero wire encodes a {{.GoType}} pointer as a {{.Name}}.
// The zero value is not encoded.
func append{{.Name}}NoZero(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
if {{template "IsZero" .}} {
return b, nil
}
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
return b, nil
}
{{if .ToGoTypeNoZero}}
// consume{{.Name}}NoZero wire decodes a {{.GoType}} pointer as a {{.Name}}.
// The zero value is not decoded.
func consume{{.Name}}NoZero(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
*p.{{.GoType.PointerMethod}}() = {{.ToGoTypeNoZero}}
out.n = n
return out, nil
}
{{end}}
var coder{{.Name}}NoZero = pointerCoderFuncs{
size: size{{.Name}}NoZero,
marshal: append{{.Name}}NoZero,
unmarshal: consume{{.Name}}{{if .ToGoTypeNoZero}}NoZero{{end}},
merge: merge{{.GoType.PointerMethod}}NoZero,
}
{{if or (eq .Name "Bytes") (eq .Name "String")}}
// append{{.Name}}NoZeroValidateUTF8 wire encodes a {{.GoType}} pointer as a {{.Name}}.
// The zero value is not encoded.
func append{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
if {{template "IsZero" .}} {
return b, nil
}
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return b, errInvalidUTF8{}
}
return b, nil
}
{{if .ToGoTypeNoZero}}
// consume{{.Name}}NoZeroValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}.
func consume{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return out, errInvalidUTF8{}
}
*p.{{.GoType.PointerMethod}}() = {{.ToGoTypeNoZero}}
out.n = n
return out, nil
}
{{end}}
var coder{{.Name}}NoZeroValidateUTF8 = pointerCoderFuncs{
size: size{{.Name}}NoZero,
marshal: append{{.Name}}NoZeroValidateUTF8,
unmarshal: consume{{.Name}}{{if .ToGoTypeNoZero}}NoZero{{end}}ValidateUTF8,
merge: merge{{.GoType.PointerMethod}}NoZero,
}
{{end}}
{{- if not .NoPointer}}
// size{{.Name}}Ptr returns the size of wire encoding a *{{.GoType}} pointer as a {{.Name}}.
// It panics if the pointer is nil.
func size{{.Name}}Ptr(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
{{if not .WireType.ConstSize -}}
v := **p.{{.GoType.PointerMethod}}Ptr()
{{end -}}
return f.tagsize + {{template "Size" .}}
}
// append{{.Name}}Ptr wire encodes a *{{.GoType}} pointer as a {{.Name}}.
// It panics if the pointer is nil.
func append{{.Name}}Ptr(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := **p.{{.GoType.PointerMethod}}Ptr()
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
return b, nil
}
// consume{{.Name}}Ptr wire decodes a *{{.GoType}} pointer as a {{.Name}}.
func consume{{.Name}}Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
vp := p.{{.GoType.PointerMethod}}Ptr()
if *vp == nil {
*vp = new({{.GoType}})
}
**vp = {{.ToGoType}}
out.n = n
return out, nil
}
var coder{{.Name}}Ptr = pointerCoderFuncs{
size: size{{.Name}}Ptr,
marshal: append{{.Name}}Ptr,
unmarshal: consume{{.Name}}Ptr,
merge: merge{{.GoType.PointerMethod}}Ptr,
}
{{end}}
{{if (eq .Name "String")}}
// append{{.Name}}PtrValidateUTF8 wire encodes a *{{.GoType}} pointer as a {{.Name}}.
// It panics if the pointer is nil.
func append{{.Name}}PtrValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := **p.{{.GoType.PointerMethod}}Ptr()
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return b, errInvalidUTF8{}
}
return b, nil
}
// consume{{.Name}}PtrValidateUTF8 wire decodes a *{{.GoType}} pointer as a {{.Name}}.
func consume{{.Name}}PtrValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return out, errInvalidUTF8{}
}
vp := p.{{.GoType.PointerMethod}}Ptr()
if *vp == nil {
*vp = new({{.GoType}})
}
**vp = {{.ToGoType}}
out.n = n
return out, nil
}
var coder{{.Name}}PtrValidateUTF8 = pointerCoderFuncs{
size: size{{.Name}}Ptr,
marshal: append{{.Name}}PtrValidateUTF8,
unmarshal: consume{{.Name}}PtrValidateUTF8,
merge: merge{{.GoType.PointerMethod}}Ptr,
}
{{end}}
// size{{.Name}}Slice returns the size of wire encoding a []{{.GoType}} pointer as a repeated {{.Name}}.
func size{{.Name}}Slice(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
s := *p.{{.GoType.PointerMethod}}Slice()
{{if .WireType.ConstSize -}}
size = len(s) * (f.tagsize + {{template "Size" .}})
{{- else -}}
for _, v := range s {
size += f.tagsize + {{template "Size" .}}
}
{{- end}}
return size
}
// append{{.Name}}Slice encodes a []{{.GoType}} pointer as a repeated {{.Name}}.
func append{{.Name}}Slice(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
s := *p.{{.GoType.PointerMethod}}Slice()
for _, v := range s {
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
}
return b, nil
}
// consume{{.Name}}Slice wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}.
func consume{{.Name}}Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.{{.GoType.PointerMethod}}Slice()
{{- if .WireType.Packable}}
if wtyp == protowire.BytesType {
s := *sp
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return out, errDecode
}
for len(b) > 0 {
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
s = append(s, {{.ToGoType}})
b = b[n:]
}
*sp = s
out.n = n
return out, nil
}
{{- end}}
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
*sp = append(*sp, {{.ToGoType}})
out.n = n
return out, nil
}
var coder{{.Name}}Slice = pointerCoderFuncs{
size: size{{.Name}}Slice,
marshal: append{{.Name}}Slice,
unmarshal: consume{{.Name}}Slice,
merge: merge{{.GoType.PointerMethod}}Slice,
}
{{if or (eq .Name "Bytes") (eq .Name "String")}}
// append{{.Name}}SliceValidateUTF8 encodes a []{{.GoType}} pointer as a repeated {{.Name}}.
func append{{.Name}}SliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
s := *p.{{.GoType.PointerMethod}}Slice()
for _, v := range s {
b = protowire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return b, errInvalidUTF8{}
}
}
return b, nil
}
// consume{{.Name}}SliceValidateUTF8 wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}.
func consume{{.Name}}SliceValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.{{.GoType.PointerMethod}}Slice()
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return out, errDecode
}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return out, errInvalidUTF8{}
}
*sp = append(*sp, {{.ToGoType}})
out.n = n
return out, nil
}
var coder{{.Name}}SliceValidateUTF8 = pointerCoderFuncs{
size: size{{.Name}}Slice,
marshal: append{{.Name}}SliceValidateUTF8,
unmarshal: consume{{.Name}}SliceValidateUTF8,
merge: merge{{.GoType.PointerMethod}}Slice,
}
{{end}}
{{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}}
// size{{.Name}}PackedSlice returns the size of wire encoding a []{{.GoType}} pointer as a packed repeated {{.Name}}.
func size{{.Name}}PackedSlice(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
s := *p.{{.GoType.PointerMethod}}Slice()
if len(s) == 0 {
return 0
}
{{if .WireType.ConstSize -}}
n := len(s) * {{template "Size" .}}
{{- else -}}
n := 0
for _, v := range s {
n += {{template "Size" .}}
}
{{- end}}
return f.tagsize + protowire.SizeBytes(n)
}
// append{{.Name}}PackedSlice encodes a []{{.GoType}} pointer as a packed repeated {{.Name}}.
func append{{.Name}}PackedSlice(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
s := *p.{{.GoType.PointerMethod}}Slice()
if len(s) == 0 {
return b, nil
}
b = protowire.AppendVarint(b, f.wiretag)
{{if .WireType.ConstSize -}}
n := len(s) * {{template "Size" .}}
{{- else -}}
n := 0
for _, v := range s {
n += {{template "Size" .}}
}
{{- end}}
b = protowire.AppendVarint(b, uint64(n))
for _, v := range s {
{{template "Append" .}}
}
return b, nil
}
var coder{{.Name}}PackedSlice = pointerCoderFuncs{
size: size{{.Name}}PackedSlice,
marshal: append{{.Name}}PackedSlice,
unmarshal: consume{{.Name}}Slice,
merge: merge{{.GoType.PointerMethod}}Slice,
}
{{end}}
{{end -}}
{{- if not .NoValueCodec}}
// size{{.Name}}Value returns the size of wire encoding a {{.GoType}} value as a {{.Name}}.
func size{{.Name}}Value(v protoreflect.Value, tagsize int, _ marshalOptions) int {
return tagsize + {{template "SizeValue" .}}
}
// append{{.Name}}Value encodes a {{.GoType}} value as a {{.Name}}.
func append{{.Name}}Value(b []byte, v protoreflect.Value, wiretag uint64, _ marshalOptions) ([]byte, error) {
b = protowire.AppendVarint(b, wiretag)
{{template "AppendValue" .}}
return b, nil
}
// consume{{.Name}}Value decodes a {{.GoType}} value as a {{.Name}}.
func consume{{.Name}}Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, _ unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return protoreflect.Value{}, out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return protoreflect.Value{}, out, errDecode
}
out.n = n
return {{.ToValue}}, out, nil
}
var coder{{.Name}}Value = valueCoderFuncs{
size: size{{.Name}}Value,
marshal: append{{.Name}}Value,
unmarshal: consume{{.Name}}Value,
{{- if (eq .Name "Bytes")}}
merge: mergeBytesValue,
{{- else}}
merge: mergeScalarValue,
{{- end}}
}
{{if (eq .Name "String")}}
// append{{.Name}}ValueValidateUTF8 encodes a {{.GoType}} value as a {{.Name}}.
func append{{.Name}}ValueValidateUTF8(b []byte, v protoreflect.Value, wiretag uint64, _ marshalOptions) ([]byte, error) {
b = protowire.AppendVarint(b, wiretag)
{{template "AppendValue" .}}
if !utf8.ValidString({{.FromValue}}) {
return b, errInvalidUTF8{}
}
return b, nil
}
// consume{{.Name}}ValueValidateUTF8 decodes a {{.GoType}} value as a {{.Name}}.
func consume{{.Name}}ValueValidateUTF8(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, _ unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return protoreflect.Value{}, out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return protoreflect.Value{}, out, errDecode
}
if !utf8.ValidString(v) {
return protoreflect.Value{}, out, errInvalidUTF8{}
}
out.n = n
return {{.ToValue}}, out, nil
}
var coder{{.Name}}ValueValidateUTF8 = valueCoderFuncs{
size: size{{.Name}}Value,
marshal: append{{.Name}}ValueValidateUTF8,
unmarshal: consume{{.Name}}ValueValidateUTF8,
merge: mergeScalarValue,
}
{{end}}
// size{{.Name}}SliceValue returns the size of wire encoding a []{{.GoType}} value as a repeated {{.Name}}.
func size{{.Name}}SliceValue(listv protoreflect.Value, tagsize int, _ marshalOptions) (size int) {
list := listv.List()
{{if .WireType.ConstSize -}}
size = list.Len() * (tagsize + {{template "SizeValue" .}})
{{- else -}}
for i, llen := 0, list.Len(); i < llen; i++ {
v := list.Get(i)
size += tagsize + {{template "SizeValue" .}}
}
{{- end}}
return size
}
// append{{.Name}}SliceValue encodes a []{{.GoType}} value as a repeated {{.Name}}.
func append{{.Name}}SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, _ marshalOptions) ([]byte, error) {
list := listv.List()
for i, llen := 0, list.Len(); i < llen; i++ {
v := list.Get(i)
b = protowire.AppendVarint(b, wiretag)
{{template "AppendValue" .}}
}
return b, nil
}
// consume{{.Name}}SliceValue wire decodes a []{{.GoType}} value as a repeated {{.Name}}.
func consume{{.Name}}SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, _ unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) {
list := listv.List()
{{- if .WireType.Packable}}
if wtyp == protowire.BytesType {
b, n := protowire.ConsumeBytes(b)
if n < 0 {
return protoreflect.Value{}, out, errDecode
}
for len(b) > 0 {
{{template "Consume" .}}
if n < 0 {
return protoreflect.Value{}, out, errDecode
}
list.Append({{.ToValue}})
b = b[n:]
}
out.n = n
return listv, out, nil
}
{{- end}}
if wtyp != {{.WireType.Expr}} {
return protoreflect.Value{}, out, errUnknown
}
{{template "Consume" .}}
if n < 0 {
return protoreflect.Value{}, out, errDecode
}
list.Append({{.ToValue}})
out.n = n
return listv, out, nil
}
var coder{{.Name}}SliceValue = valueCoderFuncs{
size: size{{.Name}}SliceValue,
marshal: append{{.Name}}SliceValue,
unmarshal: consume{{.Name}}SliceValue,
{{- if (eq .Name "Bytes")}}
merge: mergeBytesListValue,
{{- else}}
merge: mergeListValue,
{{- end}}
}
{{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}}
// size{{.Name}}PackedSliceValue returns the size of wire encoding a []{{.GoType}} value as a packed repeated {{.Name}}.
func size{{.Name}}PackedSliceValue(listv protoreflect.Value, tagsize int, _ marshalOptions) (size int) {
list := listv.List()
llen := list.Len()
if llen == 0 {
return 0
}
{{if .WireType.ConstSize -}}
n := llen * {{template "SizeValue" .}}
{{- else -}}
n := 0
for i, llen := 0, llen; i < llen; i++ {
v := list.Get(i)
n += {{template "SizeValue" .}}
}
{{- end}}
return tagsize + protowire.SizeBytes(n)
}
// append{{.Name}}PackedSliceValue encodes a []{{.GoType}} value as a packed repeated {{.Name}}.
func append{{.Name}}PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, _ marshalOptions) ([]byte, error) {
list := listv.List()
llen := list.Len()
if llen == 0 {
return b, nil
}
b = protowire.AppendVarint(b, wiretag)
{{if .WireType.ConstSize -}}
n := llen * {{template "SizeValue" .}}
{{- else -}}
n := 0
for i := 0; i < llen; i++ {
v := list.Get(i)
n += {{template "SizeValue" .}}
}
{{- end}}
b = protowire.AppendVarint(b, uint64(n))
for i := 0; i < llen; i++ {
v := list.Get(i)
{{template "AppendValue" .}}
}
return b, nil
}
var coder{{.Name}}PackedSliceValue = valueCoderFuncs{
size: size{{.Name}}PackedSliceValue,
marshal: append{{.Name}}PackedSliceValue,
unmarshal: consume{{.Name}}SliceValue,
merge: mergeListValue,
}
{{end}}
{{- end}}{{/* if not .NoValueCodec */}}
{{end -}}
// We append to an empty array rather than a nil []byte to get non-nil zero-length byte slices.
var emptyBuf [0]byte
var wireTypes = map[protoreflect.Kind]protowire.Type{
{{range . -}}
protoreflect.{{.Name}}Kind: {{.WireType.Expr}},
{{end}}
}
`))
func generateImplMessage() string {
return mustExecute(implMessageTemplate, []string{"messageState", "messageReflectWrapper"})
}
var implMessageTemplate = template.Must(template.New("").Parse(`
{{range . -}}
func (m *{{.}}) Descriptor() protoreflect.MessageDescriptor {
return m.messageInfo().Desc
}
func (m *{{.}}) Type() protoreflect.MessageType {
return m.messageInfo()
}
func (m *{{.}}) New() protoreflect.Message {
return m.messageInfo().New()
}
func (m *{{.}}) Interface() protoreflect.ProtoMessage {
{{if eq . "messageState" -}}
return m.protoUnwrap().(protoreflect.ProtoMessage)
{{- else -}}
if m, ok := m.protoUnwrap().(protoreflect.ProtoMessage); ok {
return m
}
return (*messageIfaceWrapper)(m)
{{- end -}}
}
func (m *{{.}}) protoUnwrap() interface{} {
return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem())
}
func (m *{{.}}) ProtoMethods() *protoiface.Methods {
m.messageInfo().init()
return &m.messageInfo().methods
}
// ProtoMessageInfo is a pseudo-internal API for allowing the v1 code
// to be able to retrieve a v2 MessageInfo struct.
//
// WARNING: This method is exempt from the compatibility promise and
// may be removed in the future without warning.
func (m *{{.}}) ProtoMessageInfo() *MessageInfo {
return m.messageInfo()
}
func (m *{{.}}) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) {
m.messageInfo().init()
for _, ri := range m.messageInfo().rangeInfos {
switch ri := ri.(type) {
case *fieldInfo:
if ri.has(m.pointer()) {
if !f(ri.fieldDesc, ri.get(m.pointer())) {
return
}
}
case *oneofInfo:
if n := ri.which(m.pointer()); n > 0 {
fi := m.messageInfo().fields[n]
if !f(fi.fieldDesc, fi.get(m.pointer())) {
return
}
}
}
}
m.messageInfo().extensionMap(m.pointer()).Range(f)
}
func (m *{{.}}) Has(fd protoreflect.FieldDescriptor) bool {
m.messageInfo().init()
if fi, xt := m.messageInfo().checkField(fd); fi != nil {
return fi.has(m.pointer())
} else {
return m.messageInfo().extensionMap(m.pointer()).Has(xt)
}
}
func (m *{{.}}) Clear(fd protoreflect.FieldDescriptor) {
m.messageInfo().init()
if fi, xt := m.messageInfo().checkField(fd); fi != nil {
fi.clear(m.pointer())
} else {
m.messageInfo().extensionMap(m.pointer()).Clear(xt)
}
}
func (m *{{.}}) Get(fd protoreflect.FieldDescriptor) protoreflect.Value {
m.messageInfo().init()
if fi, xt := m.messageInfo().checkField(fd); fi != nil {
return fi.get(m.pointer())
} else {
return m.messageInfo().extensionMap(m.pointer()).Get(xt)
}
}
func (m *{{.}}) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) {
m.messageInfo().init()
if fi, xt := m.messageInfo().checkField(fd); fi != nil {
fi.set(m.pointer(), v)
} else {
m.messageInfo().extensionMap(m.pointer()).Set(xt, v)
}
}
func (m *{{.}}) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value {
m.messageInfo().init()
if fi, xt := m.messageInfo().checkField(fd); fi != nil {
return fi.mutable(m.pointer())
} else {
return m.messageInfo().extensionMap(m.pointer()).Mutable(xt)
}
}
func (m *{{.}}) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value {
m.messageInfo().init()
if fi, xt := m.messageInfo().checkField(fd); fi != nil {
return fi.newField()
} else {
return xt.New()
}
}
func (m *{{.}}) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor {
m.messageInfo().init()
if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od {
return od.Fields().ByNumber(oi.which(m.pointer()))
}
panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName()))
}
func (m *{{.}}) GetUnknown() protoreflect.RawFields {
m.messageInfo().init()
return m.messageInfo().getUnknown(m.pointer())
}
func (m *{{.}}) SetUnknown(b protoreflect.RawFields) {
m.messageInfo().init()
m.messageInfo().setUnknown(m.pointer(), b)
}
func (m *{{.}}) IsValid() bool {
return !m.pointer().IsNil()
}
{{end}}
`))
func generateImplMerge() string {
return mustExecute(implMergeTemplate, GoTypes)
}
var implMergeTemplate = template.Must(template.New("").Parse(`
{{range .}}
{{if ne . "[]byte"}}
func merge{{.PointerMethod}}(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
*dst.{{.PointerMethod}}() = *src.{{.PointerMethod}}()
}
func merge{{.PointerMethod}}NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
v := *src.{{.PointerMethod}}()
if v != {{.Zero}} {
*dst.{{.PointerMethod}}() = v
}
}
func merge{{.PointerMethod}}Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
p := *src.{{.PointerMethod}}Ptr()
if p != nil {
v := *p
*dst.{{.PointerMethod}}Ptr() = &v
}
}
func merge{{.PointerMethod}}Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) {
ds := dst.{{.PointerMethod}}Slice()
ss := src.{{.PointerMethod}}Slice()
*ds = append(*ds, *ss...)
}
{{end}}
{{end}}
`))