api.go 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. // Copyright 2018 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 protoapi contains the set of types referenced by generated messages.
  5. //
  6. // WARNING: This package should only ever be imported by generated messages.
  7. // The compatibility agreement covers nothing except for functionality needed
  8. // to keep existing generated messages operational.
  9. package protoapi
  10. import (
  11. "fmt"
  12. "sync"
  13. "github.com/golang/protobuf/v2/reflect/protoreflect"
  14. )
  15. // TODO: How to handle Registration during the v1 to v2 switchover?
  16. type (
  17. Message interface {
  18. Reset()
  19. String() string
  20. ProtoMessage()
  21. }
  22. ExtensionRange struct {
  23. Start, End int32 // both inclusive
  24. }
  25. ExtensionDesc struct {
  26. // Type is the descriptor type for the extension field using the v2 API.
  27. // If populated, the information in this field takes precedence over
  28. // all other fields in ExtensionDesc.
  29. Type protoreflect.ExtensionType
  30. // ExtendedType is a typed nil-pointer to the parent message type that
  31. // is being extended. It is possible for this to be unpopulated in v2
  32. // since the message may no longer implement the v1 Message interface.
  33. //
  34. // Deprecated: Use Type.ExtendedType instead.
  35. ExtendedType Message
  36. // ExtensionType is zero value of the extension type.
  37. //
  38. // For historical reasons, reflect.TypeOf(ExtensionType) and Type.GoType
  39. // may not be identical:
  40. // * for scalars (except []byte), where ExtensionType uses *T,
  41. // while Type.GoType uses T.
  42. // * for repeated fields, where ExtensionType uses []T,
  43. // while Type.GoType uses *[]T.
  44. //
  45. // Deprecated: Use Type.GoType instead.
  46. ExtensionType interface{}
  47. // Field is the field number of the extension.
  48. //
  49. // Deprecated: Use Type.Number instead.
  50. Field int32 // field number
  51. // Name is the fully qualified name of extension.
  52. //
  53. // Deprecated: Use Type.FullName instead.
  54. Name string
  55. // Tag is the protobuf struct tag used in the v1 API.
  56. //
  57. // Deprecated: Do not use.
  58. Tag string
  59. // Filename is the proto filename in which the extension is defined.
  60. //
  61. // Deprecated: Use Type.Parent to ascend to the top-most parent and use
  62. // protoreflect.FileDescriptor.Path.
  63. Filename string
  64. }
  65. ExtensionFields extensionFields
  66. ExtensionField extensionField
  67. XXX_InternalExtensions extensionSyncMap
  68. )
  69. // ExtensionFieldsOf returns an ExtensionFields abstraction over various
  70. // internal representations of extension fields.
  71. func ExtensionFieldsOf(p interface{}) ExtensionFields {
  72. switch p := p.(type) {
  73. case *map[int32]ExtensionField:
  74. return (*extensionMap)(p)
  75. case *XXX_InternalExtensions:
  76. return (*extensionSyncMap)(p)
  77. default:
  78. panic(fmt.Sprintf("invalid extension fields type: %T", p))
  79. }
  80. }
  81. type extensionFields interface {
  82. Len() int
  83. Has(protoreflect.FieldNumber) bool
  84. Get(protoreflect.FieldNumber) ExtensionField
  85. Set(protoreflect.FieldNumber, ExtensionField)
  86. Clear(protoreflect.FieldNumber)
  87. Range(f func(protoreflect.FieldNumber, ExtensionField) bool)
  88. // HasInit and Locker are used by v1 GetExtension to provide
  89. // an artificial degree of concurrent safety.
  90. HasInit() bool
  91. sync.Locker
  92. }
  93. type extensionField struct {
  94. // When an extension is stored in a message using SetExtension
  95. // only desc and value are set. When the message is marshaled
  96. // Raw will be set to the encoded form of the message.
  97. //
  98. // When a message is unmarshaled and contains extensions, each
  99. // extension will have only Raw set. When such an extension is
  100. // accessed using GetExtension (or GetExtensions) desc and value
  101. // will be set.
  102. Desc *ExtensionDesc // TODO: switch to protoreflect.ExtensionType
  103. // Value is a concrete value for the extension field. Let the type of
  104. // Desc.ExtensionType be the "API type" and the type of Value be the
  105. // "storage type". The API type and storage type are the same except:
  106. // * for scalars (except []byte), where the API type uses *T,
  107. // while the storage type uses T.
  108. // * for repeated fields, where the API type uses []T,
  109. // while the storage type uses *[]T.
  110. //
  111. // The reason for the divergence is so that the storage type more naturally
  112. // matches what is expected of when retrieving the values through the
  113. // protobuf reflection APIs.
  114. //
  115. // The Value may only be populated if Desc is also populated.
  116. Value interface{} // TODO: switch to protoreflect.Value
  117. // Raw is the raw encoded bytes for the extension field.
  118. // It is possible for Raw to be populated irrespective of whether the
  119. // other fields are populated.
  120. Raw []byte // TODO: switch to protoreflect.RawFields
  121. }
  122. type extensionSyncMap struct {
  123. p *struct {
  124. mu sync.Mutex
  125. m extensionMap
  126. }
  127. }
  128. func (m extensionSyncMap) Len() int {
  129. if m.p == nil {
  130. return 0
  131. }
  132. return m.p.m.Len()
  133. }
  134. func (m extensionSyncMap) Has(n protoreflect.FieldNumber) bool {
  135. if m.p == nil {
  136. return false
  137. }
  138. return m.p.m.Has(n)
  139. }
  140. func (m extensionSyncMap) Get(n protoreflect.FieldNumber) ExtensionField {
  141. if m.p == nil {
  142. return ExtensionField{}
  143. }
  144. return m.p.m.Get(n)
  145. }
  146. func (m *extensionSyncMap) Set(n protoreflect.FieldNumber, x ExtensionField) {
  147. if m.p == nil {
  148. m.p = new(struct {
  149. mu sync.Mutex
  150. m extensionMap
  151. })
  152. }
  153. m.p.m.Set(n, x)
  154. }
  155. func (m extensionSyncMap) Clear(n protoreflect.FieldNumber) {
  156. if m.p == nil {
  157. return
  158. }
  159. m.p.m.Clear(n)
  160. }
  161. func (m extensionSyncMap) Range(f func(protoreflect.FieldNumber, ExtensionField) bool) {
  162. if m.p == nil {
  163. return
  164. }
  165. m.p.m.Range(f)
  166. }
  167. func (m extensionSyncMap) HasInit() bool {
  168. return m.p != nil
  169. }
  170. func (m extensionSyncMap) Lock() {
  171. m.p.mu.Lock()
  172. }
  173. func (m extensionSyncMap) Unlock() {
  174. m.p.mu.Unlock()
  175. }
  176. type extensionMap map[int32]ExtensionField
  177. func (m extensionMap) Len() int {
  178. return len(m)
  179. }
  180. func (m extensionMap) Has(n protoreflect.FieldNumber) bool {
  181. _, ok := m[int32(n)]
  182. return ok
  183. }
  184. func (m extensionMap) Get(n protoreflect.FieldNumber) ExtensionField {
  185. return m[int32(n)]
  186. }
  187. func (m *extensionMap) Set(n protoreflect.FieldNumber, x ExtensionField) {
  188. if *m == nil {
  189. *m = make(map[int32]ExtensionField)
  190. }
  191. (*m)[int32(n)] = x
  192. }
  193. func (m *extensionMap) Clear(n protoreflect.FieldNumber) {
  194. delete(*m, int32(n))
  195. }
  196. func (m extensionMap) Range(f func(protoreflect.FieldNumber, ExtensionField) bool) {
  197. for n, x := range m {
  198. if !f(protoreflect.FieldNumber(n), x) {
  199. return
  200. }
  201. }
  202. }
  203. var globalLock sync.Mutex
  204. func (m extensionMap) HasInit() bool {
  205. return m != nil
  206. }
  207. func (m extensionMap) Lock() {
  208. if !m.HasInit() {
  209. panic("cannot lock an uninitialized map")
  210. }
  211. globalLock.Lock()
  212. }
  213. func (m extensionMap) Unlock() {
  214. globalLock.Unlock()
  215. }