codec_extension.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package impl
  5. import (
  6. "sync"
  7. "sync/atomic"
  8. "google.golang.org/protobuf/internal/encoding/wire"
  9. pref "google.golang.org/protobuf/reflect/protoreflect"
  10. )
  11. type extensionFieldInfo struct {
  12. wiretag uint64
  13. tagsize int
  14. unmarshalNeedsValue bool
  15. funcs valueCoderFuncs
  16. }
  17. func (mi *MessageInfo) extensionFieldInfo(xt pref.ExtensionType) *extensionFieldInfo {
  18. // As of this time (Go 1.12, linux/amd64), an RWMutex benchmarks as faster
  19. // than a sync.Map.
  20. mi.extensionFieldInfosMu.RLock()
  21. e, ok := mi.extensionFieldInfos[xt]
  22. mi.extensionFieldInfosMu.RUnlock()
  23. if ok {
  24. return e
  25. }
  26. xd := xt.TypeDescriptor()
  27. var wiretag uint64
  28. if !xd.IsPacked() {
  29. wiretag = wire.EncodeTag(xd.Number(), wireTypes[xd.Kind()])
  30. } else {
  31. wiretag = wire.EncodeTag(xd.Number(), wire.BytesType)
  32. }
  33. e = &extensionFieldInfo{
  34. wiretag: wiretag,
  35. tagsize: wire.SizeVarint(wiretag),
  36. funcs: encoderFuncsForValue(xd),
  37. }
  38. // Does the unmarshal function need a value passed to it?
  39. // This is true for composite types, where we pass in a message, list, or map to fill in,
  40. // and for enums, where we pass in a prototype value to specify the concrete enum type.
  41. switch xd.Kind() {
  42. case pref.MessageKind, pref.GroupKind, pref.EnumKind:
  43. e.unmarshalNeedsValue = true
  44. default:
  45. if xd.Cardinality() == pref.Repeated {
  46. e.unmarshalNeedsValue = true
  47. }
  48. }
  49. mi.extensionFieldInfosMu.Lock()
  50. if mi.extensionFieldInfos == nil {
  51. mi.extensionFieldInfos = make(map[pref.ExtensionType]*extensionFieldInfo)
  52. }
  53. mi.extensionFieldInfos[xt] = e
  54. mi.extensionFieldInfosMu.Unlock()
  55. return e
  56. }
  57. type ExtensionField struct {
  58. typ pref.ExtensionType
  59. // value is either the value of GetValue,
  60. // or a *lazyExtensionValue that then returns the value of GetValue.
  61. value pref.Value
  62. lazy *lazyExtensionValue
  63. }
  64. // Set sets the type and value of the extension field.
  65. // This must not be called concurrently.
  66. func (f *ExtensionField) Set(t pref.ExtensionType, v pref.Value) {
  67. f.typ = t
  68. f.value = v
  69. }
  70. // SetLazy sets the type and a value that is to be lazily evaluated upon first use.
  71. // This must not be called concurrently.
  72. func (f *ExtensionField) SetLazy(t pref.ExtensionType, fn func() pref.Value) {
  73. f.typ = t
  74. f.lazy = &lazyExtensionValue{value: fn}
  75. }
  76. // Value returns the value of the extension field.
  77. // This may be called concurrently.
  78. func (f *ExtensionField) Value() pref.Value {
  79. if f.lazy != nil {
  80. return f.lazy.GetValue()
  81. }
  82. return f.value
  83. }
  84. // Type returns the type of the extension field.
  85. // This may be called concurrently.
  86. func (f ExtensionField) Type() pref.ExtensionType {
  87. return f.typ
  88. }
  89. // IsSet returns whether the extension field is set.
  90. // This may be called concurrently.
  91. func (f ExtensionField) IsSet() bool {
  92. return f.typ != nil
  93. }
  94. // Deprecated: Do not use.
  95. func (f ExtensionField) HasType() bool {
  96. return f.typ != nil
  97. }
  98. // Deprecated: Do not use.
  99. func (f ExtensionField) GetType() pref.ExtensionType {
  100. return f.typ
  101. }
  102. // Deprecated: Do not use.
  103. func (f *ExtensionField) SetType(t pref.ExtensionType) {
  104. f.typ = t
  105. }
  106. // Deprecated: Do not use.
  107. func (f ExtensionField) HasValue() bool {
  108. return f.value.IsValid() || f.lazy != nil
  109. }
  110. // Deprecated: Do not use.
  111. func (f ExtensionField) GetValue() interface{} {
  112. return f.typ.InterfaceOf(f.Value())
  113. }
  114. // Deprecated: Do not use.
  115. func (f *ExtensionField) SetEagerValue(ival interface{}) {
  116. f.value = f.typ.ValueOf(ival)
  117. }
  118. // Deprecated: Do not use.
  119. func (f *ExtensionField) SetLazyValue(fn func() interface{}) {
  120. f.lazy = &lazyExtensionValue{value: func() pref.Value {
  121. return f.typ.ValueOf(fn())
  122. }}
  123. }
  124. type lazyExtensionValue struct {
  125. once uint32 // atomically set if value is valid
  126. mu sync.Mutex // protects value
  127. value interface{} // either a pref.Value itself or a func() pref.ValueOf
  128. }
  129. func (v *lazyExtensionValue) GetValue() pref.Value {
  130. if atomic.LoadUint32(&v.once) == 0 {
  131. v.mu.Lock()
  132. if f, ok := v.value.(func() pref.Value); ok {
  133. v.value = f()
  134. }
  135. atomic.StoreUint32(&v.once, 1)
  136. v.mu.Unlock()
  137. }
  138. return v.value.(pref.Value)
  139. }