codec_message.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. // Copyright 2019 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/fieldsort"
  12. pref "google.golang.org/protobuf/reflect/protoreflect"
  13. piface "google.golang.org/protobuf/runtime/protoiface"
  14. )
  15. // coderMessageInfo contains per-message information used by the fast-path functions.
  16. // This is a different type from MessageInfo to keep MessageInfo as general-purpose as
  17. // possible.
  18. type coderMessageInfo struct {
  19. methods piface.Methods
  20. orderedCoderFields []*coderFieldInfo
  21. denseCoderFields []*coderFieldInfo
  22. coderFields map[protowire.Number]*coderFieldInfo
  23. sizecacheOffset offset
  24. unknownOffset offset
  25. extensionOffset offset
  26. needsInitCheck bool
  27. isMessageSet bool
  28. numRequiredFields uint8
  29. }
  30. type coderFieldInfo struct {
  31. funcs pointerCoderFuncs // fast-path per-field functions
  32. mi *MessageInfo // field's message
  33. ft reflect.Type
  34. validation validationInfo // information used by message validation
  35. num pref.FieldNumber // field number
  36. offset offset // struct field offset
  37. wiretag uint64 // field tag (number + wire type)
  38. tagsize int // size of the varint-encoded tag
  39. isPointer bool // true if IsNil may be called on the struct field
  40. isRequired bool // true if field is required
  41. }
  42. func (mi *MessageInfo) makeCoderMethods(t reflect.Type, si structInfo) {
  43. mi.sizecacheOffset = si.sizecacheOffset
  44. mi.unknownOffset = si.unknownOffset
  45. mi.extensionOffset = si.extensionOffset
  46. mi.coderFields = make(map[protowire.Number]*coderFieldInfo)
  47. fields := mi.Desc.Fields()
  48. preallocFields := make([]coderFieldInfo, fields.Len())
  49. for i := 0; i < fields.Len(); i++ {
  50. fd := fields.Get(i)
  51. fs := si.fieldsByNumber[fd.Number()]
  52. isOneof := fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic()
  53. if isOneof {
  54. fs = si.oneofsByName[fd.ContainingOneof().Name()]
  55. }
  56. ft := fs.Type
  57. var wiretag uint64
  58. if !fd.IsPacked() {
  59. wiretag = protowire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
  60. } else {
  61. wiretag = protowire.EncodeTag(fd.Number(), protowire.BytesType)
  62. }
  63. var fieldOffset offset
  64. var funcs pointerCoderFuncs
  65. var childMessage *MessageInfo
  66. switch {
  67. case isOneof:
  68. fieldOffset = offsetOf(fs, mi.Exporter)
  69. case fd.IsWeak():
  70. fieldOffset = si.weakOffset
  71. funcs = makeWeakMessageFieldCoder(fd)
  72. default:
  73. fieldOffset = offsetOf(fs, mi.Exporter)
  74. childMessage, funcs = fieldCoder(fd, ft)
  75. }
  76. cf := &preallocFields[i]
  77. *cf = coderFieldInfo{
  78. num: fd.Number(),
  79. offset: fieldOffset,
  80. wiretag: wiretag,
  81. ft: ft,
  82. tagsize: protowire.SizeVarint(wiretag),
  83. funcs: funcs,
  84. mi: childMessage,
  85. validation: newFieldValidationInfo(mi, si, fd, ft),
  86. isPointer: fd.Cardinality() == pref.Repeated || fd.HasPresence(),
  87. isRequired: fd.Cardinality() == pref.Required,
  88. }
  89. mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
  90. mi.coderFields[cf.num] = cf
  91. }
  92. for i, oneofs := 0, mi.Desc.Oneofs(); i < oneofs.Len(); i++ {
  93. if od := oneofs.Get(i); !od.IsSynthetic() {
  94. mi.initOneofFieldCoders(od, si)
  95. }
  96. }
  97. if messageset.IsMessageSet(mi.Desc) {
  98. if !mi.extensionOffset.IsValid() {
  99. panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.Desc.FullName()))
  100. }
  101. if !mi.unknownOffset.IsValid() {
  102. panic(fmt.Sprintf("%v: MessageSet with no unknown field", mi.Desc.FullName()))
  103. }
  104. mi.isMessageSet = true
  105. }
  106. sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
  107. return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
  108. })
  109. var maxDense pref.FieldNumber
  110. for _, cf := range mi.orderedCoderFields {
  111. if cf.num >= 16 && cf.num >= 2*maxDense {
  112. break
  113. }
  114. maxDense = cf.num
  115. }
  116. mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
  117. for _, cf := range mi.orderedCoderFields {
  118. if int(cf.num) >= len(mi.denseCoderFields) {
  119. break
  120. }
  121. mi.denseCoderFields[cf.num] = cf
  122. }
  123. // To preserve compatibility with historic wire output, marshal oneofs last.
  124. if mi.Desc.Oneofs().Len() > 0 {
  125. sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
  126. fi := fields.ByNumber(mi.orderedCoderFields[i].num)
  127. fj := fields.ByNumber(mi.orderedCoderFields[j].num)
  128. return fieldsort.Less(fi, fj)
  129. })
  130. }
  131. mi.needsInitCheck = needsInitCheck(mi.Desc)
  132. if mi.methods.Marshal == nil && mi.methods.Size == nil {
  133. mi.methods.Flags |= piface.SupportMarshalDeterministic
  134. mi.methods.Marshal = mi.marshal
  135. mi.methods.Size = mi.size
  136. }
  137. if mi.methods.Unmarshal == nil {
  138. mi.methods.Flags |= piface.SupportUnmarshalDiscardUnknown
  139. mi.methods.Unmarshal = mi.unmarshal
  140. }
  141. if mi.methods.CheckInitialized == nil {
  142. mi.methods.CheckInitialized = mi.checkInitialized
  143. }
  144. if mi.methods.Merge == nil {
  145. mi.methods.Merge = mi.merge
  146. }
  147. }