// 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, protowire.ParseError(n) } *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, protowire.ParseError(n) } 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, protowire.ParseError(n) } *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, protowire.ParseError(n) } 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, protowire.ParseError(n) } 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, protowire.ParseError(n) } 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, protowire.ParseError(n) } for len(b) > 0 { {{template "Consume" .}} if n < 0 { return out, protowire.ParseError(n) } 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, protowire.ParseError(n) } *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, protowire.ParseError(n) } 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, protowire.ParseError(n) } 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, protowire.ParseError(n) } 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, protowire.ParseError(n) } for len(b) > 0 { {{template "Consume" .}} if n < 0 { return protoreflect.Value{}, out, protowire.ParseError(n) } 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, protowire.ParseError(n) } 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}} `))