message_reflect.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  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. "fmt"
  7. "reflect"
  8. "google.golang.org/protobuf/internal/pragma"
  9. pvalue "google.golang.org/protobuf/internal/value"
  10. pref "google.golang.org/protobuf/reflect/protoreflect"
  11. )
  12. // MessageState is a data structure that is nested as the first field in a
  13. // concrete message. It provides a way to implement the ProtoReflect method
  14. // in an allocation-free way without needing to have a shadow Go type generated
  15. // for every message type. This technique only works using unsafe.
  16. //
  17. //
  18. // Example generated code:
  19. //
  20. // type M struct {
  21. // state protoimpl.MessageState
  22. //
  23. // Field1 int32
  24. // Field2 string
  25. // Field3 *BarMessage
  26. // ...
  27. // }
  28. //
  29. // func (m *M) ProtoReflect() protoreflect.Message {
  30. // mi := &file_fizz_buzz_proto_msgInfos[5]
  31. // if protoimpl.UnsafeEnabled && m != nil {
  32. // ms := protoimpl.X.MessageStateOf(Pointer(m))
  33. // if ms.LoadMessageInfo() == nil {
  34. // ms.StoreMessageInfo(mi)
  35. // }
  36. // return ms
  37. // }
  38. // return mi.MessageOf(m)
  39. // }
  40. //
  41. // The MessageState type holds a *MessageInfo, which must be atomically set to
  42. // the message info associated with a given message instance.
  43. // By unsafely converting a *M into a *MessageState, the MessageState object
  44. // has access to all the information needed to implement protobuf reflection.
  45. // It has access to the message info as its first field, and a pointer to the
  46. // MessageState is identical to a pointer to the concrete message value.
  47. //
  48. //
  49. // Requirements:
  50. // • The type M must implement protoreflect.ProtoMessage.
  51. // • The address of m must not be nil.
  52. // • The address of m and the address of m.state must be equal,
  53. // even though they are different Go types.
  54. type MessageState struct {
  55. pragma.NoUnkeyedLiterals
  56. pragma.DoNotCompare
  57. pragma.DoNotCopy
  58. mi *MessageInfo
  59. }
  60. type messageState MessageState
  61. var (
  62. _ pref.Message = (*messageState)(nil)
  63. _ pvalue.Unwrapper = (*messageState)(nil)
  64. )
  65. // messageDataType is a tuple of a pointer to the message data and
  66. // a pointer to the message type. It is a generalized way of providing a
  67. // reflective view over a message instance. The disadvantage of this approach
  68. // is the need to allocate this tuple of 16B.
  69. type messageDataType struct {
  70. p pointer
  71. mi *MessageInfo
  72. }
  73. type (
  74. messageReflectWrapper messageDataType
  75. messageIfaceWrapper messageDataType
  76. )
  77. var (
  78. _ pref.Message = (*messageReflectWrapper)(nil)
  79. _ pvalue.Unwrapper = (*messageReflectWrapper)(nil)
  80. _ pref.ProtoMessage = (*messageIfaceWrapper)(nil)
  81. _ pvalue.Unwrapper = (*messageIfaceWrapper)(nil)
  82. )
  83. // MessageOf returns a reflective view over a message. The input must be a
  84. // pointer to a named Go struct. If the provided type has a ProtoReflect method,
  85. // it must be implemented by calling this method.
  86. func (mi *MessageInfo) MessageOf(m interface{}) pref.Message {
  87. // TODO: Switch the input to be an opaque Pointer.
  88. if reflect.TypeOf(m) != mi.GoType {
  89. panic(fmt.Sprintf("type mismatch: got %T, want %v", m, mi.GoType))
  90. }
  91. p := pointerOfIface(m)
  92. if p.IsNil() {
  93. return mi.nilMessage.Init(mi)
  94. }
  95. return &messageReflectWrapper{p, mi}
  96. }
  97. func (m *messageReflectWrapper) pointer() pointer { return m.p }
  98. func (m *messageIfaceWrapper) ProtoReflect() pref.Message {
  99. return (*messageReflectWrapper)(m)
  100. }
  101. func (m *messageIfaceWrapper) ProtoUnwrap() interface{} {
  102. return m.p.AsIfaceOf(m.mi.GoType.Elem())
  103. }
  104. type extensionMap map[int32]ExtensionField
  105. func (m *extensionMap) Range(f func(pref.FieldDescriptor, pref.Value) bool) {
  106. if m != nil {
  107. for _, x := range *m {
  108. xt := x.GetType()
  109. if !f(xt, xt.ValueOf(x.GetValue())) {
  110. return
  111. }
  112. }
  113. }
  114. }
  115. func (m *extensionMap) Has(xt pref.ExtensionType) (ok bool) {
  116. if m != nil {
  117. _, ok = (*m)[int32(xt.Number())]
  118. }
  119. return ok
  120. }
  121. func (m *extensionMap) Clear(xt pref.ExtensionType) {
  122. delete(*m, int32(xt.Number()))
  123. }
  124. func (m *extensionMap) Get(xt pref.ExtensionType) pref.Value {
  125. if m != nil {
  126. if x, ok := (*m)[int32(xt.Number())]; ok {
  127. return xt.ValueOf(x.GetValue())
  128. }
  129. }
  130. if !isComposite(xt) {
  131. return defaultValueOf(xt)
  132. }
  133. return frozenValueOf(xt.New())
  134. }
  135. func (m *extensionMap) Set(xt pref.ExtensionType, v pref.Value) {
  136. if *m == nil {
  137. *m = make(map[int32]ExtensionField)
  138. }
  139. var x ExtensionField
  140. x.SetType(xt)
  141. x.SetEagerValue(xt.InterfaceOf(v))
  142. (*m)[int32(xt.Number())] = x
  143. }
  144. func (m *extensionMap) Mutable(xt pref.ExtensionType) pref.Value {
  145. if !isComposite(xt) {
  146. panic("invalid Mutable on field with non-composite type")
  147. }
  148. if x, ok := (*m)[int32(xt.Number())]; ok {
  149. return xt.ValueOf(x.GetValue())
  150. }
  151. v := xt.New()
  152. m.Set(xt, v)
  153. return v
  154. }
  155. func isComposite(fd pref.FieldDescriptor) bool {
  156. return fd.Kind() == pref.MessageKind || fd.Kind() == pref.GroupKind || fd.IsList() || fd.IsMap()
  157. }
  158. // checkField verifies that the provided field descriptor is valid.
  159. // Exactly one of the returned values is populated.
  160. func (mi *MessageInfo) checkField(fd pref.FieldDescriptor) (*fieldInfo, pref.ExtensionType) {
  161. if fi := mi.fields[fd.Number()]; fi != nil {
  162. if fi.fieldDesc != fd {
  163. panic("mismatching field descriptor")
  164. }
  165. return fi, nil
  166. }
  167. if fd.IsExtension() {
  168. if fd.ContainingMessage().FullName() != mi.PBType.FullName() {
  169. // TODO: Should this be exact containing message descriptor match?
  170. panic("mismatching containing message")
  171. }
  172. if !mi.PBType.ExtensionRanges().Has(fd.Number()) {
  173. panic("invalid extension field")
  174. }
  175. return nil, fd.(pref.ExtensionType)
  176. }
  177. panic("invalid field descriptor")
  178. }