codec_extension.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  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 ifaceCoderFuncs
  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. var wiretag uint64
  27. if !xt.IsPacked() {
  28. wiretag = wire.EncodeTag(xt.Number(), wireTypes[xt.Kind()])
  29. } else {
  30. wiretag = wire.EncodeTag(xt.Number(), wire.BytesType)
  31. }
  32. e = &extensionFieldInfo{
  33. wiretag: wiretag,
  34. tagsize: wire.SizeVarint(wiretag),
  35. funcs: encoderFuncsForValue(xt, xt.GoType()),
  36. }
  37. // Does the unmarshal function need a value passed to it?
  38. // This is true for composite types, where we pass in a message, list, or map to fill in,
  39. // and for enums, where we pass in a prototype value to specify the concrete enum type.
  40. switch xt.Kind() {
  41. case pref.MessageKind, pref.GroupKind, pref.EnumKind:
  42. e.unmarshalNeedsValue = true
  43. default:
  44. if xt.Cardinality() == pref.Repeated {
  45. e.unmarshalNeedsValue = true
  46. }
  47. }
  48. mi.extensionFieldInfosMu.Lock()
  49. if mi.extensionFieldInfos == nil {
  50. mi.extensionFieldInfos = make(map[pref.ExtensionType]*extensionFieldInfo)
  51. }
  52. mi.extensionFieldInfos[xt] = e
  53. mi.extensionFieldInfosMu.Unlock()
  54. return e
  55. }
  56. type ExtensionField struct {
  57. typ pref.ExtensionType
  58. // value is either the value of GetValue,
  59. // or a *lazyExtensionValue that then returns the value of GetValue.
  60. value interface{} // TODO: switch to protoreflect.Value
  61. }
  62. func (f ExtensionField) HasType() bool {
  63. return f.typ != nil
  64. }
  65. func (f ExtensionField) GetType() pref.ExtensionType {
  66. return f.typ
  67. }
  68. func (f *ExtensionField) SetType(t pref.ExtensionType) {
  69. f.typ = t
  70. }
  71. // HasValue reports whether a value is set for the extension field.
  72. // This may be called concurrently.
  73. func (f ExtensionField) HasValue() bool {
  74. return f.value != nil
  75. }
  76. // GetValue returns the concrete value for the extension field.
  77. // Let the type of Desc.ExtensionType be the "API type" and
  78. // the type of GetValue be the "storage type".
  79. // The API type and storage type are the same except:
  80. // * for scalars (except []byte), where the API type uses *T,
  81. // while the storage type uses T.
  82. // * for repeated fields, where the API type uses []T,
  83. // while the storage type uses *[]T.
  84. //
  85. // The reason for the divergence is so that the storage type more naturally
  86. // matches what is expected of when retrieving the values through the
  87. // protobuf reflection APIs.
  88. //
  89. // GetValue is only populated if Desc is also populated.
  90. // This may be called concurrently.
  91. //
  92. // TODO: switch interface{} to protoreflect.Value
  93. func (f ExtensionField) GetValue() interface{} {
  94. if f, ok := f.value.(*lazyExtensionValue); ok {
  95. return f.GetValue()
  96. }
  97. return f.value
  98. }
  99. // SetEagerValue sets the current value of the extension.
  100. // This must not be called concurrently.
  101. func (f *ExtensionField) SetEagerValue(v interface{}) {
  102. f.value = v
  103. }
  104. // SetLazyValue sets a value that is to be lazily evaluated upon first use.
  105. // The returned value must not be nil.
  106. // This must not be called concurrently.
  107. func (f *ExtensionField) SetLazyValue(v func() interface{}) {
  108. f.value = &lazyExtensionValue{value: v}
  109. }
  110. type lazyExtensionValue struct {
  111. once uint32 // atomically set if value is valid
  112. mu sync.Mutex // protects value
  113. value interface{} // either the value itself or a func() interface{}
  114. }
  115. func (v *lazyExtensionValue) GetValue() interface{} {
  116. if atomic.LoadUint32(&v.once) == 0 {
  117. v.mu.Lock()
  118. if f, ok := v.value.(func() interface{}); ok {
  119. v.value = f()
  120. }
  121. atomic.StoreUint32(&v.once, 1)
  122. v.mu.Unlock()
  123. }
  124. return v.value
  125. }