You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

544 lines
15 KiB

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