internal/impl: store extension values as Values

Change the storage type of ExtensionField from interface{} to
protoreflect.Value.

Replace the codec functions operating on interface{}s with ones
operating on Values.

Values are potentially more efficient, since they can represent
non-pointer types without allocation. This also reduces the number of
types used to represent field values.

Additionally, this change lays groundwork for changing the
user-visible representation of repeated extension fields from
*[]T to []T. The storage type for extension fields must support mutation
(thus *[]T currently); changing the storage type to a Value permits this
without the need to introduce yet another view on field values.

Change-Id: Ida336be14112bb940f655236eb58df21bf312525
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/192218
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
This commit is contained in:
Damien Neil 2019-08-22 11:41:32 -07:00
parent 835b271169
commit 68b81c3117
13 changed files with 1533 additions and 1482 deletions

View File

@ -39,6 +39,16 @@ wire.Size{{.WireType}}({{.FromGoType}})
{{- end -}}
{{- end -}}
{{- define "SizeValue" -}}
{{- if .WireType.ConstSize -}}
wire.Size{{.WireType}}()
{{- else if eq .WireType "Bytes" -}}
wire.SizeBytes(len({{.FromValue}}))
{{- else -}}
wire.Size{{.WireType}}({{.FromValue}})
{{- end -}}
{{- end -}}
{{- /*
Append is a set of statements appending 'v' to 'b'.
*/ -}}
@ -50,6 +60,14 @@ b = wire.Append{{.WireType}}(b, {{.FromGoType}})
{{- end -}}
{{- end -}}
{{- define "AppendValue" -}}
{{- if eq .Name "String" -}}
b = wire.AppendString(b, {{.FromValue}})
{{- else -}}
b = wire.Append{{.WireType}}(b, {{.FromValue}})
{{- end -}}
{{- end -}}
{{- define "Consume" -}}
{{- if eq .Name "String" -}}
wire.ConsumeString(b)
@ -59,6 +77,7 @@ wire.Consume{{.WireType}}(b)
{{- end -}}
{{- range .}}
{{- 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) {
@ -405,184 +424,184 @@ var coder{{.Name}}PackedSlice = pointerCoderFuncs{
}
{{end}}
// size{{.Name}}Iface returns the size of wire encoding a {{.GoType}} value as a {{.Name}}.
func size{{.Name}}Iface(ival interface{}, tagsize int, _ marshalOptions) int {
{{- if not .WireType.ConstSize}}
v := ival.({{.GoType}})
{{end -}}
return tagsize + {{template "Size" .}}
{{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}}Iface encodes a {{.GoType}} value as a {{.Name}}.
func append{{.Name}}Iface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
v := ival.({{.GoType}})
// 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 = wire.AppendVarint(b, wiretag)
{{template "Append" .}}
{{template "AppendValue" .}}
return b, nil
}
// consume{{.Name}}Iface decodes a {{.GoType}} value as a {{.Name}}.
func consume{{.Name}}Iface(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
// consume{{.Name}}Value decodes a {{.GoType}} value as a {{.Name}}.
func consume{{.Name}}Value(b []byte, _ protoreflect.Value, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (protoreflect.Value, int, error) {
if wtyp != {{.WireType.Expr}} {
return nil, 0, errUnknown
return protoreflect.Value{}, 0, errUnknown
}
v, n := {{template "Consume" .}}
if n < 0 {
return nil, 0, wire.ParseError(n)
return protoreflect.Value{}, 0, wire.ParseError(n)
}
return {{.ToGoType}}, n, nil
return {{.ToValue}}, n, nil
}
var coder{{.Name}}Iface = ifaceCoderFuncs{
size: size{{.Name}}Iface,
marshal: append{{.Name}}Iface,
unmarshal: consume{{.Name}}Iface,
var coder{{.Name}}Value = valueCoderFuncs{
size: size{{.Name}}Value,
marshal: append{{.Name}}Value,
unmarshal: consume{{.Name}}Value,
}
{{if or (eq .Name "Bytes") (eq .Name "String")}}
// append{{.Name}}IfaceValidateUTF8 encodes a {{.GoType}} value as a {{.Name}}.
func append{{.Name}}IfaceValidateUTF8(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
v := ival.({{.GoType}})
// 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 = wire.AppendVarint(b, wiretag)
{{template "Append" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
{{template "AppendValue" .}}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}({{.FromValue}}) {
return b, errInvalidUTF8{}
}
return b, nil
}
// consume{{.Name}}IfaceValidateUTF8 decodes a {{.GoType}} value as a {{.Name}}.
func consume{{.Name}}IfaceValidateUTF8(b []byte, _ interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
// consume{{.Name}}ValueValidateUTF8 decodes a {{.GoType}} value as a {{.Name}}.
func consume{{.Name}}ValueValidateUTF8(b []byte, _ protoreflect.Value, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (protoreflect.Value, int, error) {
if wtyp != {{.WireType.Expr}} {
return nil, 0, errUnknown
return protoreflect.Value{}, 0, errUnknown
}
v, n := {{template "Consume" .}}
if n < 0 {
return nil, 0, wire.ParseError(n)
return protoreflect.Value{}, 0, wire.ParseError(n)
}
if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) {
return nil, 0, errInvalidUTF8{}
return protoreflect.Value{}, 0, errInvalidUTF8{}
}
return {{.ToGoType}}, n, nil
return {{.ToValue}}, n, nil
}
var coder{{.Name}}IfaceValidateUTF8 = ifaceCoderFuncs{
size: size{{.Name}}Iface,
marshal: append{{.Name}}IfaceValidateUTF8,
unmarshal: consume{{.Name}}IfaceValidateUTF8,
var coder{{.Name}}ValueValidateUTF8 = valueCoderFuncs{
size: size{{.Name}}Value,
marshal: append{{.Name}}ValueValidateUTF8,
unmarshal: consume{{.Name}}ValueValidateUTF8,
}
{{end}}
// size{{.Name}}SliceIface returns the size of wire encoding a []{{.GoType}} value as a repeated {{.Name}}.
func size{{.Name}}SliceIface(ival interface{}, tagsize int, _ marshalOptions) (size int) {
s := *ival.(*[]{{.GoType}})
// 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 = len(s) * (tagsize + {{template "Size" .}})
size = list.Len() * (tagsize + {{template "SizeValue" .}})
{{- else -}}
for _, v := range s {
size += tagsize + {{template "Size" .}}
for i, llen := 0, list.Len(); i < llen; i++ {
v := list.Get(i)
size += tagsize + {{template "SizeValue" .}}
}
{{- end}}
return size
}
// append{{.Name}}SliceIface encodes a []{{.GoType}} value as a repeated {{.Name}}.
func append{{.Name}}SliceIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
s := *ival.(*[]{{.GoType}})
for _, v := range s {
// 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 = wire.AppendVarint(b, wiretag)
{{template "Append" .}}
{{template "AppendValue" .}}
}
return b, nil
}
// consume{{.Name}}SliceIface wire decodes a []{{.GoType}} value as a repeated {{.Name}}.
func consume{{.Name}}SliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ interface{}, n int, err error) {
sp := ival.(*[]{{.GoType}})
// consume{{.Name}}SliceValue wire decodes a []{{.GoType}} value as a repeated {{.Name}}.
func consume{{.Name}}SliceValue(b []byte, listv protoreflect.Value, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (_ protoreflect.Value, n int, err error) {
list := listv.List()
{{- if .WireType.Packable}}
if wtyp == wire.BytesType {
s := *sp
b, n = wire.ConsumeBytes(b)
if n < 0 {
return nil, 0, wire.ParseError(n)
return protoreflect.Value{}, 0, wire.ParseError(n)
}
for len(b) > 0 {
v, n := {{template "Consume" .}}
if n < 0 {
return nil, 0, wire.ParseError(n)
return protoreflect.Value{}, 0, wire.ParseError(n)
}
s = append(s, {{.ToGoType}})
list.Append({{.ToValue}})
b = b[n:]
}
*sp = s
return ival, n, nil
return listv, n, nil
}
{{- end}}
if wtyp != {{.WireType.Expr}} {
return nil, 0, errUnknown
return protoreflect.Value{}, 0, errUnknown
}
v, n := {{template "Consume" .}}
if n < 0 {
return nil, 0, wire.ParseError(n)
return protoreflect.Value{}, 0, wire.ParseError(n)
}
*sp = append(*sp, {{.ToGoType}})
return ival, n, nil
list.Append({{.ToValue}})
return listv, n, nil
}
var coder{{.Name}}SliceIface = ifaceCoderFuncs{
size: size{{.Name}}SliceIface,
marshal: append{{.Name}}SliceIface,
unmarshal: consume{{.Name}}SliceIface,
var coder{{.Name}}SliceValue = valueCoderFuncs{
size: size{{.Name}}SliceValue,
marshal: append{{.Name}}SliceValue,
unmarshal: consume{{.Name}}SliceValue,
}
{{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}}
// size{{.Name}}PackedSliceIface returns the size of wire encoding a []{{.GoType}} value as a packed repeated {{.Name}}.
func size{{.Name}}PackedSliceIface(ival interface{}, tagsize int, _ marshalOptions) (size int) {
s := *ival.(*[]{{.GoType}})
if len(s) == 0 {
return 0
}
// 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()
{{if .WireType.ConstSize -}}
n := len(s) * {{template "Size" .}}
n := list.Len() * {{template "SizeValue" .}}
{{- else -}}
n := 0
for _, v := range s {
n += {{template "Size" .}}
for i, llen := 0, list.Len(); i < llen; i++ {
v := list.Get(i)
n += {{template "SizeValue" .}}
}
{{- end}}
return tagsize + wire.SizeBytes(n)
}
// append{{.Name}}PackedSliceIface encodes a []{{.GoType}} value as a packed repeated {{.Name}}.
func append{{.Name}}PackedSliceIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
s := *ival.(*[]{{.GoType}})
if len(s) == 0 {
// 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 = wire.AppendVarint(b, wiretag)
{{if .WireType.ConstSize -}}
n := len(s) * {{template "Size" .}}
n := llen * {{template "SizeValue" .}}
{{- else -}}
n := 0
for _, v := range s {
n += {{template "Size" .}}
for i := 0; i < llen; i++ {
v := list.Get(i)
n += {{template "SizeValue" .}}
}
{{- end}}
b = wire.AppendVarint(b, uint64(n))
for _, v := range s {
{{template "Append" .}}
for i := 0; i < llen; i++ {
v := list.Get(i)
{{template "AppendValue" .}}
}
return b, nil
}
var coder{{.Name}}PackedSliceIface = ifaceCoderFuncs{
size: size{{.Name}}PackedSliceIface,
marshal: append{{.Name}}PackedSliceIface,
unmarshal: consume{{.Name}}SliceIface,
var coder{{.Name}}PackedSliceValue = valueCoderFuncs{
size: size{{.Name}}PackedSliceValue,
marshal: append{{.Name}}PackedSliceValue,
unmarshal: consume{{.Name}}SliceValue,
}
{{end}}
{{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.

View File

@ -16,7 +16,7 @@ type extensionFieldInfo struct {
wiretag uint64
tagsize int
unmarshalNeedsValue bool
funcs ifaceCoderFuncs
funcs valueCoderFuncs
}
func (mi *MessageInfo) extensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
@ -66,60 +66,80 @@ type ExtensionField struct {
// value is either the value of GetValue,
// or a *lazyExtensionValue that then returns the value of GetValue.
value interface{} // TODO: switch to protoreflect.Value
value pref.Value
lazy *lazyExtensionValue
}
func (f ExtensionField) HasType() bool {
return f.typ != nil
}
func (f ExtensionField) GetType() pref.ExtensionType {
return f.typ
}
func (f *ExtensionField) SetType(t pref.ExtensionType) {
// Set sets the type and value of the extension field.
// This must not be called concurrently.
func (f *ExtensionField) Set(t pref.ExtensionType, v pref.Value) {
f.typ = t
f.value = v
}
// HasValue reports whether a value is set for the extension field.
// This may be called concurrently.
func (f ExtensionField) HasValue() bool {
return f.value != nil
// SetLazy sets the type and a value that is to be lazily evaluated upon first use.
// This must not be called concurrently.
func (f *ExtensionField) SetLazy(t pref.ExtensionType, fn func() pref.Value) {
f.typ = t
f.lazy = &lazyExtensionValue{value: fn}
}
// GetValue returns the concrete value for the extension field.
// Let the type of Desc.ExtensionType be the "API type" and
// the type of GetValue be the "storage type".
// The API type and storage type are the same except:
// * for scalars (except []byte), where the API type uses *T,
// while the storage type uses T.
// * for repeated fields, where the API type uses []T,
// while the storage type uses *[]T.
//
// The reason for the divergence is so that the storage type more naturally
// matches what is expected of when retrieving the values through the
// protobuf reflection APIs.
//
// GetValue is only populated if Desc is also populated.
// Value returns the value of the extension field.
// This may be called concurrently.
//
// TODO: switch interface{} to protoreflect.Value
func (f ExtensionField) GetValue() interface{} {
if f, ok := f.value.(*lazyExtensionValue); ok {
return f.GetValue()
func (f *ExtensionField) Value() pref.Value {
if f.lazy != nil {
return f.lazy.GetValue()
}
return f.value
}
// SetEagerValue sets the current value of the extension.
// This must not be called concurrently.
func (f *ExtensionField) SetEagerValue(v interface{}) {
f.value = v
// Type returns the type of the extension field.
// This may be called concurrently.
func (f ExtensionField) Type() pref.ExtensionType {
return f.typ
}
// SetLazyValue sets a value that is to be lazily evaluated upon first use.
// The returned value must not be nil.
// This must not be called concurrently.
func (f *ExtensionField) SetLazyValue(v func() interface{}) {
f.value = &lazyExtensionValue{value: v}
// IsSet returns whether the extension field is set.
// This may be called concurrently.
func (f ExtensionField) IsSet() bool {
return f.typ != nil
}
// Deprecated: Do not use.
func (f ExtensionField) HasType() bool {
return f.typ != nil
}
// Deprecated: Do not use.
func (f ExtensionField) GetType() pref.ExtensionType {
return f.typ
}
// Deprecated: Do not use.
func (f *ExtensionField) SetType(t pref.ExtensionType) {
f.typ = t
}
// Deprecated: Do not use.
func (f ExtensionField) HasValue() bool {
return f.value.IsValid() || f.lazy != nil
}
// Deprecated: Do not use.
func (f ExtensionField) GetValue() interface{} {
return f.typ.InterfaceOf(f.Value())
}
// Deprecated: Do not use.
func (f *ExtensionField) SetEagerValue(ival interface{}) {
f.value = f.typ.ValueOf(ival)
}
// Deprecated: Do not use.
func (f *ExtensionField) SetLazyValue(fn func() interface{}) {
f.lazy = &lazyExtensionValue{value: func() interface{} {
return f.typ.ValueOf(fn())
}}
}
type lazyExtensionValue struct {
@ -128,14 +148,14 @@ type lazyExtensionValue struct {
value interface{} // either the value itself or a func() interface{}
}
func (v *lazyExtensionValue) GetValue() interface{} {
func (v *lazyExtensionValue) GetValue() pref.Value {
if atomic.LoadUint32(&v.once) == 0 {
v.mu.Lock()
if f, ok := v.value.(func() interface{}); ok {
if f, ok := v.value.(func() pref.Value); ok {
v.value = f()
}
atomic.StoreUint32(&v.once, 1)
v.mu.Unlock()
}
return v.value
return v.value.(pref.Value)
}

View File

@ -170,32 +170,55 @@ func consumeMessage(b []byte, m proto.Message, wtyp wire.Type, opts unmarshalOpt
return n, nil
}
func sizeMessageIface(ival interface{}, tagsize int, opts marshalOptions) int {
m := Export{}.MessageOf(ival).Interface()
func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int {
m := v.Message().Interface()
return sizeMessage(m, tagsize, opts)
}
func appendMessageIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
m := Export{}.MessageOf(ival).Interface()
func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
m := v.Message().Interface()
return appendMessage(b, m, wiretag, opts)
}
func consumeMessageIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
m := Export{}.MessageOf(ival).Interface()
func consumeMessageValue(b []byte, v pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
m := v.Message().Interface()
n, err := consumeMessage(b, m, wtyp, opts)
return ival, n, err
return v, n, err
}
func isInitMessageIface(ival interface{}) error {
m := Export{}.MessageOf(ival).Interface()
func isInitMessageValue(v pref.Value) error {
m := v.Message().Interface()
return proto.IsInitialized(m)
}
var coderMessageIface = ifaceCoderFuncs{
size: sizeMessageIface,
marshal: appendMessageIface,
unmarshal: consumeMessageIface,
isInit: isInitMessageIface,
var coderMessageValue = valueCoderFuncs{
size: sizeMessageValue,
marshal: appendMessageValue,
unmarshal: consumeMessageValue,
isInit: isInitMessageValue,
}
func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int {
m := v.Message().Interface()
return sizeGroup(m, tagsize, opts)
}
func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
m := v.Message().Interface()
return appendGroup(b, m, wiretag, opts)
}
func consumeGroupValue(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
m := v.Message().Interface()
n, err := consumeGroup(b, m, num, wtyp, opts)
return v, n, err
}
var coderGroupValue = valueCoderFuncs{
size: sizeGroupValue,
marshal: appendGroupValue,
unmarshal: consumeGroupValue,
isInit: isInitMessageValue,
}
func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
@ -283,25 +306,6 @@ func consumeGroup(b []byte, m proto.Message, num wire.Number, wtyp wire.Type, op
return n, opts.Options().Unmarshal(b, m)
}
func makeGroupValueCoder(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
return ifaceCoderFuncs{
size: func(ival interface{}, tagsize int, opts marshalOptions) int {
m := Export{}.MessageOf(ival).Interface()
return sizeGroup(m, tagsize, opts)
},
marshal: func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
m := Export{}.MessageOf(ival).Interface()
return appendGroup(b, m, wiretag, opts)
},
unmarshal: func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
m := Export{}.MessageOf(ival).Interface()
n, err := consumeGroup(b, m, num, wtyp, opts)
return ival, n, err
},
isInit: isInitMessageIface,
}
}
func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
if mi := getMessageInfo(ft); mi != nil {
return pointerCoderFuncs{
@ -441,32 +445,116 @@ func isInitMessageSlice(p pointer, goType reflect.Type) error {
// Slices of messages
func sizeMessageSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
p := pointerOfIface(ival)
return sizeMessageSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
list := listv.List()
n := 0
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
n += wire.SizeBytes(proto.Size(m)) + tagsize
}
return n
}
func appendMessageSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
p := pointerOfIface(ival)
return appendMessageSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
list := listv.List()
mopts := opts.Options()
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
b = wire.AppendVarint(b, wiretag)
siz := proto.Size(m)
b = wire.AppendVarint(b, uint64(siz))
var err error
b, err = mopts.MarshalAppend(b, m)
if err != nil {
return b, err
}
}
return b, nil
}
func consumeMessageSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
p := pointerOfIface(ival)
n, err := consumeMessageSlice(b, p, reflect.TypeOf(ival).Elem().Elem(), wtyp, opts)
return ival, n, err
func consumeMessageSliceValue(b []byte, listv pref.Value, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
list := listv.List()
if wtyp != wire.BytesType {
return pref.Value{}, 0, errUnknown
}
v, n := wire.ConsumeBytes(b)
if n < 0 {
return pref.Value{}, 0, wire.ParseError(n)
}
m := list.NewElement()
if err := opts.Options().Unmarshal(v, m.Message().Interface()); err != nil {
return pref.Value{}, 0, err
}
list.Append(m)
return listv, n, nil
}
func isInitMessageSliceIface(ival interface{}) error {
p := pointerOfIface(ival)
return isInitMessageSlice(p, reflect.TypeOf(ival).Elem().Elem())
func isInitMessageSliceValue(listv pref.Value) error {
list := listv.List()
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
if err := proto.IsInitialized(m); err != nil {
return err
}
}
return nil
}
var coderMessageSliceIface = ifaceCoderFuncs{
size: sizeMessageSliceIface,
marshal: appendMessageSliceIface,
unmarshal: consumeMessageSliceIface,
isInit: isInitMessageSliceIface,
var coderMessageSliceValue = valueCoderFuncs{
size: sizeMessageSliceValue,
marshal: appendMessageSliceValue,
unmarshal: consumeMessageSliceValue,
isInit: isInitMessageSliceValue,
}
func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int {
list := listv.List()
n := 0
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
n += 2*tagsize + proto.Size(m)
}
return n
}
func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
list := listv.List()
mopts := opts.Options()
for i, llen := 0, list.Len(); i < llen; i++ {
m := list.Get(i).Message().Interface()
b = wire.AppendVarint(b, wiretag) // start group
var err error
b, err = mopts.MarshalAppend(b, m)
if err != nil {
return b, err
}
b = wire.AppendVarint(b, wiretag+1) // end group
}
return b, nil
}
func consumeGroupSliceValue(b []byte, listv pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error) {
list := listv.List()
if wtyp != wire.StartGroupType {
return pref.Value{}, 0, errUnknown
}
b, n := wire.ConsumeGroup(num, b)
if n < 0 {
return pref.Value{}, 0, wire.ParseError(n)
}
m := list.NewElement()
if err := opts.Options().Unmarshal(b, m.Message().Interface()); err != nil {
return pref.Value{}, 0, err
}
list.Append(m)
return listv, n, nil
}
var coderGroupSliceValue = valueCoderFuncs{
size: sizeGroupSliceValue,
marshal: appendGroupSliceValue,
unmarshal: consumeGroupSliceValue,
isInit: isInitMessageSliceValue,
}
func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
@ -581,171 +669,6 @@ func consumeGroupSliceInfo(b []byte, p pointer, num wire.Number, wtyp wire.Type,
return n, nil
}
func sizeGroupSliceIface(ival interface{}, tagsize int, opts marshalOptions) int {
p := pointerOfIface(ival)
return sizeGroupSlice(p, reflect.TypeOf(ival).Elem().Elem(), tagsize, opts)
}
func appendGroupSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
p := pointerOfIface(ival)
return appendGroupSlice(b, p, wiretag, reflect.TypeOf(ival).Elem().Elem(), opts)
}
func consumeGroupSliceIface(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
p := pointerOfIface(ival)
n, err := consumeGroupSlice(b, p, num, wtyp, reflect.TypeOf(ival).Elem().Elem(), opts)
return ival, n, err
}
var coderGroupSliceIface = ifaceCoderFuncs{
size: sizeGroupSliceIface,
marshal: appendGroupSliceIface,
unmarshal: consumeGroupSliceIface,
isInit: isInitMessageSliceIface,
}
// Enums
func sizeEnumIface(ival interface{}, tagsize int, _ marshalOptions) (n int) {
v := reflect.ValueOf(ival).Int()
return wire.SizeVarint(uint64(v)) + tagsize
}
func appendEnumIface(b []byte, ival interface{}, wiretag uint64, _ marshalOptions) ([]byte, error) {
v := reflect.ValueOf(ival).Int()
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, uint64(v))
return b, nil
}
func consumeEnumIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, _ unmarshalOptions) (interface{}, int, error) {
if wtyp != wire.VarintType {
return nil, 0, errUnknown
}
v, n := wire.ConsumeVarint(b)
if n < 0 {
return nil, 0, wire.ParseError(n)
}
rv := reflect.New(reflect.TypeOf(ival)).Elem()
rv.SetInt(int64(v))
return rv.Interface(), n, nil
}
var coderEnumIface = ifaceCoderFuncs{
size: sizeEnumIface,
marshal: appendEnumIface,
unmarshal: consumeEnumIface,
}
func sizeEnumSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
return sizeEnumSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
}
func sizeEnumSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
for i, llen := 0, s.Len(); i < llen; i++ {
size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
}
return size
}
func appendEnumSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendEnumSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
}
func appendEnumSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
for i, llen := 0, s.Len(); i < llen; i++ {
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
}
return b, nil
}
func consumeEnumSliceIface(b []byte, ival interface{}, _ wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error) {
n, err := consumeEnumSliceReflect(b, reflect.ValueOf(ival), wtyp, opts)
return ival, n, err
}
func consumeEnumSliceReflect(b []byte, s reflect.Value, wtyp wire.Type, _ unmarshalOptions) (n int, err error) {
s = s.Elem() // *[]E -> []E
if wtyp == wire.BytesType {
b, n = wire.ConsumeBytes(b)
if n < 0 {
return 0, wire.ParseError(n)
}
for len(b) > 0 {
v, n := wire.ConsumeVarint(b)
if n < 0 {
return 0, wire.ParseError(n)
}
rv := reflect.New(s.Type().Elem()).Elem()
rv.SetInt(int64(v))
s.Set(reflect.Append(s, rv))
b = b[n:]
}
return n, nil
}
if wtyp != wire.VarintType {
return 0, errUnknown
}
v, n := wire.ConsumeVarint(b)
if n < 0 {
return 0, wire.ParseError(n)
}
rv := reflect.New(s.Type().Elem()).Elem()
rv.SetInt(int64(v))
s.Set(reflect.Append(s, rv))
return n, nil
}
var coderEnumSliceIface = ifaceCoderFuncs{
size: sizeEnumSliceIface,
marshal: appendEnumSliceIface,
unmarshal: consumeEnumSliceIface,
}
func sizeEnumPackedSliceIface(ival interface{}, tagsize int, opts marshalOptions) (size int) {
return sizeEnumPackedSliceReflect(reflect.ValueOf(ival).Elem(), tagsize, opts)
}
func sizeEnumPackedSliceReflect(s reflect.Value, tagsize int, _ marshalOptions) (size int) {
llen := s.Len()
if llen == 0 {
return 0
}
n := 0
for i := 0; i < llen; i++ {
n += wire.SizeVarint(uint64(s.Index(i).Int()))
}
return tagsize + wire.SizeBytes(n)
}
func appendEnumPackedSliceIface(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendEnumPackedSliceReflect(b, reflect.ValueOf(ival).Elem(), wiretag, opts)
}
func appendEnumPackedSliceReflect(b []byte, s reflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) {
llen := s.Len()
if llen == 0 {
return b, nil
}
b = wire.AppendVarint(b, wiretag)
n := 0
for i := 0; i < llen; i++ {
n += wire.SizeVarint(uint64(s.Index(i).Int()))
}
b = wire.AppendVarint(b, uint64(n))
for i := 0; i < llen; i++ {
b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
}
return b, nil
}
var coderEnumPackedSliceIface = ifaceCoderFuncs{
size: sizeEnumPackedSliceIface,
marshal: appendEnumPackedSliceIface,
unmarshal: consumeEnumSliceIface,
}
func asMessage(v reflect.Value) pref.ProtoMessage {
if m, ok := v.Interface().(pref.ProtoMessage); ok {
return m

File diff suppressed because it is too large Load Diff

View File

@ -5,11 +5,10 @@
package impl
import (
"fmt"
"reflect"
"sort"
"google.golang.org/protobuf/internal/encoding/wire"
"google.golang.org/protobuf/internal/mapsort"
pref "google.golang.org/protobuf/reflect/protoreflect"
)
@ -17,11 +16,10 @@ type mapInfo struct {
goType reflect.Type
keyWiretag uint64
valWiretag uint64
keyFuncs ifaceCoderFuncs
valFuncs ifaceCoderFuncs
keyZero interface{}
valZero interface{}
newVal func() interface{}
keyFuncs valueCoderFuncs
valFuncs valueCoderFuncs
keyZero pref.Value
keyKind pref.Kind
}
func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (funcs pointerCoderFuncs) {
@ -32,6 +30,7 @@ func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (funcs pointer
valWiretag := wire.EncodeTag(2, wireTypes[valField.Kind()])
keyFuncs := encoderFuncsForValue(keyField, ft.Key())
valFuncs := encoderFuncsForValue(valField, ft.Elem())
conv := NewConverter(ft, fd)
mapi := &mapInfo{
goType: ft,
@ -39,30 +38,32 @@ func encoderFuncsForMap(fd pref.FieldDescriptor, ft reflect.Type) (funcs pointer
valWiretag: valWiretag,
keyFuncs: keyFuncs,
valFuncs: valFuncs,
keyZero: reflect.Zero(ft.Key()).Interface(),
valZero: reflect.Zero(ft.Elem()).Interface(),
}
switch valField.Kind() {
case pref.GroupKind, pref.MessageKind:
mapi.newVal = func() interface{} {
return reflect.New(ft.Elem().Elem()).Interface()
}
keyZero: keyField.Default(),
keyKind: keyField.Kind(),
}
funcs = pointerCoderFuncs{
size: func(p pointer, tagsize int, opts marshalOptions) int {
return sizeMap(p, tagsize, ft, keyFuncs, valFuncs, opts)
mapv := conv.PBValueOf(p.AsValueOf(ft).Elem()).Map()
return sizeMap(mapv, tagsize, mapi, opts)
},
marshal: func(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendMap(b, p, wiretag, keyWiretag, valWiretag, ft, keyFuncs, valFuncs, opts)
mapv := conv.PBValueOf(p.AsValueOf(ft).Elem()).Map()
return appendMap(b, mapv, wiretag, mapi, opts)
},
unmarshal: func(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (int, error) {
return consumeMap(b, p, wtyp, mapi, opts)
mp := p.AsValueOf(ft)
if mp.Elem().IsNil() {
mp.Elem().Set(reflect.MakeMap(mapi.goType))
}
mapv := conv.PBValueOf(mp.Elem()).Map()
return consumeMap(b, mapv, wtyp, mapi, opts)
},
}
if valFuncs.isInit != nil {
funcs.isInit = func(p pointer) error {
return isInitMap(p, ft, valFuncs.isInit)
mapv := conv.PBValueOf(p.AsValueOf(ft).Elem()).Map()
return isInitMap(mapv, mapi)
}
}
return funcs
@ -73,13 +74,21 @@ const (
mapValTagSize = 1 // field 2, tag size 2.
)
func consumeMap(b []byte, p pointer, wtyp wire.Type, mapi *mapInfo, opts unmarshalOptions) (int, error) {
mp := p.AsValueOf(mapi.goType)
if mp.Elem().IsNil() {
mp.Elem().Set(reflect.MakeMap(mapi.goType))
func sizeMap(mapv pref.Map, tagsize int, mapi *mapInfo, opts marshalOptions) int {
if mapv.Len() == 0 {
return 0
}
m := mp.Elem()
n := 0
mapv.Range(func(key pref.MapKey, value pref.Value) bool {
n += tagsize + wire.SizeBytes(
mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)+
mapi.valFuncs.size(value, mapValTagSize, opts))
return true
})
return n
}
func consumeMap(b []byte, mapv pref.Map, wtyp wire.Type, mapi *mapInfo, opts unmarshalOptions) (int, error) {
if wtyp != wire.BytesType {
return 0, errUnknown
}
@ -89,11 +98,8 @@ func consumeMap(b []byte, p pointer, wtyp wire.Type, mapi *mapInfo, opts unmarsh
}
var (
key = mapi.keyZero
val = mapi.valZero
val = mapv.NewValue()
)
if mapi.newVal != nil {
val = mapi.newVal()
}
for len(b) > 0 {
num, wtyp, n := wire.ConsumeTag(b)
if n < 0 {
@ -103,14 +109,14 @@ func consumeMap(b []byte, p pointer, wtyp wire.Type, mapi *mapInfo, opts unmarsh
err := errUnknown
switch num {
case 1:
var v interface{}
var v pref.Value
v, n, err = mapi.keyFuncs.unmarshal(b, key, num, wtyp, opts)
if err != nil {
break
}
key = v
case 2:
var v interface{}
var v pref.Value
v, n, err = mapi.valFuncs.unmarshal(b, val, num, wtyp, opts)
if err != nil {
break
@ -127,119 +133,44 @@ func consumeMap(b []byte, p pointer, wtyp wire.Type, mapi *mapInfo, opts unmarsh
}
b = b[n:]
}
m.SetMapIndex(reflect.ValueOf(key), reflect.ValueOf(val))
mapv.Set(key.MapKey(), val)
return n, nil
}
func sizeMap(p pointer, tagsize int, goType reflect.Type, keyFuncs, valFuncs ifaceCoderFuncs, opts marshalOptions) int {
m := p.AsValueOf(goType).Elem()
n := 0
if m.Len() == 0 {
return 0
func appendMap(b []byte, mapv pref.Map, wiretag uint64, mapi *mapInfo, opts marshalOptions) ([]byte, error) {
if mapv.Len() == 0 {
return b, nil
}
iter := mapRange(m)
for iter.Next() {
ki := iter.Key().Interface()
vi := iter.Value().Interface()
size := keyFuncs.size(ki, mapKeyTagSize, opts) + valFuncs.size(vi, mapValTagSize, opts)
n += wire.SizeBytes(size) + tagsize
}
return n
}
func appendMap(b []byte, p pointer, wiretag, keyWiretag, valWiretag uint64, goType reflect.Type, keyFuncs, valFuncs ifaceCoderFuncs, opts marshalOptions) ([]byte, error) {
m := p.AsValueOf(goType).Elem()
var err error
if m.Len() == 0 {
return b, nil
}
if opts.Deterministic() {
keys := m.MapKeys()
sort.Sort(mapKeys(keys))
for _, k := range keys {
b, err = appendMapElement(b, k, m.MapIndex(k), wiretag, keyWiretag, valWiretag, keyFuncs, valFuncs, opts)
if err != nil {
return b, err
}
}
return b, nil
}
iter := mapRange(m)
for iter.Next() {
b, err = appendMapElement(b, iter.Key(), iter.Value(), wiretag, keyWiretag, valWiretag, keyFuncs, valFuncs, opts)
fn := func(key pref.MapKey, value pref.Value) bool {
b = wire.AppendVarint(b, wiretag)
size := 0
size += mapi.keyFuncs.size(key.Value(), mapKeyTagSize, opts)
size += mapi.valFuncs.size(value, mapValTagSize, opts)
b = wire.AppendVarint(b, uint64(size))
b, err = mapi.keyFuncs.marshal(b, key.Value(), mapi.keyWiretag, opts)
if err != nil {
return b, err
return false
}
}
return b, nil
}
func appendMapElement(b []byte, key, value reflect.Value, wiretag, keyWiretag, valWiretag uint64, keyFuncs, valFuncs ifaceCoderFuncs, opts marshalOptions) ([]byte, error) {
ki := key.Interface()
vi := value.Interface()
b = wire.AppendVarint(b, wiretag)
size := keyFuncs.size(ki, mapKeyTagSize, opts) + valFuncs.size(vi, mapValTagSize, opts)
b = wire.AppendVarint(b, uint64(size))
b, err := keyFuncs.marshal(b, ki, keyWiretag, opts)
if err != nil {
return b, err
}
b, err = valFuncs.marshal(b, vi, valWiretag, opts)
if err != nil {
return b, err
}
return b, nil
}
func isInitMap(p pointer, goType reflect.Type, isInit func(interface{}) error) error {
m := p.AsValueOf(goType).Elem()
if m.Len() == 0 {
return nil
}
iter := mapRange(m)
for iter.Next() {
if err := isInit(iter.Value().Interface()); err != nil {
return err
b, err = mapi.valFuncs.marshal(b, value, mapi.valWiretag, opts)
if err != nil {
return false
}
return true
}
return nil
}
// mapKeys returns a sort.Interface to be used for sorting the map keys.
// Map fields may have key types of non-float scalars, strings and enums.
func mapKeys(vs []reflect.Value) sort.Interface {
s := mapKeySorter{vs: vs}
// Type specialization per https://developers.google.com/protocol-buffers/docs/proto#maps.
if len(vs) == 0 {
return s
if opts.Deterministic() {
mapsort.Range(mapv, mapi.keyKind, fn)
} else {
mapv.Range(fn)
}
switch vs[0].Kind() {
case reflect.Int32, reflect.Int64:
s.less = func(a, b reflect.Value) bool { return a.Int() < b.Int() }
case reflect.Uint32, reflect.Uint64:
s.less = func(a, b reflect.Value) bool { return a.Uint() < b.Uint() }
case reflect.Bool:
s.less = func(a, b reflect.Value) bool { return !a.Bool() && b.Bool() } // false < true
case reflect.String:
s.less = func(a, b reflect.Value) bool { return a.String() < b.String() }
default:
panic(fmt.Sprintf("unsupported map key type: %v", vs[0].Kind()))
}
return s
return b, err
}
type mapKeySorter struct {
vs []reflect.Value
less func(a, b reflect.Value) bool
}
func (s mapKeySorter) Len() int { return len(s.vs) }
func (s mapKeySorter) Swap(i, j int) { s.vs[i], s.vs[j] = s.vs[j], s.vs[i] }
func (s mapKeySorter) Less(i, j int) bool {
return s.less(s.vs[i], s.vs[j])
func isInitMap(mapv pref.Map, mapi *mapInfo) error {
var err error
mapv.Range(func(_ pref.MapKey, value pref.Value) bool {
err = mapi.valFuncs.isInit(value)
return err == nil
})
return err
}

View File

@ -39,7 +39,7 @@ func sizeMessageSet(mi *MessageInfo, p pointer, tagsize int, opts marshalOptions
}
num, _ := wire.DecodeTag(xi.wiretag)
n += messageset.SizeField(num)
n += xi.funcs.size(x.GetValue(), wire.SizeTag(messageset.FieldMessage), opts)
n += xi.funcs.size(x.Value(), wire.SizeTag(messageset.FieldMessage), opts)
}
return n
}
@ -88,7 +88,7 @@ func marshalMessageSetField(mi *MessageInfo, b []byte, x ExtensionField, opts ma
xi := mi.extensionFieldInfo(x.GetType())
num, _ := wire.DecodeTag(xi.wiretag)
b = messageset.AppendFieldStart(b, num)
b, err := xi.funcs.marshal(b, x.GetValue(), wire.EncodeTag(messageset.FieldMessage, wire.BytesType), opts)
b, err := xi.funcs.marshal(b, x.Value(), wire.EncodeTag(messageset.FieldMessage, wire.BytesType), opts)
if err != nil {
return b, err
}

View File

@ -87,15 +87,52 @@ var coderEnumPtr = pointerCoderFuncs{
}
func sizeEnumSlice(p pointer, tagsize int, opts marshalOptions) (size int) {
return sizeEnumSliceReflect(p.v.Elem(), tagsize, opts)
s := p.v.Elem()
for i, llen := 0, s.Len(); i < llen; i++ {
size += wire.SizeVarint(uint64(s.Index(i).Int())) + tagsize
}
return size
}
func appendEnumSlice(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendEnumSliceReflect(b, p.v.Elem(), wiretag, opts)
s := p.v.Elem()
for i, llen := 0, s.Len(); i < llen; i++ {
b = wire.AppendVarint(b, wiretag)
b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
}
return b, nil
}
func consumeEnumSlice(b []byte, p pointer, wtyp wire.Type, opts unmarshalOptions) (n int, err error) {
return consumeEnumSliceReflect(b, p.v, wtyp, opts)
s := p.v.Elem()
if wtyp == wire.BytesType {
b, n = wire.ConsumeBytes(b)
if n < 0 {
return 0, wire.ParseError(n)
}
for len(b) > 0 {
v, n := wire.ConsumeVarint(b)
if n < 0 {
return 0, wire.ParseError(n)
}
rv := reflect.New(s.Type().Elem()).Elem()
rv.SetInt(int64(v))
s.Set(reflect.Append(s, rv))
b = b[n:]
}
return n, nil
}
if wtyp != wire.VarintType {
return 0, errUnknown
}
v, n := wire.ConsumeVarint(b)
if n < 0 {
return 0, wire.ParseError(n)
}
rv := reflect.New(s.Type().Elem()).Elem()
rv.SetInt(int64(v))
s.Set(reflect.Append(s, rv))
return n, nil
}
var coderEnumSlice = pointerCoderFuncs{
@ -105,11 +142,34 @@ var coderEnumSlice = pointerCoderFuncs{
}
func sizeEnumPackedSlice(p pointer, tagsize int, opts marshalOptions) (size int) {
return sizeEnumPackedSliceReflect(p.v.Elem(), tagsize, opts)
s := p.v.Elem()
llen := s.Len()
if llen == 0 {
return 0
}
n := 0
for i := 0; i < llen; i++ {
n += wire.SizeVarint(uint64(s.Index(i).Int()))
}
return tagsize + wire.SizeBytes(n)
}
func appendEnumPackedSlice(b []byte, p pointer, wiretag uint64, opts marshalOptions) ([]byte, error) {
return appendEnumPackedSliceReflect(b, p.v.Elem(), wiretag, opts)
s := p.v.Elem()
llen := s.Len()
if llen == 0 {
return b, nil
}
b = wire.AppendVarint(b, wiretag)
n := 0
for i := 0; i < llen; i++ {
n += wire.SizeVarint(uint64(s.Index(i).Int()))
}
b = wire.AppendVarint(b, uint64(n))
for i := 0; i < llen; i++ {
b = wire.AppendVarint(b, uint64(s.Index(i).Int()))
}
return b, nil
}
var coderEnumPackedSlice = pointerCoderFuncs{

View File

@ -21,12 +21,12 @@ type pointerCoderFuncs struct {
isInit func(p pointer) error
}
// ifaceCoderFuncs is a set of interface{} encoding functions.
type ifaceCoderFuncs struct {
size func(ival interface{}, tagsize int, opts marshalOptions) int
marshal func(b []byte, ival interface{}, wiretag uint64, opts marshalOptions) ([]byte, error)
unmarshal func(b []byte, ival interface{}, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (interface{}, int, error)
isInit func(ival interface{}) error
// valueCoderFuncs is a set of protoreflect.Value encoding functions.
type valueCoderFuncs struct {
size func(v pref.Value, tagsize int, opts marshalOptions) int
marshal func(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error)
unmarshal func(b []byte, v pref.Value, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (pref.Value, int, error)
isInit func(v pref.Value) error
}
// fieldCoder returns pointer functions for a field, used for operating on
@ -428,7 +428,7 @@ func fieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs {
// encoderFuncsForValue returns interface{} value functions for a field, used for
// extension values and map encoding.
func encoderFuncsForValue(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFuncs {
func encoderFuncsForValue(fd pref.FieldDescriptor, ft reflect.Type) valueCoderFuncs {
switch {
case fd.Cardinality() == pref.Repeated && !fd.IsPacked():
if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
@ -438,78 +438,78 @@ func encoderFuncsForValue(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFu
switch fd.Kind() {
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBoolSliceIface
return coderBoolSliceValue
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnumSliceIface
return coderEnumSliceValue
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32SliceIface
return coderInt32SliceValue
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32SliceIface
return coderSint32SliceValue
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32SliceIface
return coderUint32SliceValue
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64SliceIface
return coderInt64SliceValue
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64SliceIface
return coderSint64SliceValue
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64SliceIface
return coderUint64SliceValue
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32SliceIface
return coderSfixed32SliceValue
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32SliceIface
return coderFixed32SliceValue
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloatSliceIface
return coderFloatSliceValue
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64SliceIface
return coderSfixed64SliceValue
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64SliceIface
return coderFixed64SliceValue
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDoubleSliceIface
return coderDoubleSliceValue
}
case pref.StringKind:
if ft.Kind() == reflect.String {
return coderStringSliceIface
return coderStringSliceValue
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesSliceIface
return coderBytesSliceValue
}
case pref.BytesKind:
if ft.Kind() == reflect.String {
return coderStringSliceIface
return coderStringSliceValue
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesSliceIface
return coderBytesSliceValue
}
case pref.MessageKind:
return coderMessageSliceIface
return coderMessageSliceValue
case pref.GroupKind:
return coderGroupSliceIface
return coderGroupSliceValue
}
case fd.Cardinality() == pref.Repeated && fd.IsPacked():
if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
@ -519,143 +519,144 @@ func encoderFuncsForValue(fd pref.FieldDescriptor, ft reflect.Type) ifaceCoderFu
switch fd.Kind() {
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBoolPackedSliceIface
return coderBoolPackedSliceValue
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnumPackedSliceIface
return coderEnumPackedSliceValue
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32PackedSliceIface
return coderInt32PackedSliceValue
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32PackedSliceIface
return coderSint32PackedSliceValue
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32PackedSliceIface
return coderUint32PackedSliceValue
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64PackedSliceIface
return coderInt64PackedSliceValue
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64PackedSliceIface
return coderSint64PackedSliceValue
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64PackedSliceIface
return coderUint64PackedSliceValue
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32PackedSliceIface
return coderSfixed32PackedSliceValue
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32PackedSliceIface
return coderFixed32PackedSliceValue
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloatPackedSliceIface
return coderFloatPackedSliceValue
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64PackedSliceIface
return coderSfixed64PackedSliceValue
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64PackedSliceIface
return coderFixed64PackedSliceValue
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDoublePackedSliceIface
return coderDoublePackedSliceValue
}
}
default:
switch fd.Kind() {
default:
case pref.BoolKind:
if ft.Kind() == reflect.Bool {
return coderBoolIface
return coderBoolValue
}
case pref.EnumKind:
if ft.Kind() == reflect.Int32 {
return coderEnumIface
return coderEnumValue
}
case pref.Int32Kind:
if ft.Kind() == reflect.Int32 {
return coderInt32Iface
return coderInt32Value
}
case pref.Sint32Kind:
if ft.Kind() == reflect.Int32 {
return coderSint32Iface
return coderSint32Value
}
case pref.Uint32Kind:
if ft.Kind() == reflect.Uint32 {
return coderUint32Iface
return coderUint32Value
}
case pref.Int64Kind:
if ft.Kind() == reflect.Int64 {
return coderInt64Iface
return coderInt64Value
}
case pref.Sint64Kind:
if ft.Kind() == reflect.Int64 {
return coderSint64Iface
return coderSint64Value
}
case pref.Uint64Kind:
if ft.Kind() == reflect.Uint64 {
return coderUint64Iface
return coderUint64Value
}
case pref.Sfixed32Kind:
if ft.Kind() == reflect.Int32 {
return coderSfixed32Iface
return coderSfixed32Value
}
case pref.Fixed32Kind:
if ft.Kind() == reflect.Uint32 {
return coderFixed32Iface
return coderFixed32Value
}
case pref.FloatKind:
if ft.Kind() == reflect.Float32 {
return coderFloatIface
return coderFloatValue
}
case pref.Sfixed64Kind:
if ft.Kind() == reflect.Int64 {
return coderSfixed64Iface
return coderSfixed64Value
}
case pref.Fixed64Kind:
if ft.Kind() == reflect.Uint64 {
return coderFixed64Iface
return coderFixed64Value
}
case pref.DoubleKind:
if ft.Kind() == reflect.Float64 {
return coderDoubleIface
return coderDoubleValue
}
case pref.StringKind:
if ft.Kind() == reflect.String && strs.EnforceUTF8(fd) {
return coderStringIfaceValidateUTF8
return coderStringValueValidateUTF8
}
if ft.Kind() == reflect.String {
return coderStringIface
return coderStringValue
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 && strs.EnforceUTF8(fd) {
return coderBytesIfaceValidateUTF8
return coderBytesValueValidateUTF8
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesIface
return coderBytesValue
}
case pref.BytesKind:
if ft.Kind() == reflect.String {
return coderStringIface
return coderStringValue
}
if ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8 {
return coderBytesIface
return coderBytesValue
}
case pref.MessageKind:
return coderMessageIface
return coderMessageValue
case pref.GroupKind:
return makeGroupValueCoder(fd, ft)
return coderGroupValue
}
}
panic(fmt.Errorf("invalid type: no encoder for %v %v %v/%v", fd.FullName(), fd.Cardinality(), fd.Kind(), ft))

View File

@ -90,13 +90,12 @@ func (ms *mapReflect) Clear(k pref.MapKey) {
ms.v.SetMapIndex(rk, reflect.Value{})
}
func (ms *mapReflect) Range(f func(pref.MapKey, pref.Value) bool) {
for _, k := range ms.v.MapKeys() {
if v := ms.v.MapIndex(k); v.IsValid() {
pk := ms.keyConv.PBValueOf(k).MapKey()
pv := ms.valConv.PBValueOf(v)
if !f(pk, pv) {
return
}
iter := mapRange(ms.v)
for iter.Next() {
k := ms.keyConv.PBValueOf(iter.Key()).MapKey()
v := ms.valConv.PBValueOf(iter.Value())
if !f(k, v) {
return
}
}
}

View File

@ -145,24 +145,23 @@ func (mi *MessageInfo) unmarshalExtension(b []byte, num wire.Number, wtyp wire.T
}
return 0, err
}
x.SetType(xt)
}
xi := mi.extensionFieldInfo(xt)
if xi.funcs.unmarshal == nil {
return 0, errUnknown
}
ival := x.GetValue()
if ival == nil && xi.unmarshalNeedsValue {
ival := x.Value()
if !ival.IsValid() && xi.unmarshalNeedsValue {
// Create a new message, list, or map value to fill in.
// For enums, create a prototype value to let the unmarshal func know the
// concrete type.
ival = xt.InterfaceOf(xt.New())
ival = xt.New()
}
v, n, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
if err != nil {
return 0, err
}
x.SetEagerValue(v)
x.Set(xt, v)
exts[int32(num)] = x
return n, nil
}

View File

@ -144,11 +144,11 @@ func (mi *MessageInfo) sizeExtensions(ext *map[int32]ExtensionField, opts marsha
return 0
}
for _, x := range *ext {
xi := mi.extensionFieldInfo(x.GetType())
xi := mi.extensionFieldInfo(x.Type())
if xi.funcs.size == nil {
continue
}
n += xi.funcs.size(x.GetValue(), xi.tagsize, opts)
n += xi.funcs.size(x.Value(), xi.tagsize, opts)
}
return n
}
@ -165,8 +165,8 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField,
// Fast-path for one extension: Don't bother sorting the keys.
var err error
for _, x := range *ext {
xi := mi.extensionFieldInfo(x.GetType())
b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts)
xi := mi.extensionFieldInfo(x.Type())
b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
}
return b, err
default:
@ -180,8 +180,8 @@ func (mi *MessageInfo) appendExtensions(b []byte, ext *map[int32]ExtensionField,
var err error
for _, k := range keys {
x := (*ext)[int32(k)]
xi := mi.extensionFieldInfo(x.GetType())
b, err = xi.funcs.marshal(b, x.GetValue(), xi.wiretag, opts)
xi := mi.extensionFieldInfo(x.Type())
b, err = xi.funcs.marshal(b, x.Value(), xi.wiretag, opts)
if err != nil {
return b, err
}

View File

@ -66,12 +66,12 @@ func (mi *MessageInfo) isInitExtensions(ext *map[int32]ExtensionField) error {
return nil
}
for _, x := range *ext {
ei := mi.extensionFieldInfo(x.GetType())
ei := mi.extensionFieldInfo(x.Type())
if ei.funcs.isInit == nil {
continue
}
v := x.GetValue()
if v == nil {
v := x.Value()
if !v.IsValid() {
continue
}
if err := ei.funcs.isInit(v); err != nil {

View File

@ -119,7 +119,7 @@ func (m *extensionMap) Range(f func(pref.FieldDescriptor, pref.Value) bool) {
if m != nil {
for _, x := range *m {
xt := x.GetType()
if !f(xt.TypeDescriptor(), xt.ValueOf(x.GetValue())) {
if !f(xt.TypeDescriptor(), x.Value()) {
return
}
}
@ -138,18 +138,20 @@ func (m *extensionMap) Get(xt pref.ExtensionType) pref.Value {
xd := xt.TypeDescriptor()
if m != nil {
if x, ok := (*m)[int32(xd.Number())]; ok {
return xt.ValueOf(x.GetValue())
return x.Value()
}
}
return xt.Zero()
}
func (m *extensionMap) Set(xt pref.ExtensionType, v pref.Value) {
if !xt.IsValidValue(v) {
panic(fmt.Errorf("%v: assigning invalid value", xt.TypeDescriptor().FullName()))
}
if *m == nil {
*m = make(map[int32]ExtensionField)
}
var x ExtensionField
x.SetType(xt)
x.SetEagerValue(xt.InterfaceOf(v))
x.Set(xt, v)
(*m)[int32(xt.TypeDescriptor().Number())] = x
}
func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value {
@ -158,7 +160,7 @@ func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value {
panic("invalid Mutable on field with non-composite type")
}
if x, ok := (*m)[int32(xd.Number())]; ok {
return xt.ValueOf(x.GetValue())
return x.Value()
}
v := xt.New()
m.Set(xt, v)