vendor/google.golang.org/protobuf/internal/impl/codec_extension.go
changeset 260 445e01aede7e
parent 256 6d9efbef00a9
equal deleted inserted replaced
259:db4911b0c721 260:445e01aede7e
     8 	"sync"
     8 	"sync"
     9 	"sync/atomic"
     9 	"sync/atomic"
    10 
    10 
    11 	"google.golang.org/protobuf/encoding/protowire"
    11 	"google.golang.org/protobuf/encoding/protowire"
    12 	"google.golang.org/protobuf/internal/errors"
    12 	"google.golang.org/protobuf/internal/errors"
    13 	pref "google.golang.org/protobuf/reflect/protoreflect"
    13 	"google.golang.org/protobuf/reflect/protoreflect"
    14 )
    14 )
    15 
    15 
    16 type extensionFieldInfo struct {
    16 type extensionFieldInfo struct {
    17 	wiretag             uint64
    17 	wiretag             uint64
    18 	tagsize             int
    18 	tagsize             int
    21 	validation          validationInfo
    21 	validation          validationInfo
    22 }
    22 }
    23 
    23 
    24 var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo
    24 var legacyExtensionFieldInfoCache sync.Map // map[protoreflect.ExtensionType]*extensionFieldInfo
    25 
    25 
    26 func getExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
    26 func getExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo {
    27 	if xi, ok := xt.(*ExtensionInfo); ok {
    27 	if xi, ok := xt.(*ExtensionInfo); ok {
    28 		xi.lazyInit()
    28 		xi.lazyInit()
    29 		return xi.info
    29 		return xi.info
    30 	}
    30 	}
    31 	return legacyLoadExtensionFieldInfo(xt)
    31 	return legacyLoadExtensionFieldInfo(xt)
    32 }
    32 }
    33 
    33 
    34 // legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt.
    34 // legacyLoadExtensionFieldInfo dynamically loads a *ExtensionInfo for xt.
    35 func legacyLoadExtensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
    35 func legacyLoadExtensionFieldInfo(xt protoreflect.ExtensionType) *extensionFieldInfo {
    36 	if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok {
    36 	if xi, ok := legacyExtensionFieldInfoCache.Load(xt); ok {
    37 		return xi.(*extensionFieldInfo)
    37 		return xi.(*extensionFieldInfo)
    38 	}
    38 	}
    39 	e := makeExtensionFieldInfo(xt.TypeDescriptor())
    39 	e := makeExtensionFieldInfo(xt.TypeDescriptor())
    40 	if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok {
    40 	if e, ok := legacyMessageTypeCache.LoadOrStore(xt, e); ok {
    41 		return e.(*extensionFieldInfo)
    41 		return e.(*extensionFieldInfo)
    42 	}
    42 	}
    43 	return e
    43 	return e
    44 }
    44 }
    45 
    45 
    46 func makeExtensionFieldInfo(xd pref.ExtensionDescriptor) *extensionFieldInfo {
    46 func makeExtensionFieldInfo(xd protoreflect.ExtensionDescriptor) *extensionFieldInfo {
    47 	var wiretag uint64
    47 	var wiretag uint64
    48 	if !xd.IsPacked() {
    48 	if !xd.IsPacked() {
    49 		wiretag = protowire.EncodeTag(xd.Number(), wireTypes[xd.Kind()])
    49 		wiretag = protowire.EncodeTag(xd.Number(), wireTypes[xd.Kind()])
    50 	} else {
    50 	} else {
    51 		wiretag = protowire.EncodeTag(xd.Number(), protowire.BytesType)
    51 		wiretag = protowire.EncodeTag(xd.Number(), protowire.BytesType)
    57 	}
    57 	}
    58 	// Does the unmarshal function need a value passed to it?
    58 	// Does the unmarshal function need a value passed to it?
    59 	// This is true for composite types, where we pass in a message, list, or map to fill in,
    59 	// This is true for composite types, where we pass in a message, list, or map to fill in,
    60 	// and for enums, where we pass in a prototype value to specify the concrete enum type.
    60 	// and for enums, where we pass in a prototype value to specify the concrete enum type.
    61 	switch xd.Kind() {
    61 	switch xd.Kind() {
    62 	case pref.MessageKind, pref.GroupKind, pref.EnumKind:
    62 	case protoreflect.MessageKind, protoreflect.GroupKind, protoreflect.EnumKind:
    63 		e.unmarshalNeedsValue = true
    63 		e.unmarshalNeedsValue = true
    64 	default:
    64 	default:
    65 		if xd.Cardinality() == pref.Repeated {
    65 		if xd.Cardinality() == protoreflect.Repeated {
    66 			e.unmarshalNeedsValue = true
    66 			e.unmarshalNeedsValue = true
    67 		}
    67 		}
    68 	}
    68 	}
    69 	return e
    69 	return e
    70 }
    70 }
    71 
    71 
    72 type lazyExtensionValue struct {
    72 type lazyExtensionValue struct {
    73 	atomicOnce uint32 // atomically set if value is valid
    73 	atomicOnce uint32 // atomically set if value is valid
    74 	mu         sync.Mutex
    74 	mu         sync.Mutex
    75 	xi         *extensionFieldInfo
    75 	xi         *extensionFieldInfo
    76 	value      pref.Value
    76 	value      protoreflect.Value
    77 	b          []byte
    77 	b          []byte
    78 	fn         func() pref.Value
    78 	fn         func() protoreflect.Value
    79 }
    79 }
    80 
    80 
    81 type ExtensionField struct {
    81 type ExtensionField struct {
    82 	typ pref.ExtensionType
    82 	typ protoreflect.ExtensionType
    83 
    83 
    84 	// value is either the value of GetValue,
    84 	// value is either the value of GetValue,
    85 	// or a *lazyExtensionValue that then returns the value of GetValue.
    85 	// or a *lazyExtensionValue that then returns the value of GetValue.
    86 	value pref.Value
    86 	value protoreflect.Value
    87 	lazy  *lazyExtensionValue
    87 	lazy  *lazyExtensionValue
    88 }
    88 }
    89 
    89 
    90 func (f *ExtensionField) appendLazyBytes(xt pref.ExtensionType, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, b []byte) {
    90 func (f *ExtensionField) appendLazyBytes(xt protoreflect.ExtensionType, xi *extensionFieldInfo, num protowire.Number, wtyp protowire.Type, b []byte) {
    91 	if f.lazy == nil {
    91 	if f.lazy == nil {
    92 		f.lazy = &lazyExtensionValue{xi: xi}
    92 		f.lazy = &lazyExtensionValue{xi: xi}
    93 	}
    93 	}
    94 	f.typ = xt
    94 	f.typ = xt
    95 	f.lazy.xi = xi
    95 	f.lazy.xi = xi
    96 	f.lazy.b = protowire.AppendTag(f.lazy.b, num, wtyp)
    96 	f.lazy.b = protowire.AppendTag(f.lazy.b, num, wtyp)
    97 	f.lazy.b = append(f.lazy.b, b...)
    97 	f.lazy.b = append(f.lazy.b, b...)
    98 }
    98 }
    99 
    99 
   100 func (f *ExtensionField) canLazy(xt pref.ExtensionType) bool {
   100 func (f *ExtensionField) canLazy(xt protoreflect.ExtensionType) bool {
   101 	if f.typ == nil {
   101 	if f.typ == nil {
   102 		return true
   102 		return true
   103 	}
   103 	}
   104 	if f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 {
   104 	if f.typ == xt && f.lazy != nil && atomic.LoadUint32(&f.lazy.atomicOnce) == 0 {
   105 		return true
   105 		return true
   152 	atomic.StoreUint32(&f.lazy.atomicOnce, 1)
   152 	atomic.StoreUint32(&f.lazy.atomicOnce, 1)
   153 }
   153 }
   154 
   154 
   155 // Set sets the type and value of the extension field.
   155 // Set sets the type and value of the extension field.
   156 // This must not be called concurrently.
   156 // This must not be called concurrently.
   157 func (f *ExtensionField) Set(t pref.ExtensionType, v pref.Value) {
   157 func (f *ExtensionField) Set(t protoreflect.ExtensionType, v protoreflect.Value) {
   158 	f.typ = t
   158 	f.typ = t
   159 	f.value = v
   159 	f.value = v
   160 	f.lazy = nil
   160 	f.lazy = nil
   161 }
   161 }
   162 
   162 
   163 // SetLazy sets the type and a value that is to be lazily evaluated upon first use.
   163 // SetLazy sets the type and a value that is to be lazily evaluated upon first use.
   164 // This must not be called concurrently.
   164 // This must not be called concurrently.
   165 func (f *ExtensionField) SetLazy(t pref.ExtensionType, fn func() pref.Value) {
   165 func (f *ExtensionField) SetLazy(t protoreflect.ExtensionType, fn func() protoreflect.Value) {
   166 	f.typ = t
   166 	f.typ = t
   167 	f.lazy = &lazyExtensionValue{fn: fn}
   167 	f.lazy = &lazyExtensionValue{fn: fn}
   168 }
   168 }
   169 
   169 
   170 // Value returns the value of the extension field.
   170 // Value returns the value of the extension field.
   171 // This may be called concurrently.
   171 // This may be called concurrently.
   172 func (f *ExtensionField) Value() pref.Value {
   172 func (f *ExtensionField) Value() protoreflect.Value {
   173 	if f.lazy != nil {
   173 	if f.lazy != nil {
   174 		if atomic.LoadUint32(&f.lazy.atomicOnce) == 0 {
   174 		if atomic.LoadUint32(&f.lazy.atomicOnce) == 0 {
   175 			f.lazyInit()
   175 			f.lazyInit()
   176 		}
   176 		}
   177 		return f.lazy.value
   177 		return f.lazy.value
   179 	return f.value
   179 	return f.value
   180 }
   180 }
   181 
   181 
   182 // Type returns the type of the extension field.
   182 // Type returns the type of the extension field.
   183 // This may be called concurrently.
   183 // This may be called concurrently.
   184 func (f ExtensionField) Type() pref.ExtensionType {
   184 func (f ExtensionField) Type() protoreflect.ExtensionType {
   185 	return f.typ
   185 	return f.typ
   186 }
   186 }
   187 
   187 
   188 // IsSet returns whether the extension field is set.
   188 // IsSet returns whether the extension field is set.
   189 // This may be called concurrently.
   189 // This may be called concurrently.
   191 	return f.typ != nil
   191 	return f.typ != nil
   192 }
   192 }
   193 
   193 
   194 // IsLazy reports whether a field is lazily encoded.
   194 // IsLazy reports whether a field is lazily encoded.
   195 // It is exported for testing.
   195 // It is exported for testing.
   196 func IsLazy(m pref.Message, fd pref.FieldDescriptor) bool {
   196 func IsLazy(m protoreflect.Message, fd protoreflect.FieldDescriptor) bool {
   197 	var mi *MessageInfo
   197 	var mi *MessageInfo
   198 	var p pointer
   198 	var p pointer
   199 	switch m := m.(type) {
   199 	switch m := m.(type) {
   200 	case *messageState:
   200 	case *messageState:
   201 		mi = m.messageInfo()
   201 		mi = m.messageInfo()
   204 		mi = m.messageInfo()
   204 		mi = m.messageInfo()
   205 		p = m.pointer()
   205 		p = m.pointer()
   206 	default:
   206 	default:
   207 		return false
   207 		return false
   208 	}
   208 	}
   209 	xd, ok := fd.(pref.ExtensionTypeDescriptor)
   209 	xd, ok := fd.(protoreflect.ExtensionTypeDescriptor)
   210 	if !ok {
   210 	if !ok {
   211 		return false
   211 		return false
   212 	}
   212 	}
   213 	xt := xd.Type()
   213 	xt := xd.Type()
   214 	ext := mi.extensionMap(p)
   214 	ext := mi.extensionMap(p)