legacy_message.go 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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 impl
  5. import (
  6. "fmt"
  7. "reflect"
  8. "strings"
  9. "sync"
  10. "unicode"
  11. descriptorV1 "github.com/golang/protobuf/protoc-gen-go/descriptor"
  12. ptag "github.com/golang/protobuf/v2/internal/encoding/tag"
  13. scalar "github.com/golang/protobuf/v2/internal/scalar"
  14. pvalue "github.com/golang/protobuf/v2/internal/value"
  15. pref "github.com/golang/protobuf/v2/reflect/protoreflect"
  16. ptype "github.com/golang/protobuf/v2/reflect/prototype"
  17. )
  18. // legacyWrapMessage wraps v as a protoreflect.ProtoMessage,
  19. // where v must be a *struct kind and not implement the v2 API already.
  20. func legacyWrapMessage(v reflect.Value) pref.ProtoMessage {
  21. mt := legacyLoadMessageType(v.Type())
  22. return (*legacyMessageWrapper)(mt.dataTypeOf(v.Interface()))
  23. }
  24. var messageTypeCache sync.Map // map[reflect.Type]*MessageType
  25. // legacyLoadMessageType dynamically loads a *MessageType for t,
  26. // where t must be a *struct kind and not implement the v2 API already.
  27. func legacyLoadMessageType(t reflect.Type) *MessageType {
  28. // Fast-path: check if a MessageType is cached for this concrete type.
  29. if mt, ok := messageTypeCache.Load(t); ok {
  30. return mt.(*MessageType)
  31. }
  32. // Slow-path: derive message descriptor and initialize MessageType.
  33. md := legacyLoadMessageDesc(t)
  34. mt := new(MessageType)
  35. mt.Type = ptype.GoMessage(md, func(pref.MessageType) pref.ProtoMessage {
  36. p := reflect.New(t.Elem()).Interface()
  37. return (*legacyMessageWrapper)(mt.dataTypeOf(p))
  38. })
  39. messageTypeCache.Store(t, mt)
  40. return mt
  41. }
  42. type legacyMessageWrapper messageDataType
  43. func (m *legacyMessageWrapper) Type() pref.MessageType {
  44. return m.mi.Type
  45. }
  46. func (m *legacyMessageWrapper) KnownFields() pref.KnownFields {
  47. return (*knownFields)(m)
  48. }
  49. func (m *legacyMessageWrapper) UnknownFields() pref.UnknownFields {
  50. return m.mi.unknownFields((*messageDataType)(m))
  51. }
  52. func (m *legacyMessageWrapper) Unwrap() interface{} {
  53. return m.p.asType(m.mi.goType.Elem()).Interface()
  54. }
  55. func (m *legacyMessageWrapper) Interface() pref.ProtoMessage {
  56. return m
  57. }
  58. func (m *legacyMessageWrapper) ProtoReflect() pref.Message {
  59. return m
  60. }
  61. func (m *legacyMessageWrapper) ProtoMutable() {}
  62. var (
  63. _ pref.Message = (*legacyMessageWrapper)(nil)
  64. _ pref.ProtoMessage = (*legacyMessageWrapper)(nil)
  65. _ pvalue.Unwrapper = (*legacyMessageWrapper)(nil)
  66. )
  67. var messageDescCache sync.Map // map[reflect.Type]protoreflect.MessageDescriptor
  68. // legacyLoadMessageDesc returns an MessageDescriptor derived from the Go type,
  69. // which must be a *struct kind and not implement the v2 API already.
  70. func legacyLoadMessageDesc(t reflect.Type) pref.MessageDescriptor {
  71. return messageDescSet{}.Load(t)
  72. }
  73. type messageDescSet struct {
  74. visited map[reflect.Type]*ptype.StandaloneMessage
  75. descs []*ptype.StandaloneMessage
  76. types []reflect.Type
  77. }
  78. func (ms messageDescSet) Load(t reflect.Type) pref.MessageDescriptor {
  79. // Fast-path: check if a MessageDescriptor is cached for this concrete type.
  80. if mi, ok := messageDescCache.Load(t); ok {
  81. return mi.(pref.MessageDescriptor)
  82. }
  83. // Slow-path: initialize MessageDescriptor from the Go type.
  84. // Processing t recursively populates descs and types with all sub-messages.
  85. // The descriptor for the first type is guaranteed to be at the front.
  86. ms.processMessage(t)
  87. // Within a proto file it is possible for cyclic dependencies to exist
  88. // between multiple message types. When these cases arise, the set of
  89. // message descriptors must be created together.
  90. mds, err := ptype.NewMessages(ms.descs)
  91. if err != nil {
  92. panic(err)
  93. }
  94. for i, md := range mds {
  95. // Protobuf semantics represents map entries under-the-hood as
  96. // pseudo-messages (has a descriptor, but no generated Go type).
  97. // Avoid caching these fake messages.
  98. if t := ms.types[i]; t.Kind() != reflect.Map {
  99. messageDescCache.Store(t, md)
  100. }
  101. }
  102. return mds[0]
  103. }
  104. func (ms *messageDescSet) processMessage(t reflect.Type) pref.MessageDescriptor {
  105. // Fast-path: Obtain a placeholder if the message is already processed.
  106. if m, ok := ms.visited[t]; ok {
  107. return ptype.PlaceholderMessage(m.FullName)
  108. }
  109. // Slow-path: Walk over the struct fields to derive the message descriptor.
  110. if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct || t.Elem().PkgPath() == "" {
  111. panic(fmt.Sprintf("got %v, want named *struct kind", t))
  112. }
  113. // Derive name and syntax from the raw descriptor.
  114. m := new(ptype.StandaloneMessage)
  115. mv := reflect.New(t.Elem()).Interface()
  116. if _, ok := mv.(pref.ProtoMessage); ok {
  117. panic(fmt.Sprintf("%v already implements proto.Message", t))
  118. }
  119. if md, ok := mv.(legacyMessage); ok {
  120. b, idxs := md.Descriptor()
  121. fd := legacyLoadFileDesc(b)
  122. // Derive syntax.
  123. switch fd.GetSyntax() {
  124. case "proto2", "":
  125. m.Syntax = pref.Proto2
  126. case "proto3":
  127. m.Syntax = pref.Proto3
  128. }
  129. // Derive full name.
  130. md := fd.MessageType[idxs[0]]
  131. m.FullName = pref.FullName(fd.GetPackage()).Append(pref.Name(md.GetName()))
  132. for _, i := range idxs[1:] {
  133. md = md.NestedType[i]
  134. m.FullName = m.FullName.Append(pref.Name(md.GetName()))
  135. }
  136. } else {
  137. // If the type does not implement legacyMessage, then the only way to
  138. // obtain the full name is through the registry. However, this is
  139. // unreliable as some generated messages register with a fork of
  140. // golang/protobuf, so the registry may not have this information.
  141. m.FullName = deriveFullName(t.Elem())
  142. m.Syntax = pref.Proto2
  143. // Try to determine if the message is using proto3 by checking scalars.
  144. for i := 0; i < t.Elem().NumField(); i++ {
  145. f := t.Elem().Field(i)
  146. if tag := f.Tag.Get("protobuf"); tag != "" {
  147. switch f.Type.Kind() {
  148. case reflect.Bool, reflect.Int32, reflect.Int64, reflect.Uint32, reflect.Uint64, reflect.Float32, reflect.Float64, reflect.String:
  149. m.Syntax = pref.Proto3
  150. }
  151. for _, s := range strings.Split(tag, ",") {
  152. if s == "proto3" {
  153. m.Syntax = pref.Proto3
  154. }
  155. }
  156. }
  157. }
  158. }
  159. ms.visit(m, t)
  160. // Obtain a list of oneof wrapper types.
  161. var oneofWrappers []reflect.Type
  162. if fn, ok := t.MethodByName("XXX_OneofFuncs"); ok {
  163. vs := fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[3]
  164. for _, v := range vs.Interface().([]interface{}) {
  165. oneofWrappers = append(oneofWrappers, reflect.TypeOf(v))
  166. }
  167. }
  168. // Obtain a list of the extension ranges.
  169. if fn, ok := t.MethodByName("ExtensionRangeArray"); ok {
  170. vs := fn.Func.Call([]reflect.Value{reflect.Zero(fn.Type.In(0))})[0]
  171. for i := 0; i < vs.Len(); i++ {
  172. v := vs.Index(i)
  173. m.ExtensionRanges = append(m.ExtensionRanges, [2]pref.FieldNumber{
  174. pref.FieldNumber(v.FieldByName("Start").Int()),
  175. pref.FieldNumber(v.FieldByName("End").Int() + 1),
  176. })
  177. }
  178. }
  179. // Derive the message fields by inspecting the struct fields.
  180. for i := 0; i < t.Elem().NumField(); i++ {
  181. f := t.Elem().Field(i)
  182. if tag := f.Tag.Get("protobuf"); tag != "" {
  183. tagKey := f.Tag.Get("protobuf_key")
  184. tagVal := f.Tag.Get("protobuf_val")
  185. m.Fields = append(m.Fields, ms.parseField(tag, tagKey, tagVal, f.Type, m))
  186. }
  187. if tag := f.Tag.Get("protobuf_oneof"); tag != "" {
  188. name := pref.Name(tag)
  189. m.Oneofs = append(m.Oneofs, ptype.Oneof{Name: name})
  190. for _, t := range oneofWrappers {
  191. if t.Implements(f.Type) {
  192. f := t.Elem().Field(0)
  193. if tag := f.Tag.Get("protobuf"); tag != "" {
  194. ft := ms.parseField(tag, "", "", f.Type, m)
  195. ft.OneofName = name
  196. m.Fields = append(m.Fields, ft)
  197. }
  198. }
  199. }
  200. }
  201. }
  202. return ptype.PlaceholderMessage(m.FullName)
  203. }
  204. func (ms *messageDescSet) parseField(tag, tagKey, tagVal string, goType reflect.Type, parent *ptype.StandaloneMessage) ptype.Field {
  205. t := goType
  206. isOptional := t.Kind() == reflect.Ptr && t.Elem().Kind() != reflect.Struct
  207. isRepeated := t.Kind() == reflect.Slice && t.Elem().Kind() != reflect.Uint8
  208. if isOptional || isRepeated {
  209. t = t.Elem()
  210. }
  211. f := ptag.Unmarshal(tag, t)
  212. // Populate EnumType and MessageType.
  213. if f.EnumType == nil && f.Kind == pref.EnumKind {
  214. if ev, ok := reflect.Zero(t).Interface().(pref.ProtoEnum); ok {
  215. f.EnumType = ev.ProtoReflect().Type()
  216. } else {
  217. f.EnumType = legacyLoadEnumDesc(t)
  218. }
  219. }
  220. if f.MessageType == nil && (f.Kind == pref.MessageKind || f.Kind == pref.GroupKind) {
  221. if mv, ok := reflect.Zero(t).Interface().(pref.ProtoMessage); ok {
  222. f.MessageType = mv.ProtoReflect().Type()
  223. } else if t.Kind() == reflect.Map {
  224. m := &ptype.StandaloneMessage{
  225. Syntax: parent.Syntax,
  226. FullName: parent.FullName.Append(mapEntryName(f.Name)),
  227. Options: &descriptorV1.MessageOptions{MapEntry: scalar.Bool(true)},
  228. Fields: []ptype.Field{
  229. ms.parseField(tagKey, "", "", t.Key(), nil),
  230. ms.parseField(tagVal, "", "", t.Elem(), nil),
  231. },
  232. }
  233. ms.visit(m, t)
  234. f.MessageType = ptype.PlaceholderMessage(m.FullName)
  235. } else if mv, ok := messageDescCache.Load(t); ok {
  236. f.MessageType = mv.(pref.MessageDescriptor)
  237. } else {
  238. f.MessageType = ms.processMessage(t)
  239. }
  240. }
  241. return f
  242. }
  243. func (ms *messageDescSet) visit(m *ptype.StandaloneMessage, t reflect.Type) {
  244. if ms.visited == nil {
  245. ms.visited = make(map[reflect.Type]*ptype.StandaloneMessage)
  246. }
  247. if t.Kind() != reflect.Map {
  248. ms.visited[t] = m
  249. }
  250. ms.descs = append(ms.descs, m)
  251. ms.types = append(ms.types, t)
  252. }
  253. // deriveFullName derives a fully qualified protobuf name for the given Go type
  254. // The provided name is not guaranteed to be stable nor universally unique.
  255. // It should be sufficiently unique within a program.
  256. func deriveFullName(t reflect.Type) pref.FullName {
  257. sanitize := func(r rune) rune {
  258. switch {
  259. case r == '/':
  260. return '.'
  261. case 'a' <= r && r <= 'z', 'A' <= r && r <= 'Z', '0' <= r && r <= '9':
  262. return r
  263. default:
  264. return '_'
  265. }
  266. }
  267. prefix := strings.Map(sanitize, t.PkgPath())
  268. suffix := strings.Map(sanitize, t.Name())
  269. if suffix == "" {
  270. suffix = fmt.Sprintf("UnknownX%X", reflect.ValueOf(t).Pointer())
  271. }
  272. ss := append(strings.Split(prefix, "."), suffix)
  273. for i, s := range ss {
  274. if s == "" || ('0' <= s[0] && s[0] <= '9') {
  275. ss[i] = "x" + s
  276. }
  277. }
  278. return pref.FullName(strings.Join(ss, "."))
  279. }
  280. // mapEntryName derives the message name for a map field of a given name.
  281. // This is identical to MapEntryName from parser.cc in the protoc source.
  282. func mapEntryName(s pref.Name) pref.Name {
  283. var b []byte
  284. nextUpper := true
  285. for i := 0; i < len(s); i++ {
  286. if c := s[i]; c == '_' {
  287. nextUpper = true
  288. } else {
  289. if nextUpper {
  290. c = byte(unicode.ToUpper(rune(c)))
  291. nextUpper = false
  292. }
  293. b = append(b, c)
  294. }
  295. }
  296. return pref.Name(append(b, "Entry"...))
  297. }