internal/impl: pass *coderFieldInfo into fast-path functions

Refactor the fast-path size, marshal, unmarshal, and isinit functions to
take the *coderFieldInfo for the field as input.

This replaces a number of closures capturing field-specific information
with functions taking that information as an explicit parameter.

Change-Id: I8cb39701265edb7b673f6f04a0152d5f4dbb4d5d
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/218937
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Damien Neil 2020-02-09 12:26:50 -08:00
parent f26172248d
commit 316febd1ab
10 changed files with 675 additions and 701 deletions

View File

@ -92,23 +92,23 @@ v, n := wire.Consume{{.WireType}}(b)
{{- if .FromGoType }}
// size{{.Name}} returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}.
func size{{.Name}}(p pointer, tagsize int, _ marshalOptions) (size int) {
func size{{.Name}}(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
{{if not .WireType.ConstSize -}}
v := *p.{{.GoType.PointerMethod}}()
{{- end}}
return tagsize + {{template "Size" .}}
return f.tagsize + {{template "Size" .}}
}
// append{{.Name}} wire encodes a {{.GoType}} pointer as a {{.Name}}.
func append{{.Name}}(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
func append{{.Name}}(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
b = wire.AppendVarint(b, wiretag)
b = wire.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 wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consume{{.Name}}(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
@ -129,9 +129,9 @@ var coder{{.Name}} = pointerCoderFuncs{
{{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, wiretag uint64, _ marshalOptions) ([]byte, error) {
func append{{.Name}}ValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return b, errInvalidUTF8{}
@ -140,7 +140,7 @@ func append{{.Name}}ValidateUTF8(b []byte, p pointer, wiretag uint64, _ marshalO
}
// consume{{.Name}}ValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}.
func consume{{.Name}}ValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consume{{.Name}}ValidateUTF8(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
@ -165,22 +165,22 @@ var coder{{.Name}}ValidateUTF8 = pointerCoderFuncs{
// 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, tagsize int, _ marshalOptions) (size int) {
func size{{.Name}}NoZero(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
v := *p.{{.GoType.PointerMethod}}()
if {{template "IsZero" .}} {
return 0
}
return tagsize + {{template "Size" .}}
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, wiretag uint64, _ marshalOptions) ([]byte, error) {
func append{{.Name}}NoZero(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
if {{template "IsZero" .}} {
return b, nil
}
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
return b, nil
}
@ -188,7 +188,7 @@ func append{{.Name}}NoZero(b []byte, p pointer, wiretag uint64, _ marshalOptions
{{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 wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consume{{.Name}}NoZero(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
@ -211,12 +211,12 @@ var coder{{.Name}}NoZero = pointerCoderFuncs{
{{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, wiretag uint64, _ marshalOptions) ([]byte, error) {
func append{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := *p.{{.GoType.PointerMethod}}()
if {{template "IsZero" .}} {
return b, nil
}
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return b, errInvalidUTF8{}
@ -226,7 +226,7 @@ func append{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, wiretag uint64, _ ma
{{if .ToGoTypeNoZero}}
// consume{{.Name}}NoZeroValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}.
func consume{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consume{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
@ -253,24 +253,24 @@ var coder{{.Name}}NoZeroValidateUTF8 = pointerCoderFuncs{
{{- 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, tagsize int, _ marshalOptions) (size int) {
func size{{.Name}}Ptr(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
{{if not .WireType.ConstSize -}}
v := **p.{{.GoType.PointerMethod}}Ptr()
{{end -}}
return tagsize + {{template "Size" .}}
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, wiretag uint64, _ marshalOptions) ([]byte, error) {
func append{{.Name}}Ptr(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
v := **p.{{.GoType.PointerMethod}}Ptr()
b = wire.AppendVarint(b, wiretag)
b = wire.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 wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consume{{.Name}}Ptr(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
}
@ -295,30 +295,30 @@ var coder{{.Name}}Ptr = pointerCoderFuncs{
{{end}}
// size{{.Name}}Slice returns the size of wire encoding a []{{.GoType}} pointer as a repeated {{.Name}}.
func size{{.Name}}Slice(p pointer, tagsize int, _ marshalOptions) (size int) {
func size{{.Name}}Slice(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
s := *p.{{.GoType.PointerMethod}}Slice()
{{if .WireType.ConstSize -}}
size = len(s) * (tagsize + {{template "Size" .}})
size = len(s) * (f.tagsize + {{template "Size" .}})
{{- else -}}
for _, v := range s {
size += tagsize + {{template "Size" .}}
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, wiretag uint64, _ marshalOptions) ([]byte, error) {
func append{{.Name}}Slice(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
s := *p.{{.GoType.PointerMethod}}Slice()
for _, v := range s {
b = wire.AppendVarint(b, wiretag)
b = wire.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 wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consume{{.Name}}Slice(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.{{.GoType.PointerMethod}}Slice()
{{- if .WireType.Packable}}
if wtyp == wire.BytesType {
@ -360,10 +360,10 @@ var coder{{.Name}}Slice = pointerCoderFuncs{
{{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, wiretag uint64, _ marshalOptions) ([]byte, error) {
func append{{.Name}}SliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, _ marshalOptions) ([]byte, error) {
s := *p.{{.GoType.PointerMethod}}Slice()
for _, v := range s {
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return b, errInvalidUTF8{}
@ -373,7 +373,7 @@ func append{{.Name}}SliceValidateUTF8(b []byte, p pointer, wiretag uint64, _ mar
}
// consume{{.Name}}SliceValidateUTF8 wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}.
func consume{{.Name}}SliceValidateUTF8(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consume{{.Name}}SliceValidateUTF8(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
sp := p.{{.GoType.PointerMethod}}Slice()
if wtyp != {{.WireType.Expr}} {
return out, errUnknown
@ -399,7 +399,7 @@ var coder{{.Name}}SliceValidateUTF8 = pointerCoderFuncs{
{{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, tagsize int, _ marshalOptions) (size int) {
func size{{.Name}}PackedSlice(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
s := *p.{{.GoType.PointerMethod}}Slice()
if len(s) == 0 {
return 0
@ -412,16 +412,16 @@ func size{{.Name}}PackedSlice(p pointer, tagsize int, _ marshalOptions) (size in
n += {{template "Size" .}}
}
{{- end}}
return tagsize + wire.SizeBytes(n)
return f.tagsize + wire.SizeBytes(n)
}
// append{{.Name}}PackedSlice encodes a []{{.GoType}} pointer as a packed repeated {{.Name}}.
func append{{.Name}}PackedSlice(b []byte, p pointer, wiretag uint64, _ marshalOptions) ([]byte, error) {
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 = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
{{if .WireType.ConstSize -}}
n := len(s) * {{template "Size" .}}
{{- else -}}

View File

@ -29,31 +29,28 @@ func (errInvalidUTF8) InvalidUTF8() bool { return true }
//
// The unmarshal function is set on each field individually as usual.
func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structInfo) {
type oneofFieldInfo struct {
wiretag uint64 // field tag (number + wire type)
tagsize int // size of the varint-encoded tag
funcs pointerCoderFuncs
}
fs := si.oneofsByName[od.Name()]
ft := fs.Type
oneofFields := make(map[reflect.Type]*oneofFieldInfo)
oneofFields := make(map[reflect.Type]*coderFieldInfo)
needIsInit := false
fields := od.Fields()
for i, lim := 0, fields.Len(); i < lim; i++ {
fd := od.Fields().Get(i)
num := fd.Number()
cf := mi.coderFields[num]
// Make a copy of the original coderFieldInfo for use in unmarshaling.
//
// oneofFields[oneofType].funcs.marshal is the field-specific marshal function.
//
// mi.coderFields[num].marshal is set on only the first field in the oneof,
// and dispatches to the field-specific marshaler in oneofFields.
cf := *mi.coderFields[num]
ot := si.oneofWrappersByNumber[num]
funcs := fieldCoder(fd, ot.Field(0).Type)
oneofFields[ot] = &oneofFieldInfo{
wiretag: cf.wiretag,
tagsize: cf.tagsize,
funcs: funcs,
}
if funcs.isInit != nil {
cf.mi, cf.funcs = fieldCoder(fd, ot.Field(0).Type)
oneofFields[ot] = &cf
if cf.funcs.isInit != nil {
needIsInit = true
}
cf.funcs.unmarshal = func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
var vw reflect.Value // pointer to wrapper type
vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind
if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot {
@ -61,7 +58,7 @@ func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structIn
} else {
vw = reflect.New(ot)
}
out, err := funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, opts)
out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts)
if err != nil {
return out, err
}
@ -69,7 +66,7 @@ func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structIn
return out, nil
}
}
getInfo := func(p pointer) (pointer, *oneofFieldInfo) {
getInfo := func(p pointer) (pointer, *coderFieldInfo) {
v := p.AsValueOf(ft).Elem()
if v.IsNil() {
return pointer{}, nil
@ -81,27 +78,27 @@ func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structIn
return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()]
}
first := mi.coderFields[od.Fields().Get(0).Number()]
first.funcs.size = func(p pointer, tagsize int, opts marshalOptions) int {
first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int {
p, info := getInfo(p)
if info == nil || info.funcs.size == nil {
return 0
}
return info.funcs.size(p, info.tagsize, opts)
return info.funcs.size(p, info, opts)
}
first.funcs.marshal = func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) {
p, info := getInfo(p)
if info == nil || info.funcs.marshal == nil {
return b, nil
}
return info.funcs.marshal(b, p, info.wiretag, opts)
return info.funcs.marshal(b, p, info, opts)
}
if needIsInit {
first.funcs.isInit = func(p pointer) error {
first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error {
p, info := getInfo(p)
if info == nil || info.funcs.isInit == nil {
return nil
}
return info.funcs.isInit(p)
return info.funcs.isInit(p, info)
}
}
}
@ -118,7 +115,7 @@ func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
num := fd.Number()
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
m, ok := p.WeakFields().get(num)
if !ok {
return 0
@ -127,9 +124,9 @@ func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
if messageType == nil {
panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
}
return sizeMessage(m, tagsize, opts)
return sizeMessage(m, f.tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
m, ok := p.WeakFields().get(num)
if !ok {
return b, nil
@ -138,9 +135,9 @@ func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
if messageType == nil {
panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName()))
}
return appendMessage(b, m, wiretag, opts)
return appendMessage(b, m, f.wiretag, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
fs := p.WeakFields()
m, ok := fs.get(num)
if !ok {
@ -153,7 +150,7 @@ func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
}
return consumeMessage(b, m, wtyp, opts)
},
isInit: func(p pointer) error {
isInit: func(p pointer, f *coderFieldInfo) error {
m, ok := p.WeakFields().get(num)
if !ok {
return nil
@ -166,40 +163,32 @@ func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs {
func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
if mi := getMessageInfo(ft); mi != nil {
funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMessageInfo(p, mi, tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendMessageInfo(b, p, wiretag, mi, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
return consumeMessageInfo(b, p, mi, wtyp, opts)
},
size: sizeMessageInfo,
marshal: appendMessageInfo,
unmarshal: consumeMessageInfo,
}
if needsInitCheck(mi.Desc) {
funcs.isInit = func(p pointer) error {
return mi.isInitializedPointer(p.Elem())
}
funcs.isInit = isInitMessageInfo
}
return funcs
} else {
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
m := asMessage(p.AsValueOf(ft).Elem())
return sizeMessage(m, tagsize, opts)
return sizeMessage(m, f.tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
m := asMessage(p.AsValueOf(ft).Elem())
return appendMessage(b, m, wiretag, opts)
return appendMessage(b, m, f.wiretag, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
mp := p.AsValueOf(ft).Elem()
if mp.IsNil() {
mp.Set(reflect.New(ft.Elem()))
}
return consumeMessage(b, asMessage(mp), wtyp, opts)
},
isInit: func(p pointer) error {
isInit: func(p pointer, f *coderFieldInfo) error {
m := asMessage(p.AsValueOf(ft).Elem())
return proto.IsInitialized(m)
},
@ -207,17 +196,17 @@ func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCode
}
}
func sizeMessageInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
return wire.SizeBytes(mi.sizePointer(p.Elem(), opts)) + tagsize
func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
return wire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize
}
func appendMessageInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, uint64(mi.sizePointer(p.Elem(), opts)))
return mi.marshalAppendPointer(b, p.Elem(), opts)
func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
b = wire.AppendVarint(b, f.wiretag)
b = wire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts)))
return f.mi.marshalAppendPointer(b, p.Elem(), opts)
}
func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
func consumeMessageInfo(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != wire.BytesType {
return out, errUnknown
}
@ -226,9 +215,9 @@ func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, op
return out, wire.ParseError(n)
}
if p.Elem().IsNil() {
p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
}
o, err := mi.unmarshalPointer(v, p.Elem(), 0, opts)
o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts)
if err != nil {
return out, err
}
@ -237,6 +226,10 @@ func consumeMessageInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, op
return out, nil
}
func isInitMessageInfo(p pointer, f *coderFieldInfo) error {
return f.mi.isInitializedPointer(p.Elem())
}
func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int {
return wire.SizeBytes(proto.Size(m)) + tagsize
}
@ -321,40 +314,32 @@ func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderF
num := fd.Number()
if mi := getMessageInfo(ft); mi != nil {
funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeGroupType(p, mi, tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendGroupType(b, p, wiretag, mi, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
return consumeGroupType(b, p, mi, num, wtyp, opts)
},
size: sizeGroupType,
marshal: appendGroupType,
unmarshal: consumeGroupType,
}
if needsInitCheck(mi.Desc) {
funcs.isInit = func(p pointer) error {
return mi.isInitializedPointer(p.Elem())
}
funcs.isInit = isInitMessageInfo
}
return funcs
} else {
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
m := asMessage(p.AsValueOf(ft).Elem())
return sizeGroup(m, tagsize, opts)
return sizeGroup(m, f.tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
m := asMessage(p.AsValueOf(ft).Elem())
return appendGroup(b, m, wiretag, opts)
return appendGroup(b, m, f.wiretag, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
mp := p.AsValueOf(ft).Elem()
if mp.IsNil() {
mp.Set(reflect.New(ft.Elem()))
}
return consumeGroup(b, asMessage(mp), num, wtyp, opts)
},
isInit: func(p pointer) error {
isInit: func(p pointer, f *coderFieldInfo) error {
m := asMessage(p.AsValueOf(ft).Elem())
return proto.IsInitialized(m)
},
@ -362,25 +347,25 @@ func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderF
}
}
func sizeGroupType(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
return 2*tagsize + mi.sizePointer(p.Elem(), opts)
func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int {
return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts)
}
func appendGroupType(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
b = wire.AppendVarint(b, wiretag) // start group
b, err := mi.marshalAppendPointer(b, p.Elem(), opts)
b = wire.AppendVarint(b, wiretag+1) // end group
func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
b = wire.AppendVarint(b, f.wiretag) // start group
b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts)
b = wire.AppendVarint(b, f.wiretag+1) // end group
return b, err
}
func consumeGroupType(b []byte, p pointer, mi *MessageInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
func consumeGroupType(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != wire.StartGroupType {
return out, errUnknown
}
if p.Elem().IsNil() {
p.SetPointer(pointerOfValue(reflect.New(mi.GoReflectType.Elem())))
p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem())))
}
return mi.unmarshalPointer(b, p.Elem(), num, opts)
return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts)
}
func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int {
@ -416,56 +401,48 @@ func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, op
func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
if mi := getMessageInfo(ft); mi != nil {
funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMessageSliceInfo(p, mi, tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendMessageSliceInfo(b, p, wiretag, mi, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
return consumeMessageSliceInfo(b, p, mi, wtyp, opts)
},
size: sizeMessageSliceInfo,
marshal: appendMessageSliceInfo,
unmarshal: consumeMessageSliceInfo,
}
if needsInitCheck(mi.Desc) {
funcs.isInit = func(p pointer) error {
return isInitMessageSliceInfo(p, mi)
}
funcs.isInit = isInitMessageSliceInfo
}
return funcs
}
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMessageSlice(p, ft, tagsize, opts)
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
return sizeMessageSlice(p, ft, f.tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendMessageSlice(b, p, wiretag, ft, opts)
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
return appendMessageSlice(b, p, f.wiretag, ft, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
return consumeMessageSlice(b, p, ft, wtyp, opts)
},
isInit: func(p pointer) error {
isInit: func(p pointer, f *coderFieldInfo) error {
return isInitMessageSlice(p, ft)
},
}
}
func sizeMessageSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
s := p.PointerSlice()
n := 0
for _, v := range s {
n += wire.SizeBytes(mi.sizePointer(v, opts)) + tagsize
n += wire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize
}
return n
}
func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
s := p.PointerSlice()
var err error
for _, v := range s {
b = wire.AppendVarint(b, wiretag)
siz := mi.sizePointer(v, opts)
b = wire.AppendVarint(b, f.wiretag)
siz := f.mi.sizePointer(v, opts)
b = wire.AppendVarint(b, uint64(siz))
b, err = mi.marshalAppendPointer(b, v, opts)
b, err = f.mi.marshalAppendPointer(b, v, opts)
if err != nil {
return b, err
}
@ -473,7 +450,7 @@ func appendMessageSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo
return b, nil
}
func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
func consumeMessageSliceInfo(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != wire.BytesType {
return out, errUnknown
}
@ -481,9 +458,9 @@ func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Typ
if n < 0 {
return out, wire.ParseError(n)
}
m := reflect.New(mi.GoReflectType.Elem()).Interface()
m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
mp := pointerOfIface(m)
o, err := mi.unmarshalPointer(v, mp, 0, opts)
o, err := f.mi.unmarshalPointer(v, mp, 0, opts)
if err != nil {
return out, err
}
@ -493,10 +470,10 @@ func consumeMessageSliceInfo(b []byte, p pointer, mi *MessageInfo, wtyp wire.Typ
return out, nil
}
func isInitMessageSliceInfo(p pointer, mi *MessageInfo) error {
func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error {
s := p.PointerSlice()
for _, v := range s {
if err := mi.isInitializedPointer(v); err != nil {
if err := f.mi.isInitializedPointer(v); err != nil {
return err
}
}
@ -689,34 +666,26 @@ func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerC
num := fd.Number()
if mi := getMessageInfo(ft); mi != nil {
funcs := pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeGroupSliceInfo(p, mi, tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendGroupSliceInfo(b, p, wiretag, mi, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
return consumeGroupSliceInfo(b, p, num, wtyp, mi, opts)
},
size: sizeGroupSliceInfo,
marshal: appendGroupSliceInfo,
unmarshal: consumeGroupSliceInfo,
}
if needsInitCheck(mi.Desc) {
funcs.isInit = func(p pointer) error {
return isInitMessageSliceInfo(p, mi)
}
funcs.isInit = isInitMessageSliceInfo
}
return funcs
}
return pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeGroupSlice(p, ft, tagsize, opts)
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
return sizeGroupSlice(p, ft, f.tagsize, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendGroupSlice(b, p, wiretag, ft, opts)
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
return appendGroupSlice(b, p, f.wiretag, ft, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
return consumeGroupSlice(b, p, num, wtyp, ft, opts)
},
isInit: func(p pointer) error {
isInit: func(p pointer, f *coderFieldInfo) error {
return isInitMessageSlice(p, ft)
},
}
@ -768,36 +737,36 @@ func consumeGroupSlice(b []byte, p pointer, num wire.Number, wtyp wire.Type, goT
return out, nil
}
func sizeGroupSliceInfo(p pointer, mi *MessageInfo, tagsize int, opts marshalOptions) int {
func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int {
s := p.PointerSlice()
n := 0
for _, v := range s {
n += 2*tagsize + mi.sizePointer(v, opts)
n += 2*f.tagsize + f.mi.sizePointer(v, opts)
}
return n
}
func appendGroupSliceInfo(b []byte, p pointer, wiretag uint64, mi *MessageInfo, opts marshalOptions) ([]byte, error) {
func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
s := p.PointerSlice()
var err error
for _, v := range s {
b = wire.AppendVarint(b, wiretag) // start group
b, err = mi.marshalAppendPointer(b, v, opts)
b = wire.AppendVarint(b, f.wiretag) // start group
b, err = f.mi.marshalAppendPointer(b, v, opts)
if err != nil {
return b, err
}
b = wire.AppendVarint(b, wiretag+1) // end group
b = wire.AppendVarint(b, f.wiretag+1) // end group
}
return b, nil
}
func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type, mi *MessageInfo, opts unmarshalOptions) (unmarshalOutput, error) {
func consumeGroupSliceInfo(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
if wtyp != wire.StartGroupType {
return unmarshalOutput{}, errUnknown
}
m := reflect.New(mi.GoReflectType.Elem()).Interface()
m := reflect.New(f.mi.GoReflectType.Elem()).Interface()
mp := pointerOfIface(m)
out, err := mi.unmarshalPointer(b, mp, num, opts)
out, err := f.mi.unmarshalPointer(b, mp, f.num, opts)
if err != nil {
return out, err
}

File diff suppressed because it is too large Load Diff

View File

@ -14,18 +14,17 @@ import (
)
type mapInfo struct {
goType reflect.Type
keyWiretag uint64
valWiretag uint64
keyFuncs valueCoderFuncs
valFuncs valueCoderFuncs
keyZero pref.Value
keyKind pref.Kind
valMessageInfo *MessageInfo
conv *mapConverter
goType reflect.Type
keyWiretag uint64
valWiretag uint64
keyFuncs valueCoderFuncs
valFuncs valueCoderFuncs
keyZero pref.Value
keyKind pref.Kind
conv *mapConverter
}
func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (funcs pointerCoderFuncs) {
func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (valueMessage *MessageInfo, funcs pointerCoderFuncs) {
// TODO: Consider generating specialized map coders.
keyField := fd.MapKey()
valField := fd.MapValue()
@ -46,34 +45,34 @@ func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (funcs pointer
conv: conv,
}
if valField.Kind() == pref.MessageKind {
mapi.valMessageInfo = getMessageInfo(ft.Elem())
valueMessage = getMessageInfo(ft.Elem())
}
funcs = pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMap(p.AsValueOf(ft).Elem(), tagsize, mapi, opts)
size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int {
return sizeMap(p.AsValueOf(ft).Elem(), mapi, f, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendMap(b, p.AsValueOf(ft).Elem(), wiretag, mapi, opts)
marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
return appendMap(b, p.AsValueOf(ft).Elem(), mapi, f, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error) {
unmarshal: func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) {
mp := p.AsValueOf(ft)
if mp.Elem().IsNil() {
mp.Elem().Set(reflect.MakeMap(mapi.goType))
}
if mapi.valMessageInfo == nil {
return consumeMap(b, mp.Elem(), wtyp, mapi, opts)
if f.mi == nil {
return consumeMap(b, mp.Elem(), wtyp, mapi, f, opts)
} else {
return consumeMapOfMessage(b, mp.Elem(), wtyp, mapi, opts)
return consumeMapOfMessage(b, mp.Elem(), wtyp, mapi, f, opts)
}
},
}
if valFuncs.isInit != nil {
funcs.isInit = func(p pointer) error {
return isInitMap(p.AsValueOf(ft).Elem(), mapi)
funcs.isInit = func(p pointer, f *coderFieldInfo) error {
return isInitMap(p.AsValueOf(ft).Elem(), mapi, f)
}
}
return funcs
return valueMessage, funcs
}
const (
@ -81,7 +80,7 @@ const (
mapValTagSize = 1 // field 2, tag size 2.
)
func sizeMap(mapv reflect.Value, tagsize int, mapi *mapInfo, opts marshalOptions) int {
func sizeMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) int {
if mapv.Len() == 0 {
return 0
}
@ -92,19 +91,19 @@ func sizeMap(mapv reflect.Value, tagsize int, mapi *mapInfo, opts marshalOptions
keySize := mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
var valSize int
value := mapi.conv.valConv.PBValueOf(iter.Value())
if mapi.valMessageInfo == nil {
if f.mi == nil {
valSize = mapi.valFuncs.size(value, mapValTagSize, opts)
} else {
p := pointerOfValue(iter.Value())
valSize += mapValTagSize
valSize += wire.SizeBytes(mapi.valMessageInfo.sizePointer(p, opts))
valSize += wire.SizeBytes(f.mi.sizePointer(p, opts))
}
n += tagsize + wire.SizeBytes(keySize+valSize)
n += f.tagsize + wire.SizeBytes(keySize+valSize)
}
return n
}
func consumeMap(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *mapInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
func consumeMap(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != wire.BytesType {
return out, errUnknown
}
@ -161,7 +160,7 @@ func consumeMap(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *mapInfo, opt
return out, nil
}
func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *mapInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *mapInfo, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != wire.BytesType {
return out, errUnknown
}
@ -171,7 +170,7 @@ func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *map
}
var (
key = mapi.keyZero
val = reflect.New(mapi.valMessageInfo.GoReflectType.Elem())
val = reflect.New(f.mi.GoReflectType.Elem())
)
for len(b) > 0 {
num, wtyp, n := wire.ConsumeTag(b)
@ -203,7 +202,7 @@ func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *map
return out, wire.ParseError(n)
}
var o unmarshalOutput
o, err = mapi.valMessageInfo.unmarshalPointer(v, pointerOfValue(val), 0, opts)
o, err = f.mi.unmarshalPointer(v, pointerOfValue(val), 0, opts)
if o.initialized {
// Consider this map item initialized so long as we see
// an initialized value.
@ -225,8 +224,8 @@ func consumeMapOfMessage(b []byte, mapv reflect.Value, wtyp wire.Type, mapi *map
return out, nil
}
func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, opts marshalOptions) ([]byte, error) {
if mapi.valMessageInfo == nil {
func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
if f.mi == nil {
key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
val := mapi.conv.valConv.PBValueOf(valrv)
size := 0
@ -241,7 +240,7 @@ func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, opts mar
} else {
key := mapi.conv.keyConv.PBValueOf(keyrv).MapKey()
val := pointerOfValue(valrv)
valSize := mapi.valMessageInfo.sizePointer(val, opts)
valSize := f.mi.sizePointer(val, opts)
size := 0
size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
size += mapValTagSize + wire.SizeBytes(valSize)
@ -252,22 +251,22 @@ func appendMapItem(b []byte, keyrv, valrv reflect.Value, mapi *mapInfo, opts mar
}
b = wire.AppendVarint(b, mapi.valWiretag)
b = wire.AppendVarint(b, uint64(valSize))
return mapi.valMessageInfo.marshalAppendPointer(b, val, opts)
return f.mi.marshalAppendPointer(b, val, opts)
}
}
func appendMap(b []byte, mapv reflect.Value, wiretag uint64, mapi *mapInfo, opts marshalOptions) ([]byte, error) {
func appendMap(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
if mapv.Len() == 0 {
return b, nil
}
if opts.Deterministic() {
return appendMapDeterministic(b, mapv, wiretag, mapi, opts)
return appendMapDeterministic(b, mapv, mapi, f, opts)
}
iter := mapRange(mapv)
for iter.Next() {
var err error
b = wire.AppendVarint(b, wiretag)
b, err = appendMapItem(b, iter.Key(), iter.Value(), mapi, opts)
b = wire.AppendVarint(b, f.wiretag)
b, err = appendMapItem(b, iter.Key(), iter.Value(), mapi, f, opts)
if err != nil {
return b, err
}
@ -275,7 +274,7 @@ func appendMap(b []byte, mapv reflect.Value, wiretag uint64, mapi *mapInfo, opts
return b, nil
}
func appendMapDeterministic(b []byte, mapv reflect.Value, wiretag uint64, mapi *mapInfo, opts marshalOptions) ([]byte, error) {
func appendMapDeterministic(b []byte, mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
keys := mapv.MapKeys()
sort.Slice(keys, func(i, j int) bool {
switch keys[i].Kind() {
@ -295,8 +294,8 @@ func appendMapDeterministic(b []byte, mapv reflect.Value, wiretag uint64, mapi *
})
for _, key := range keys {
var err error
b = wire.AppendVarint(b, wiretag)
b, err = appendMapItem(b, key, mapv.MapIndex(key), mapi, opts)
b = wire.AppendVarint(b, f.wiretag)
b, err = appendMapItem(b, key, mapv.MapIndex(key), mapi, f, opts)
if err != nil {
return b, err
}
@ -304,8 +303,8 @@ func appendMapDeterministic(b []byte, mapv reflect.Value, wiretag uint64, mapi *
return b, nil
}
func isInitMap(mapv reflect.Value, mapi *mapInfo) error {
if mi := mapi.valMessageInfo; mi != nil {
func isInitMap(mapv reflect.Value, mapi *mapInfo, f *coderFieldInfo) error {
if mi := f.mi; mi != nil {
mi.init()
if !mi.needsInitCheck {
return nil

View File

@ -35,13 +35,15 @@ type coderMessageInfo struct {
type coderFieldInfo struct {
funcs pointerCoderFuncs // fast-path per-field functions
validation validationInfo // information used by message validation
num pref.FieldNumber // field number
offset offset // struct field offset
wiretag uint64 // field tag (number + wire type)
tagsize int // size of the varint-encoded tag
isPointer bool // true if IsNil may be called on the struct field
isRequired bool // true if field is required
mi *MessageInfo // field's message
ft reflect.Type
validation validationInfo // information used by message validation
num pref.FieldNumber // field number
offset offset // struct field offset
wiretag uint64 // field tag (number + wire type)
tagsize int // size of the varint-encoded tag
isPointer bool // true if IsNil may be called on the struct field
isRequired bool // true if field is required
}
func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
@ -67,6 +69,7 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
}
var fieldOffset offset
var funcs pointerCoderFuncs
var childMessage *MessageInfo
switch {
case fd.ContainingOneof() != nil:
fieldOffset = offsetOf(fs, mi.Exporter)
@ -75,14 +78,16 @@ func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
funcs = makeWeakMessageFieldCoder(fd)
default:
fieldOffset = offsetOf(fs, mi.Exporter)
funcs = fieldCoder(fd, ft)
childMessage, funcs = fieldCoder(fd, ft)
}
cf := &coderFieldInfo{
num: fd.Number(),
offset: fieldOffset,
wiretag: wiretag,
ft: ft,
tagsize: wire.SizeVarint(wiretag),
funcs: funcs,
mi: childMessage,
validation: newFieldValidationInfo(mi, si, fd, ft),
isPointer: (fd.Cardinality() == pref.Repeated ||
fd.Kind() == pref.MessageKind ||

View File

@ -12,19 +12,19 @@ import (
"google.golang.org/protobuf/internal/encoding/wire"
)
func sizeEnum(p pointer, tagsize int, _ marshalOptions) (size int) {
func sizeEnum(p pointer, f *coderFieldInfo, _ marshalOptions) (size int) {
v := p.v.Elem().Int()
return tagsize + wire.SizeVarint(uint64(v))
return f.tagsize + wire.SizeVarint(uint64(v))
}
func appendEnum(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
func appendEnum(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
v := p.v.Elem().Int()
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
b = wire.AppendVarint(b, uint64(v))
return b, nil
}
func consumeEnum(b []byte, p pointer, wtyp wire.Type, _ unmarshalOptions) (out unmarshalOutput, err error) {
func consumeEnum(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, _ unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != wire.VarintType {
return out, errUnknown
}
@ -43,18 +43,18 @@ var coderEnum = pointerCoderFuncs{
unmarshal: consumeEnum,
}
func sizeEnumNoZero(p pointer, tagsize int, opts marshalOptions) (size int) {
func sizeEnumNoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
if p.v.Elem().Int() == 0 {
return 0
}
return sizeEnum(p, tagsize, opts)
return sizeEnum(p, f, opts)
}
func appendEnumNoZero(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
func appendEnumNoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
if p.v.Elem().Int() == 0 {
return b, nil
}
return appendEnum(b, p, wiretag, opts)
return appendEnum(b, p, f, opts)
}
var coderEnumNoZero = pointerCoderFuncs{
@ -63,22 +63,22 @@ var coderEnumNoZero = pointerCoderFuncs{
unmarshal: consumeEnum,
}
func sizeEnumPtr(p pointer, tagsize int, opts marshalOptions) (size int) {
return sizeEnum(pointer{p.v.Elem()}, tagsize, opts)
func sizeEnumPtr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
return sizeEnum(pointer{p.v.Elem()}, f, opts)
}
func appendEnumPtr(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendEnum(b, pointer{p.v.Elem()}, wiretag, opts)
func appendEnumPtr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
return appendEnum(b, pointer{p.v.Elem()}, f, opts)
}
func consumeEnumPtr(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
func consumeEnumPtr(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
if wtyp != wire.VarintType {
return out, errUnknown
}
if p.v.Elem().IsNil() {
p.v.Elem().Set(reflect.New(p.v.Elem().Type().Elem()))
}
return consumeEnum(b, pointer{p.v.Elem()}, wtyp, opts)
return consumeEnum(b, pointer{p.v.Elem()}, wtyp, f, opts)
}
var coderEnumPtr = pointerCoderFuncs{
@ -87,24 +87,24 @@ var coderEnumPtr = pointerCoderFuncs{
unmarshal: consumeEnumPtr,
}
func sizeEnumSlice(p pointer, tagsize int, opts marshalOptions) (size int) {
func sizeEnumSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
s := p.v.Elem()
for i, llen := 0, s.Len(); i < llen; i++ {
size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
size += wire.SizeVarint(uint64(s.Index(i).Int())) + f.tagsize
}
return size
}
func appendEnumSlice(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
func appendEnumSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
s := p.v.Elem()
for i, llen := 0, s.Len(); i < llen; i++ {
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
}
return b, nil
}
func consumeEnumSlice(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) {
func consumeEnumSlice(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) {
s := p.v.Elem()
if wtyp == wire.BytesType {
b, n := wire.ConsumeBytes(b)
@ -144,7 +144,7 @@ var coderEnumSlice = pointerCoderFuncs{
unmarshal: consumeEnumSlice,
}
func sizeEnumPackedSlice(p pointer, tagsize int, opts marshalOptions) (size int) {
func sizeEnumPackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) {
s := p.v.Elem()
llen := s.Len()
if llen == 0 {
@ -154,16 +154,16 @@ func sizeEnumPackedSlice(p pointer, tagsize int, opts marshalOptions) (size int)
for i := 0; i < llen; i++ {
n += wire.SizeVarint(uint64(s.Index(i).Int()))
}
return tagsize + wire.SizeBytes(n)
return f.tagsize + wire.SizeBytes(n)
}
func appendEnumPackedSlice(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
func appendEnumPackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) {
s := p.v.Elem()
llen := s.Len()
if llen == 0 {
return b, nil
}
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, f.wiretag)
n := 0
for i := 0; i < llen; i++ {
n += wire.SizeVarint(uint64(s.Index(i).Int()))

View File

@ -15,10 +15,11 @@ import (
// pointerCoderFuncs is a set of pointer encoding functions.
type pointerCoderFuncs struct {
size func(p pointer, tagsize int, opts marshalOptions) int
marshal func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error)
unmarshal func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (unmarshalOutput, error)
isInit func(p pointer) error
mi *MessageInfo
size func(p pointer, f *coderFieldInfo, opts marshalOptions) int
marshal func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error)
unmarshal func(b []byte, p pointer, wtyp wire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error)
isInit func(p pointer, f *coderFieldInfo) error
}
// valueCoderFuncs is a set of protoreflect.Value encoding functions.
@ -31,7 +32,7 @@ type valueCoderFuncs struct {
// fieldCoder returns pointer functions for a field, used for operating on
// struct fields.
func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) (*MessageInfo, pointerCoderFuncs) {
switch {
case fd.IsMap():
return encoderFuncsForMap(fd, ft)
@ -44,84 +45,84 @@ func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
switch fd.Kind() {
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBoolSlice
return nil, coderBoolSlice
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnumSlice
return nil, coderEnumSlice
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32Slice
return nil, coderInt32Slice
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32Slice
return nil, coderSint32Slice
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32Slice
return nil, coderUint32Slice
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64Slice
return nil, coderInt64Slice
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64Slice
return nil, coderSint64Slice
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64Slice
return nil, coderUint64Slice
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32Slice
return nil, coderSfixed32Slice
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32Slice
return nil, coderFixed32Slice
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloatSlice
return nil, coderFloatSlice
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64Slice
return nil, coderSfixed64Slice
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64Slice
return nil, coderFixed64Slice
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDoubleSlice
return nil, coderDoubleSlice
}
case pref.StringKind:
if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) {
return coderStringSliceValidateUTF8
return nil, coderStringSliceValidateUTF8
}
if ft.Kind() == reflect.String {
return coderStringSlice
return nil, coderStringSlice
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) {
return coderBytesSliceValidateUTF8
return nil, coderBytesSliceValidateUTF8
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesSlice
return nil, coderBytesSlice
}
case pref.BytesKind:
if ft.Kind() == reflect.String {
return coderStringSlice
return nil, coderStringSlice
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesSlice
return nil, coderBytesSlice
}
case pref.MessageKind:
return makeMessageSliceFieldCoder(fd, ft)
return getMessageInfo(ft), makeMessageSliceFieldCoder(fd, ft)
case pref.GroupKind:
return makeGroupSliceFieldCoder(fd, ft)
return getMessageInfo(ft), makeGroupSliceFieldCoder(fd, ft)
}
case fd.Cardinality() == pref.Repeated && fd.IsPacked():
// Packed repeated fields.
@ -135,144 +136,144 @@ func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
switch fd.Kind() {
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBoolPackedSlice
return nil, coderBoolPackedSlice
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnumPackedSlice
return nil, coderEnumPackedSlice
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32PackedSlice
return nil, coderInt32PackedSlice
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32PackedSlice
return nil, coderSint32PackedSlice
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32PackedSlice
return nil, coderUint32PackedSlice
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64PackedSlice
return nil, coderInt64PackedSlice
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64PackedSlice
return nil, coderSint64PackedSlice
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64PackedSlice
return nil, coderUint64PackedSlice
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32PackedSlice
return nil, coderSfixed32PackedSlice
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32PackedSlice
return nil, coderFixed32PackedSlice
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloatPackedSlice
return nil, coderFloatPackedSlice
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64PackedSlice
return nil, coderSfixed64PackedSlice
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64PackedSlice
return nil, coderFixed64PackedSlice
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDoublePackedSlice
return nil, coderDoublePackedSlice
}
}
case fd.Kind() == pref.MessageKind:
return makeMessageFieldCoder(fd, ft)
return getMessageInfo(ft), makeMessageFieldCoder(fd, ft)
case fd.Kind() == pref.GroupKind:
return makeGroupFieldCoder(fd, ft)
return getMessageInfo(ft), makeGroupFieldCoder(fd, ft)
case fd.Syntax() == pref.Proto3 && fd.ContainingOneof() == nil:
// Populated oneof fields always encode even if set to the zero value,
// which normally are not encoded in proto3.
switch fd.Kind() {
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBoolNoZero
return nil, coderBoolNoZero
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnumNoZero
return nil, coderEnumNoZero
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32NoZero
return nil, coderInt32NoZero
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32NoZero
return nil, coderSint32NoZero
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32NoZero
return nil, coderUint32NoZero
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64NoZero
return nil, coderInt64NoZero
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64NoZero
return nil, coderSint64NoZero
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64NoZero
return nil, coderUint64NoZero
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32NoZero
return nil, coderSfixed32NoZero
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32NoZero
return nil, coderFixed32NoZero
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloatNoZero
return nil, coderFloatNoZero
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64NoZero
return nil, coderSfixed64NoZero
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64NoZero
return nil, coderFixed64NoZero
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDoubleNoZero
return nil, coderDoubleNoZero
}
case pref.StringKind:
if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) {
return coderStringNoZeroValidateUTF8
return nil, coderStringNoZeroValidateUTF8
}
if ft.Kind() == reflect.String {
return coderStringNoZero
return nil, coderStringNoZero
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) {
return coderBytesNoZeroValidateUTF8
return nil, coderBytesNoZeroValidateUTF8
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesNoZero
return nil, coderBytesNoZero
}
case pref.BytesKind:
if ft.Kind() == reflect.String {
return coderStringNoZero
return nil, coderStringNoZero
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesNoZero
return nil, coderBytesNoZero
}
}
case ft.Kind() == reflect.Ptr:
@ -280,146 +281,146 @@ func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
switch fd.Kind() {
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBoolPtr
return nil, coderBoolPtr
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnumPtr
return nil, coderEnumPtr
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32Ptr
return nil, coderInt32Ptr
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32Ptr
return nil, coderSint32Ptr
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32Ptr
return nil, coderUint32Ptr
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64Ptr
return nil, coderInt64Ptr
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64Ptr
return nil, coderSint64Ptr
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64Ptr
return nil, coderUint64Ptr
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32Ptr
return nil, coderSfixed32Ptr
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32Ptr
return nil, coderFixed32Ptr
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloatPtr
return nil, coderFloatPtr
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64Ptr
return nil, coderSfixed64Ptr
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64Ptr
return nil, coderFixed64Ptr
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDoublePtr
return nil, coderDoublePtr
}
case pref.StringKind:
if ft.Kind() == reflect.String {
return coderStringPtr
return nil, coderStringPtr
}
case pref.BytesKind:
if ft.Kind() == reflect.String {
return coderStringPtr
return nil, coderStringPtr
}
}
default:
switch fd.Kind() {
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBool
return nil, coderBool
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnum
return nil, coderEnum
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32
return nil, coderInt32
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32
return nil, coderSint32
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32
return nil, coderUint32
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64
return nil, coderInt64
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64
return nil, coderSint64
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64
return nil, coderUint64
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32
return nil, coderSfixed32
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32
return nil, coderFixed32
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloat
return nil, coderFloat
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64
return nil, coderSfixed64
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64
return nil, coderFixed64
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDouble
return nil, coderDouble
}
case pref.StringKind:
if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) {
return coderStringValidateUTF8
return nil, coderStringValidateUTF8
}
if ft.Kind() == reflect.String {
return coderString
return nil, coderString
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) {
return coderBytesValidateUTF8
return nil, coderBytesValidateUTF8
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytes
return nil, coderBytes
}
case pref.BytesKind:
if ft.Kind() == reflect.String {
return coderString
return nil, coderString
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytes
return nil, coderBytes
}
}
}

View File

@ -120,7 +120,7 @@ func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Numbe
break
}
var o unmarshalOutput
o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, f, opts)
n = o.n
if err != nil {
break

View File

@ -69,7 +69,7 @@ func (mi *MessageInfo) sizePointerSlow(p pointer, opts marshalOptions) (size int
if f.isPointer && fptr.Elem().IsNil() {
continue
}
size += f.funcs.size(fptr, f.tagsize, opts)
size += f.funcs.size(fptr, f, opts)
}
if mi.unknownOffset.IsValid() {
u := *p.Apply(mi.unknownOffset).Bytes()
@ -119,7 +119,7 @@ func (mi *MessageInfo) marshalAppendPointer(b []byte, p pointer, opts marshalOpt
if f.isPointer && fptr.Elem().IsNil() {
continue
}
b, err = f.funcs.marshal(b, fptr, f.wiretag, opts)
b, err = f.funcs.marshal(b, fptr, f, opts)
if err != nil {
return b, err
}

View File

@ -54,7 +54,7 @@ func (mi *MessageInfo) isInitializedPointer(p pointer) error {
if f.funcs.isInit == nil {
continue
}
if err := f.funcs.isInit(fptr); err != nil {
if err := f.funcs.isInit(fptr, f); err != nil {
return err
}
}