mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-04-09 21:44:37 +00:00
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:
parent
835b271169
commit
68b81c3117
@ -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.
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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{
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user