message_opaque.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598
  1. // Copyright 2024 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. "strings"
  10. "sync/atomic"
  11. "google.golang.org/protobuf/internal/filedesc"
  12. "google.golang.org/protobuf/reflect/protoreflect"
  13. )
  14. type opaqueStructInfo struct {
  15. structInfo
  16. }
  17. // isOpaque determines whether a protobuf message type is on the Opaque API. It
  18. // checks whether the type is a Go struct that protoc-gen-go would generate.
  19. //
  20. // This function only detects newly generated messages from the v2
  21. // implementation of protoc-gen-go. It is unable to classify generated messages
  22. // that are too old or those that are generated by a different generator
  23. // such as protoc-gen-gogo.
  24. func isOpaque(t reflect.Type) bool {
  25. // The current detection mechanism is to simply check the first field
  26. // for a struct tag with the "protogen" key.
  27. if t.Kind() == reflect.Struct && t.NumField() > 0 {
  28. pgt := t.Field(0).Tag.Get("protogen")
  29. return strings.HasPrefix(pgt, "opaque.")
  30. }
  31. return false
  32. }
  33. func opaqueInitHook(mi *MessageInfo) bool {
  34. mt := mi.GoReflectType.Elem()
  35. si := opaqueStructInfo{
  36. structInfo: mi.makeStructInfo(mt),
  37. }
  38. if !isOpaque(mt) {
  39. return false
  40. }
  41. defer atomic.StoreUint32(&mi.initDone, 1)
  42. mi.fields = map[protoreflect.FieldNumber]*fieldInfo{}
  43. fds := mi.Desc.Fields()
  44. for i := 0; i < fds.Len(); i++ {
  45. fd := fds.Get(i)
  46. fs := si.fieldsByNumber[fd.Number()]
  47. var fi fieldInfo
  48. usePresence, _ := filedesc.UsePresenceForField(fd)
  49. switch {
  50. case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
  51. // Oneofs are no different for opaque.
  52. fi = fieldInfoForOneof(fd, si.oneofsByName[fd.ContainingOneof().Name()], mi.Exporter, si.oneofWrappersByNumber[fd.Number()])
  53. case fd.IsMap():
  54. fi = mi.fieldInfoForMapOpaque(si, fd, fs)
  55. case fd.IsList() && fd.Message() == nil && usePresence:
  56. fi = mi.fieldInfoForScalarListOpaque(si, fd, fs)
  57. case fd.IsList() && fd.Message() == nil:
  58. // Proto3 lists without presence can use same access methods as open
  59. fi = fieldInfoForList(fd, fs, mi.Exporter)
  60. case fd.IsList() && usePresence:
  61. fi = mi.fieldInfoForMessageListOpaque(si, fd, fs)
  62. case fd.IsList():
  63. // Proto3 opaque messages that does not need presence bitmap.
  64. // Different representation than open struct, but same logic
  65. fi = mi.fieldInfoForMessageListOpaqueNoPresence(si, fd, fs)
  66. case fd.Message() != nil && usePresence:
  67. fi = mi.fieldInfoForMessageOpaque(si, fd, fs)
  68. case fd.Message() != nil:
  69. // Proto3 messages without presence can use same access methods as open
  70. fi = fieldInfoForMessage(fd, fs, mi.Exporter)
  71. default:
  72. fi = mi.fieldInfoForScalarOpaque(si, fd, fs)
  73. }
  74. mi.fields[fd.Number()] = &fi
  75. }
  76. mi.oneofs = map[protoreflect.Name]*oneofInfo{}
  77. for i := 0; i < mi.Desc.Oneofs().Len(); i++ {
  78. od := mi.Desc.Oneofs().Get(i)
  79. mi.oneofs[od.Name()] = makeOneofInfoOpaque(mi, od, si.structInfo, mi.Exporter)
  80. }
  81. mi.denseFields = make([]*fieldInfo, fds.Len()*2)
  82. for i := 0; i < fds.Len(); i++ {
  83. if fd := fds.Get(i); int(fd.Number()) < len(mi.denseFields) {
  84. mi.denseFields[fd.Number()] = mi.fields[fd.Number()]
  85. }
  86. }
  87. for i := 0; i < fds.Len(); {
  88. fd := fds.Get(i)
  89. if od := fd.ContainingOneof(); od != nil && !fd.ContainingOneof().IsSynthetic() {
  90. mi.rangeInfos = append(mi.rangeInfos, mi.oneofs[od.Name()])
  91. i += od.Fields().Len()
  92. } else {
  93. mi.rangeInfos = append(mi.rangeInfos, mi.fields[fd.Number()])
  94. i++
  95. }
  96. }
  97. mi.makeExtensionFieldsFunc(mt, si.structInfo)
  98. mi.makeUnknownFieldsFunc(mt, si.structInfo)
  99. mi.makeOpaqueCoderMethods(mt, si)
  100. mi.makeFieldTypes(si.structInfo)
  101. return true
  102. }
  103. func makeOneofInfoOpaque(mi *MessageInfo, od protoreflect.OneofDescriptor, si structInfo, x exporter) *oneofInfo {
  104. oi := &oneofInfo{oneofDesc: od}
  105. if od.IsSynthetic() {
  106. fd := od.Fields().Get(0)
  107. index, _ := presenceIndex(mi.Desc, fd)
  108. oi.which = func(p pointer) protoreflect.FieldNumber {
  109. if p.IsNil() {
  110. return 0
  111. }
  112. if !mi.present(p, index) {
  113. return 0
  114. }
  115. return od.Fields().Get(0).Number()
  116. }
  117. return oi
  118. }
  119. // Dispatch to non-opaque oneof implementation for non-synthetic oneofs.
  120. return makeOneofInfo(od, si, x)
  121. }
  122. func (mi *MessageInfo) fieldInfoForMapOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo {
  123. ft := fs.Type
  124. if ft.Kind() != reflect.Map {
  125. panic(fmt.Sprintf("invalid type: got %v, want map kind", ft))
  126. }
  127. fieldOffset := offsetOf(fs)
  128. conv := NewConverter(ft, fd)
  129. return fieldInfo{
  130. fieldDesc: fd,
  131. has: func(p pointer) bool {
  132. if p.IsNil() {
  133. return false
  134. }
  135. // Don't bother checking presence bits, since we need to
  136. // look at the map length even if the presence bit is set.
  137. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  138. return rv.Len() > 0
  139. },
  140. clear: func(p pointer) {
  141. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  142. rv.Set(reflect.Zero(rv.Type()))
  143. },
  144. get: func(p pointer) protoreflect.Value {
  145. if p.IsNil() {
  146. return conv.Zero()
  147. }
  148. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  149. if rv.Len() == 0 {
  150. return conv.Zero()
  151. }
  152. return conv.PBValueOf(rv)
  153. },
  154. set: func(p pointer, v protoreflect.Value) {
  155. pv := conv.GoValueOf(v)
  156. if pv.IsNil() {
  157. panic(fmt.Sprintf("invalid value: setting map field to read-only value"))
  158. }
  159. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  160. rv.Set(pv)
  161. },
  162. mutable: func(p pointer) protoreflect.Value {
  163. v := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  164. if v.IsNil() {
  165. v.Set(reflect.MakeMap(fs.Type))
  166. }
  167. return conv.PBValueOf(v)
  168. },
  169. newField: func() protoreflect.Value {
  170. return conv.New()
  171. },
  172. }
  173. }
  174. func (mi *MessageInfo) fieldInfoForScalarListOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo {
  175. ft := fs.Type
  176. if ft.Kind() != reflect.Slice {
  177. panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
  178. }
  179. conv := NewConverter(reflect.PtrTo(ft), fd)
  180. fieldOffset := offsetOf(fs)
  181. index, _ := presenceIndex(mi.Desc, fd)
  182. return fieldInfo{
  183. fieldDesc: fd,
  184. has: func(p pointer) bool {
  185. if p.IsNil() {
  186. return false
  187. }
  188. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  189. return rv.Len() > 0
  190. },
  191. clear: func(p pointer) {
  192. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  193. rv.Set(reflect.Zero(rv.Type()))
  194. },
  195. get: func(p pointer) protoreflect.Value {
  196. if p.IsNil() {
  197. return conv.Zero()
  198. }
  199. rv := p.Apply(fieldOffset).AsValueOf(fs.Type)
  200. if rv.Elem().Len() == 0 {
  201. return conv.Zero()
  202. }
  203. return conv.PBValueOf(rv)
  204. },
  205. set: func(p pointer, v protoreflect.Value) {
  206. pv := conv.GoValueOf(v)
  207. if pv.IsNil() {
  208. panic(fmt.Sprintf("invalid value: setting repeated field to read-only value"))
  209. }
  210. mi.setPresent(p, index)
  211. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  212. rv.Set(pv.Elem())
  213. },
  214. mutable: func(p pointer) protoreflect.Value {
  215. mi.setPresent(p, index)
  216. return conv.PBValueOf(p.Apply(fieldOffset).AsValueOf(fs.Type))
  217. },
  218. newField: func() protoreflect.Value {
  219. return conv.New()
  220. },
  221. }
  222. }
  223. func (mi *MessageInfo) fieldInfoForMessageListOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo {
  224. ft := fs.Type
  225. if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
  226. panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
  227. }
  228. conv := NewConverter(ft, fd)
  229. fieldOffset := offsetOf(fs)
  230. index, _ := presenceIndex(mi.Desc, fd)
  231. fieldNumber := fd.Number()
  232. return fieldInfo{
  233. fieldDesc: fd,
  234. has: func(p pointer) bool {
  235. if p.IsNil() {
  236. return false
  237. }
  238. if !mi.present(p, index) {
  239. return false
  240. }
  241. sp := p.Apply(fieldOffset).AtomicGetPointer()
  242. if sp.IsNil() {
  243. // Lazily unmarshal this field.
  244. mi.lazyUnmarshal(p, fieldNumber)
  245. sp = p.Apply(fieldOffset).AtomicGetPointer()
  246. }
  247. rv := sp.AsValueOf(fs.Type.Elem())
  248. return rv.Elem().Len() > 0
  249. },
  250. clear: func(p pointer) {
  251. fp := p.Apply(fieldOffset)
  252. sp := fp.AtomicGetPointer()
  253. if sp.IsNil() {
  254. sp = fp.AtomicSetPointerIfNil(pointerOfValue(reflect.New(fs.Type.Elem())))
  255. mi.setPresent(p, index)
  256. }
  257. rv := sp.AsValueOf(fs.Type.Elem())
  258. rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
  259. },
  260. get: func(p pointer) protoreflect.Value {
  261. if p.IsNil() {
  262. return conv.Zero()
  263. }
  264. if !mi.present(p, index) {
  265. return conv.Zero()
  266. }
  267. sp := p.Apply(fieldOffset).AtomicGetPointer()
  268. if sp.IsNil() {
  269. // Lazily unmarshal this field.
  270. mi.lazyUnmarshal(p, fieldNumber)
  271. sp = p.Apply(fieldOffset).AtomicGetPointer()
  272. }
  273. rv := sp.AsValueOf(fs.Type.Elem())
  274. if rv.Elem().Len() == 0 {
  275. return conv.Zero()
  276. }
  277. return conv.PBValueOf(rv)
  278. },
  279. set: func(p pointer, v protoreflect.Value) {
  280. fp := p.Apply(fieldOffset)
  281. sp := fp.AtomicGetPointer()
  282. if sp.IsNil() {
  283. sp = fp.AtomicSetPointerIfNil(pointerOfValue(reflect.New(fs.Type.Elem())))
  284. mi.setPresent(p, index)
  285. }
  286. rv := sp.AsValueOf(fs.Type.Elem())
  287. val := conv.GoValueOf(v)
  288. if val.IsNil() {
  289. panic(fmt.Sprintf("invalid value: setting repeated field to read-only value"))
  290. } else {
  291. rv.Elem().Set(val.Elem())
  292. }
  293. },
  294. mutable: func(p pointer) protoreflect.Value {
  295. fp := p.Apply(fieldOffset)
  296. sp := fp.AtomicGetPointer()
  297. if sp.IsNil() {
  298. if mi.present(p, index) {
  299. // Lazily unmarshal this field.
  300. mi.lazyUnmarshal(p, fieldNumber)
  301. sp = p.Apply(fieldOffset).AtomicGetPointer()
  302. } else {
  303. sp = fp.AtomicSetPointerIfNil(pointerOfValue(reflect.New(fs.Type.Elem())))
  304. mi.setPresent(p, index)
  305. }
  306. }
  307. rv := sp.AsValueOf(fs.Type.Elem())
  308. return conv.PBValueOf(rv)
  309. },
  310. newField: func() protoreflect.Value {
  311. return conv.New()
  312. },
  313. }
  314. }
  315. func (mi *MessageInfo) fieldInfoForMessageListOpaqueNoPresence(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo {
  316. ft := fs.Type
  317. if ft.Kind() != reflect.Ptr || ft.Elem().Kind() != reflect.Slice {
  318. panic(fmt.Sprintf("invalid type: got %v, want slice kind", ft))
  319. }
  320. conv := NewConverter(ft, fd)
  321. fieldOffset := offsetOf(fs)
  322. return fieldInfo{
  323. fieldDesc: fd,
  324. has: func(p pointer) bool {
  325. if p.IsNil() {
  326. return false
  327. }
  328. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  329. if rv.IsNil() {
  330. return false
  331. }
  332. return rv.Elem().Len() > 0
  333. },
  334. clear: func(p pointer) {
  335. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  336. if !rv.IsNil() {
  337. rv.Elem().Set(reflect.Zero(rv.Type().Elem()))
  338. }
  339. },
  340. get: func(p pointer) protoreflect.Value {
  341. if p.IsNil() {
  342. return conv.Zero()
  343. }
  344. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  345. if rv.IsNil() {
  346. return conv.Zero()
  347. }
  348. if rv.Elem().Len() == 0 {
  349. return conv.Zero()
  350. }
  351. return conv.PBValueOf(rv)
  352. },
  353. set: func(p pointer, v protoreflect.Value) {
  354. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  355. if rv.IsNil() {
  356. rv.Set(reflect.New(fs.Type.Elem()))
  357. }
  358. val := conv.GoValueOf(v)
  359. if val.IsNil() {
  360. panic(fmt.Sprintf("invalid value: setting repeated field to read-only value"))
  361. } else {
  362. rv.Elem().Set(val.Elem())
  363. }
  364. },
  365. mutable: func(p pointer) protoreflect.Value {
  366. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  367. if rv.IsNil() {
  368. rv.Set(reflect.New(fs.Type.Elem()))
  369. }
  370. return conv.PBValueOf(rv)
  371. },
  372. newField: func() protoreflect.Value {
  373. return conv.New()
  374. },
  375. }
  376. }
  377. func (mi *MessageInfo) fieldInfoForScalarOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo {
  378. ft := fs.Type
  379. nullable := fd.HasPresence()
  380. if oneof := fd.ContainingOneof(); oneof != nil && oneof.IsSynthetic() {
  381. nullable = true
  382. }
  383. deref := false
  384. if nullable && ft.Kind() == reflect.Ptr {
  385. ft = ft.Elem()
  386. deref = true
  387. }
  388. conv := NewConverter(ft, fd)
  389. fieldOffset := offsetOf(fs)
  390. index, _ := presenceIndex(mi.Desc, fd)
  391. var getter func(p pointer) protoreflect.Value
  392. if !nullable {
  393. getter = getterForDirectScalar(fd, fs, conv, fieldOffset)
  394. } else {
  395. getter = getterForOpaqueNullableScalar(mi, index, fd, fs, conv, fieldOffset)
  396. }
  397. return fieldInfo{
  398. fieldDesc: fd,
  399. has: func(p pointer) bool {
  400. if p.IsNil() {
  401. return false
  402. }
  403. if nullable {
  404. return mi.present(p, index)
  405. }
  406. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  407. switch rv.Kind() {
  408. case reflect.Bool:
  409. return rv.Bool()
  410. case reflect.Int32, reflect.Int64:
  411. return rv.Int() != 0
  412. case reflect.Uint32, reflect.Uint64:
  413. return rv.Uint() != 0
  414. case reflect.Float32, reflect.Float64:
  415. return rv.Float() != 0 || math.Signbit(rv.Float())
  416. case reflect.String, reflect.Slice:
  417. return rv.Len() > 0
  418. default:
  419. panic(fmt.Sprintf("invalid type: %v", rv.Type())) // should never happen
  420. }
  421. },
  422. clear: func(p pointer) {
  423. if nullable {
  424. mi.clearPresent(p, index)
  425. }
  426. // This is only valuable for bytes and strings, but we do it unconditionally.
  427. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  428. rv.Set(reflect.Zero(rv.Type()))
  429. },
  430. get: getter,
  431. // TODO: Implement unsafe fast path for set?
  432. set: func(p pointer, v protoreflect.Value) {
  433. rv := p.Apply(fieldOffset).AsValueOf(fs.Type).Elem()
  434. if deref {
  435. if rv.IsNil() {
  436. rv.Set(reflect.New(ft))
  437. }
  438. rv = rv.Elem()
  439. }
  440. rv.Set(conv.GoValueOf(v))
  441. if nullable && rv.Kind() == reflect.Slice && rv.IsNil() {
  442. rv.Set(emptyBytes)
  443. }
  444. if nullable {
  445. mi.setPresent(p, index)
  446. }
  447. },
  448. newField: func() protoreflect.Value {
  449. return conv.New()
  450. },
  451. }
  452. }
  453. func (mi *MessageInfo) fieldInfoForMessageOpaque(si opaqueStructInfo, fd protoreflect.FieldDescriptor, fs reflect.StructField) fieldInfo {
  454. ft := fs.Type
  455. conv := NewConverter(ft, fd)
  456. fieldOffset := offsetOf(fs)
  457. index, _ := presenceIndex(mi.Desc, fd)
  458. fieldNumber := fd.Number()
  459. elemType := fs.Type.Elem()
  460. return fieldInfo{
  461. fieldDesc: fd,
  462. has: func(p pointer) bool {
  463. if p.IsNil() {
  464. return false
  465. }
  466. return mi.present(p, index)
  467. },
  468. clear: func(p pointer) {
  469. mi.clearPresent(p, index)
  470. p.Apply(fieldOffset).AtomicSetNilPointer()
  471. },
  472. get: func(p pointer) protoreflect.Value {
  473. if p.IsNil() || !mi.present(p, index) {
  474. return conv.Zero()
  475. }
  476. fp := p.Apply(fieldOffset)
  477. mp := fp.AtomicGetPointer()
  478. if mp.IsNil() {
  479. // Lazily unmarshal this field.
  480. mi.lazyUnmarshal(p, fieldNumber)
  481. mp = fp.AtomicGetPointer()
  482. }
  483. rv := mp.AsValueOf(elemType)
  484. return conv.PBValueOf(rv)
  485. },
  486. set: func(p pointer, v protoreflect.Value) {
  487. val := pointerOfValue(conv.GoValueOf(v))
  488. if val.IsNil() {
  489. panic("invalid nil pointer")
  490. }
  491. p.Apply(fieldOffset).AtomicSetPointer(val)
  492. mi.setPresent(p, index)
  493. },
  494. mutable: func(p pointer) protoreflect.Value {
  495. fp := p.Apply(fieldOffset)
  496. mp := fp.AtomicGetPointer()
  497. if mp.IsNil() {
  498. if mi.present(p, index) {
  499. // Lazily unmarshal this field.
  500. mi.lazyUnmarshal(p, fieldNumber)
  501. mp = fp.AtomicGetPointer()
  502. } else {
  503. mp = pointerOfValue(conv.GoValueOf(conv.New()))
  504. fp.AtomicSetPointer(mp)
  505. mi.setPresent(p, index)
  506. }
  507. }
  508. return conv.PBValueOf(mp.AsValueOf(fs.Type.Elem()))
  509. },
  510. newMessage: func() protoreflect.Message {
  511. return conv.New().Message()
  512. },
  513. newField: func() protoreflect.Value {
  514. return conv.New()
  515. },
  516. }
  517. }
  518. // A presenceList wraps a List, updating presence bits as necessary when the
  519. // list contents change.
  520. type presenceList struct {
  521. pvalueList
  522. setPresence func(bool)
  523. }
  524. type pvalueList interface {
  525. protoreflect.List
  526. //Unwrapper
  527. }
  528. func (list presenceList) Append(v protoreflect.Value) {
  529. list.pvalueList.Append(v)
  530. list.setPresence(true)
  531. }
  532. func (list presenceList) Truncate(i int) {
  533. list.pvalueList.Truncate(i)
  534. list.setPresence(i > 0)
  535. }
  536. // presenceIndex returns the index to pass to presence functions.
  537. //
  538. // TODO: field.Desc.Index() would be simpler, and would give space to record the presence of oneof fields.
  539. func presenceIndex(md protoreflect.MessageDescriptor, fd protoreflect.FieldDescriptor) (uint32, presenceSize) {
  540. found := false
  541. var index, numIndices uint32
  542. for i := 0; i < md.Fields().Len(); i++ {
  543. f := md.Fields().Get(i)
  544. if f == fd {
  545. found = true
  546. index = numIndices
  547. }
  548. if f.ContainingOneof() == nil || isLastOneofField(f) {
  549. numIndices++
  550. }
  551. }
  552. if !found {
  553. panic(fmt.Sprintf("BUG: %v not in %v", fd.Name(), md.FullName()))
  554. }
  555. return index, presenceSize(numIndices)
  556. }
  557. func isLastOneofField(fd protoreflect.FieldDescriptor) bool {
  558. fields := fd.ContainingOneof().Fields()
  559. return fields.Get(fields.Len()-1) == fd
  560. }
  561. func (mi *MessageInfo) setPresent(p pointer, index uint32) {
  562. p.Apply(mi.presenceOffset).PresenceInfo().SetPresent(index, mi.presenceSize)
  563. }
  564. func (mi *MessageInfo) clearPresent(p pointer, index uint32) {
  565. p.Apply(mi.presenceOffset).PresenceInfo().ClearPresent(index)
  566. }
  567. func (mi *MessageInfo) present(p pointer, index uint32) bool {
  568. return p.Apply(mi.presenceOffset).PresenceInfo().Present(index)
  569. }