PageRenderTime 45ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go

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