message_reflect_field.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  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. "math"
  8. "reflect"
  9. "sync"
  10. "google.golang.org/protobuf/internal/flags"
  11. pref "google.golang.org/protobuf/reflect/protoreflect"
  12. preg "google.golang.org/protobuf/reflect/protoregistry"
  13. piface "google.golang.org/protobuf/runtime/protoiface"
  14. )
  15. type fieldInfo struct {
  16. fieldDesc pref.FieldDescriptor
  17. // These fields are used for protobuf reflection support.
  18. has func(pointer) bool
  19. clear func(pointer)
  20. get func(pointer) pref.Value
  21. set func(pointer, pref.Value)
  22. mutable func(pointer) pref.Value
  23. newMessage func() pref.Message
  24. newField func() pref.Value
  25. }
  26. func fieldInfoForOneof(fd pref.FieldDescriptor, fs reflect.StructField, x exporter, ot reflect.Type) fieldInfo {
  27. ft := fs.Type
  28. if ft.Kind() != reflect.Interface {
  29. panic(fmt.Sprintf("invalid type: got %v, want interface kind", ft))
  30. }
  31. if ot.Kind() != reflect.Struct {
  32. panic(fmt.Sprintf("invalid type: got %v, want struct kind", ot))
  33. }
  34. if !reflect.PtrTo(ot).Implements(ft) {
  35. panic(fmt.Sprintf("invalid type: %v does not implement %v", ot, ft))
  36. }
  37. conv := NewConverter(ot.Field(0).Type, fd)
  38. isMessage := fd.Message() != nil
  39. // TODO: Implement unsafe fast path?
  40. fieldOffset := offsetOf(fs, x)
  41. return fieldInfo{
  42. // NOTE: The logic below intentionally assumes that oneof fields are
  43. // well-formatted. That is, the oneof interface never contains a
  44. // typed nil pointer to one of the wrapper structs.
  45. fieldDesc: fd,
  46. has: func(p pointer) bool {
  47. if p.IsNil() {
  48. return false
  49. }
  50. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  51. if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
  52. return false
  53. }
  54. return true
  55. },
  56. clear: func(p pointer) {
  57. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  58. if rv.IsNil() || rv.Elem().Type().Elem() != ot {
  59. // NOTE: We intentionally don't check for rv.Elem().IsNil()
  60. // so that (*OneofWrapperType)(nil) gets cleared to nil.
  61. return
  62. }
  63. rv.Set(reflect.Zero(rv.Type()))
  64. },
  65. get: func(p pointer) pref.Value {
  66. if p.IsNil() {
  67. return conv.Zero()
  68. }
  69. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  70. if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
  71. return conv.Zero()
  72. }
  73. rv = rv.Elem().Elem().Field(0)
  74. return conv.PBValueOf(rv)
  75. },
  76. set: func(p pointer, v pref.Value) {
  77. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  78. if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
  79. rv.Set(reflect.New(ot))
  80. }
  81. rv = rv.Elem().Elem().Field(0)
  82. rv.Set(conv.GoValueOf(v))
  83. },
  84. mutable: func(p pointer) pref.Value {
  85. if !isMessage {
  86. panic("invalid Mutable on field with non-composite type")
  87. }
  88. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  89. if rv.IsNil() || rv.Elem().Type().Elem() != ot || rv.Elem().IsNil() {
  90. rv.Set(reflect.New(ot))
  91. }
  92. rv = rv.Elem().Elem().Field(0)
  93. if rv.IsNil() {
  94. rv.Set(conv.GoValueOf(pref.ValueOf(conv.New().Message())))
  95. }
  96. return conv.PBValueOf(rv)
  97. },
  98. newMessage: func() pref.Message {
  99. return conv.New().Message()
  100. },
  101. newField: func() pref.Value {
  102. return conv.New()
  103. },
  104. }
  105. }
  106. func fieldInfoForMap(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
  107. ft := fs.Type
  108. if ft.Kind() != reflect.Map {
  109. panic(fmt.Sprintf("invalid type: got %v, want map kind", ft))
  110. }
  111. conv := NewConverter(ft, fd)
  112. // TODO: Implement unsafe fast path?
  113. fieldOffset := offsetOf(fs, x)
  114. return fieldInfo{
  115. fieldDesc: fd,
  116. has: func(p pointer) bool {
  117. if p.IsNil() {
  118. return false
  119. }
  120. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  121. return rv.Len() > 0
  122. },
  123. clear: func(p pointer) {
  124. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  125. rv.Set(reflect.Zero(rv.Type()))
  126. },
  127. get: func(p pointer) pref.Value {
  128. if p.IsNil() {
  129. return conv.Zero()
  130. }
  131. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  132. return conv.PBValueOf(rv)
  133. },
  134. set: func(p pointer, v pref.Value) {
  135. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  136. rv.Set(conv.GoValueOf(v))
  137. },
  138. mutable: func(p pointer) pref.Value {
  139. v := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  140. if v.IsNil() {
  141. v.Set(reflect.MakeMap(fs.Type))
  142. }
  143. return conv.PBValueOf(v)
  144. },
  145. newField: func() pref.Value {
  146. return conv.New()
  147. },
  148. }
  149. }
  150. func fieldInfoForList(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
  151. ft := fs.Type
  152. if ft.Kind() != reflect.Slice {
  153. panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
  154. }
  155. conv := NewConverter(reflect.PtrTo(ft), fd)
  156. // TODO: Implement unsafe fast path?
  157. fieldOffset := offsetOf(fs, x)
  158. return fieldInfo{
  159. fieldDesc: fd,
  160. has: func(p pointer) bool {
  161. if p.IsNil() {
  162. return false
  163. }
  164. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  165. return rv.Len() > 0
  166. },
  167. clear: func(p pointer) {
  168. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  169. rv.Set(reflect.Zero(rv.Type()))
  170. },
  171. get: func(p pointer) pref.Value {
  172. if p.IsNil() {
  173. return conv.Zero()
  174. }
  175. rv := p.Apply(fieldOffset).AsValueOf(fs.Type)
  176. return conv.PBValueOf(rv)
  177. },
  178. set: func(p pointer, v pref.Value) {
  179. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  180. rv.Set(reflect.ValueOf(v.List().(Unwrapper).ProtoUnwrap()).Elem())
  181. },
  182. mutable: func(p pointer) pref.Value {
  183. v := p.Apply(fieldOffset).AsValueOf(fs.Type)
  184. return conv.PBValueOf(v)
  185. },
  186. newField: func() pref.Value {
  187. return conv.New()
  188. },
  189. }
  190. }
  191. var (
  192. nilBytes = reflect.ValueOf([]byte(nil))
  193. emptyBytes = reflect.ValueOf([]byte{})
  194. )
  195. func fieldInfoForScalar(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
  196. ft := fs.Type
  197. nullable := fd.Syntax() == pref.Proto2
  198. isBytes := ft.Kind() == reflect.Slice && ft.Elem().Kind() == reflect.Uint8
  199. if nullable {
  200. if ft.Kind() != reflect.Ptr && ft.Kind() != reflect.Slice {
  201. panic(fmt.Sprintf("invalid type: got %v, want pointer", ft))
  202. }
  203. if ft.Kind() == reflect.Ptr {
  204. ft = ft.Elem()
  205. }
  206. }
  207. conv := NewConverter(ft, fd)
  208. // TODO: Implement unsafe fast path?
  209. fieldOffset := offsetOf(fs, x)
  210. return fieldInfo{
  211. fieldDesc: fd,
  212. has: func(p pointer) bool {
  213. if p.IsNil() {
  214. return false
  215. }
  216. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  217. if nullable {
  218. return !rv.IsNil()
  219. }
  220. switch rv.Kind() {
  221. case reflect.Bool:
  222. return rv.Bool()
  223. case reflect.Int32, reflect.Int64:
  224. return rv.Int() != 0
  225. case reflect.Uint32, reflect.Uint64:
  226. return rv.Uint() != 0
  227. case reflect.Float32, reflect.Float64:
  228. return rv.Float() != 0 || math.Signbit(rv.Float())
  229. case reflect.String, reflect.Slice:
  230. return rv.Len() > 0
  231. default:
  232. panic(fmt.Sprintf("invalid type: %v", rv.Type())) // should never happen
  233. }
  234. },
  235. clear: func(p pointer) {
  236. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  237. rv.Set(reflect.Zero(rv.Type()))
  238. },
  239. get: func(p pointer) pref.Value {
  240. if p.IsNil() {
  241. return conv.Zero()
  242. }
  243. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  244. if nullable {
  245. if rv.IsNil() {
  246. return conv.Zero()
  247. }
  248. if rv.Kind() == reflect.Ptr {
  249. rv = rv.Elem()
  250. }
  251. }
  252. return conv.PBValueOf(rv)
  253. },
  254. set: func(p pointer, v pref.Value) {
  255. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  256. if nullable && rv.Kind() == reflect.Ptr {
  257. if rv.IsNil() {
  258. rv.Set(reflect.New(ft))
  259. }
  260. rv = rv.Elem()
  261. }
  262. rv.Set(conv.GoValueOf(v))
  263. if isBytes && rv.Len() == 0 {
  264. if nullable {
  265. rv.Set(emptyBytes) // preserve presence in proto2
  266. } else {
  267. rv.Set(nilBytes) // do not preserve presence in proto3
  268. }
  269. }
  270. },
  271. newField: func() pref.Value {
  272. return conv.New()
  273. },
  274. }
  275. }
  276. func fieldInfoForWeakMessage(fd pref.FieldDescriptor, weakOffset offset) fieldInfo {
  277. if !flags.ProtoLegacy {
  278. panic("no support for proto1 weak fields")
  279. }
  280. var once sync.Once
  281. var messageType pref.MessageType
  282. lazyInit := func() {
  283. once.Do(func() {
  284. messageName := fd.Message().FullName()
  285. messageType, _ = preg.GlobalTypes.FindMessageByName(messageName)
  286. if messageType == nil {
  287. panic(fmt.Sprintf("weak message %v is not linked in", messageName))
  288. }
  289. })
  290. }
  291. num := int32(fd.Number())
  292. return fieldInfo{
  293. fieldDesc: fd,
  294. has: func(p pointer) bool {
  295. if p.IsNil() {
  296. return false
  297. }
  298. fs := p.Apply(weakOffset).WeakFields()
  299. _, ok := (*fs)[num]
  300. return ok
  301. },
  302. clear: func(p pointer) {
  303. fs := p.Apply(weakOffset).WeakFields()
  304. delete(*fs, num)
  305. },
  306. get: func(p pointer) pref.Value {
  307. lazyInit()
  308. if p.IsNil() {
  309. return pref.ValueOf(messageType.Zero())
  310. }
  311. fs := p.Apply(weakOffset).WeakFields()
  312. m, ok := (*fs)[num]
  313. if !ok {
  314. return pref.ValueOf(messageType.Zero())
  315. }
  316. return pref.ValueOf(m.(pref.ProtoMessage).ProtoReflect())
  317. },
  318. set: func(p pointer, v pref.Value) {
  319. lazyInit()
  320. m := v.Message()
  321. if m.Descriptor() != messageType.Descriptor() {
  322. panic("mismatching message descriptor")
  323. }
  324. fs := p.Apply(weakOffset).WeakFields()
  325. if *fs == nil {
  326. *fs = make(WeakFields)
  327. }
  328. (*fs)[num] = m.Interface().(piface.MessageV1)
  329. },
  330. mutable: func(p pointer) pref.Value {
  331. lazyInit()
  332. fs := p.Apply(weakOffset).WeakFields()
  333. if *fs == nil {
  334. *fs = make(WeakFields)
  335. }
  336. m, ok := (*fs)[num]
  337. if !ok {
  338. m = messageType.New().Interface().(piface.MessageV1)
  339. (*fs)[num] = m
  340. }
  341. return pref.ValueOf(m.(pref.ProtoMessage).ProtoReflect())
  342. },
  343. newMessage: func() pref.Message {
  344. lazyInit()
  345. return messageType.New()
  346. },
  347. newField: func() pref.Value {
  348. lazyInit()
  349. return pref.ValueOf(messageType.New())
  350. },
  351. }
  352. }
  353. func fieldInfoForMessage(fd pref.FieldDescriptor, fs reflect.StructField, x exporter) fieldInfo {
  354. ft := fs.Type
  355. conv := NewConverter(ft, fd)
  356. // TODO: Implement unsafe fast path?
  357. fieldOffset := offsetOf(fs, x)
  358. return fieldInfo{
  359. fieldDesc: fd,
  360. has: func(p pointer) bool {
  361. if p.IsNil() {
  362. return false
  363. }
  364. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  365. return !rv.IsNil()
  366. },
  367. clear: func(p pointer) {
  368. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  369. rv.Set(reflect.Zero(rv.Type()))
  370. },
  371. get: func(p pointer) pref.Value {
  372. if p.IsNil() {
  373. return conv.Zero()
  374. }
  375. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  376. return conv.PBValueOf(rv)
  377. },
  378. set: func(p pointer, v pref.Value) {
  379. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  380. rv.Set(conv.GoValueOf(v))
  381. if rv.IsNil() {
  382. panic("invalid nil pointer")
  383. }
  384. },
  385. mutable: func(p pointer) pref.Value {
  386. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  387. if rv.IsNil() {
  388. rv.Set(conv.GoValueOf(conv.New()))
  389. }
  390. return conv.PBValueOf(rv)
  391. },
  392. newMessage: func() pref.Message {
  393. return conv.New().Message()
  394. },
  395. newField: func() pref.Value {
  396. return conv.New()
  397. },
  398. }
  399. }
  400. type oneofInfo struct {
  401. oneofDesc pref.OneofDescriptor
  402. which func(pointer) pref.FieldNumber
  403. }
  404. func makeOneofInfo(od pref.OneofDescriptor, fs reflect.StructField, x exporter, wrappersByType map[reflect.Type]pref.FieldNumber) *oneofInfo {
  405. fieldOffset := offsetOf(fs, x)
  406. return &oneofInfo{
  407. oneofDesc: od,
  408. which: func(p pointer) pref.FieldNumber {
  409. if p.IsNil() {
  410. return 0
  411. }
  412. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  413. if rv.IsNil() {
  414. return 0
  415. }
  416. return wrappersByType[rv.Elem().Type().Elem()]
  417. },
  418. }
  419. }