codec_message_opaque.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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. "reflect"
  8. "sort"
  9. "google.golang.org/protobuf/encoding/protowire"
  10. "google.golang.org/protobuf/internal/encoding/messageset"
  11. "google.golang.org/protobuf/internal/filedesc"
  12. "google.golang.org/protobuf/internal/order"
  13. "google.golang.org/protobuf/reflect/protoreflect"
  14. piface "google.golang.org/protobuf/runtime/protoiface"
  15. )
  16. func (mi *MessageInfo) makeOpaqueCoderMethods(t reflect.Type, si opaqueStructInfo) {
  17. mi.sizecacheOffset = si.sizecacheOffset
  18. mi.unknownOffset = si.unknownOffset
  19. mi.unknownPtrKind = si.unknownType.Kind() == reflect.Ptr
  20. mi.extensionOffset = si.extensionOffset
  21. mi.lazyOffset = si.lazyOffset
  22. mi.presenceOffset = si.presenceOffset
  23. mi.coderFields = make(map[protowire.Number]*coderFieldInfo)
  24. fields := mi.Desc.Fields()
  25. for i := 0; i < fields.Len(); i++ {
  26. fd := fields.Get(i)
  27. fs := si.fieldsByNumber[fd.Number()]
  28. if fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic() {
  29. fs = si.oneofsByName[fd.ContainingOneof().Name()]
  30. }
  31. ft := fs.Type
  32. var wiretag uint64
  33. if !fd.IsPacked() {
  34. wiretag = protowire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
  35. } else {
  36. wiretag = protowire.EncodeTag(fd.Number(), protowire.BytesType)
  37. }
  38. var fieldOffset offset
  39. var funcs pointerCoderFuncs
  40. var childMessage *MessageInfo
  41. switch {
  42. case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
  43. fieldOffset = offsetOf(fs)
  44. case fd.Message() != nil && !fd.IsMap():
  45. fieldOffset = offsetOf(fs)
  46. if fd.IsList() {
  47. childMessage, funcs = makeOpaqueRepeatedMessageFieldCoder(fd, ft)
  48. } else {
  49. childMessage, funcs = makeOpaqueMessageFieldCoder(fd, ft)
  50. }
  51. default:
  52. fieldOffset = offsetOf(fs)
  53. childMessage, funcs = fieldCoder(fd, ft)
  54. }
  55. cf := &coderFieldInfo{
  56. num: fd.Number(),
  57. offset: fieldOffset,
  58. wiretag: wiretag,
  59. ft: ft,
  60. tagsize: protowire.SizeVarint(wiretag),
  61. funcs: funcs,
  62. mi: childMessage,
  63. validation: newFieldValidationInfo(mi, si.structInfo, fd, ft),
  64. isPointer: (fd.Cardinality() == protoreflect.Repeated ||
  65. fd.Kind() == protoreflect.MessageKind ||
  66. fd.Kind() == protoreflect.GroupKind),
  67. isRequired: fd.Cardinality() == protoreflect.Required,
  68. presenceIndex: noPresence,
  69. }
  70. // TODO: Use presence for all fields.
  71. //
  72. // In some cases, such as maps, presence means only "might be set" rather
  73. // than "is definitely set", but every field should have a presence bit to
  74. // permit us to skip over definitely-unset fields at marshal time.
  75. var hasPresence bool
  76. hasPresence, cf.isLazy = filedesc.UsePresenceForField(fd)
  77. if hasPresence {
  78. cf.presenceIndex, mi.presenceSize = presenceIndex(mi.Desc, fd)
  79. }
  80. mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
  81. mi.coderFields[cf.num] = cf
  82. }
  83. for i, oneofs := 0, mi.Desc.Oneofs(); i < oneofs.Len(); i++ {
  84. if od := oneofs.Get(i); !od.IsSynthetic() {
  85. mi.initOneofFieldCoders(od, si.structInfo)
  86. }
  87. }
  88. if messageset.IsMessageSet(mi.Desc) {
  89. if !mi.extensionOffset.IsValid() {
  90. panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.Desc.FullName()))
  91. }
  92. if !mi.unknownOffset.IsValid() {
  93. panic(fmt.Sprintf("%v: MessageSet with no unknown field", mi.Desc.FullName()))
  94. }
  95. mi.isMessageSet = true
  96. }
  97. sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
  98. return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
  99. })
  100. var maxDense protoreflect.FieldNumber
  101. for _, cf := range mi.orderedCoderFields {
  102. if cf.num >= 16 && cf.num >= 2*maxDense {
  103. break
  104. }
  105. maxDense = cf.num
  106. }
  107. mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
  108. for _, cf := range mi.orderedCoderFields {
  109. if int(cf.num) > len(mi.denseCoderFields) {
  110. break
  111. }
  112. mi.denseCoderFields[cf.num] = cf
  113. }
  114. // To preserve compatibility with historic wire output, marshal oneofs last.
  115. if mi.Desc.Oneofs().Len() > 0 {
  116. sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
  117. fi := fields.ByNumber(mi.orderedCoderFields[i].num)
  118. fj := fields.ByNumber(mi.orderedCoderFields[j].num)
  119. return order.LegacyFieldOrder(fi, fj)
  120. })
  121. }
  122. mi.needsInitCheck = needsInitCheck(mi.Desc)
  123. if mi.methods.Marshal == nil && mi.methods.Size == nil {
  124. mi.methods.Flags |= piface.SupportMarshalDeterministic
  125. mi.methods.Marshal = mi.marshal
  126. mi.methods.Size = mi.size
  127. }
  128. if mi.methods.Unmarshal == nil {
  129. mi.methods.Flags |= piface.SupportUnmarshalDiscardUnknown
  130. mi.methods.Unmarshal = mi.unmarshal
  131. }
  132. if mi.methods.CheckInitialized == nil {
  133. mi.methods.CheckInitialized = mi.checkInitialized
  134. }
  135. if mi.methods.Merge == nil {
  136. mi.methods.Merge = mi.merge
  137. }
  138. if mi.methods.Equal == nil {
  139. mi.methods.Equal = equal
  140. }
  141. }