codec_message.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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/internal/encoding/messageset"
  10. "google.golang.org/protobuf/internal/encoding/wire"
  11. pref "google.golang.org/protobuf/reflect/protoreflect"
  12. piface "google.golang.org/protobuf/runtime/protoiface"
  13. )
  14. // coderMessageInfo contains per-message information used by the fast-path functions.
  15. // This is a different type from MessageInfo to keep MessageInfo as general-purpose as
  16. // possible.
  17. type coderMessageInfo struct {
  18. orderedCoderFields []*coderFieldInfo
  19. denseCoderFields []*coderFieldInfo
  20. coderFields map[wire.Number]*coderFieldInfo
  21. sizecacheOffset offset
  22. unknownOffset offset
  23. extensionOffset offset
  24. needsInitCheck bool
  25. }
  26. type coderFieldInfo struct {
  27. funcs pointerCoderFuncs // fast-path per-field functions
  28. num pref.FieldNumber // field number
  29. offset offset // struct field offset
  30. wiretag uint64 // field tag (number + wire type)
  31. tagsize int // size of the varint-encoded tag
  32. isPointer bool // true if IsNil may be called on the struct field
  33. isRequired bool // true if field is required
  34. }
  35. func (mi *MessageInfo) makeMethods(t reflect.Type, si structInfo) {
  36. mi.sizecacheOffset = si.sizecacheOffset
  37. mi.unknownOffset = si.unknownOffset
  38. mi.extensionOffset = si.extensionOffset
  39. mi.coderFields = make(map[wire.Number]*coderFieldInfo)
  40. for i := 0; i < mi.PBType.Fields().Len(); i++ {
  41. fd := mi.PBType.Fields().Get(i)
  42. fs := si.fieldsByNumber[fd.Number()]
  43. if fd.ContainingOneof() != nil {
  44. fs = si.oneofsByName[fd.ContainingOneof().Name()]
  45. }
  46. ft := fs.Type
  47. var wiretag uint64
  48. if !fd.IsPacked() {
  49. wiretag = wire.EncodeTag(fd.Number(), wireTypes[fd.Kind()])
  50. } else {
  51. wiretag = wire.EncodeTag(fd.Number(), wire.BytesType)
  52. }
  53. var funcs pointerCoderFuncs
  54. if fd.ContainingOneof() != nil {
  55. funcs = makeOneofFieldCoder(si, fd)
  56. } else {
  57. funcs = fieldCoder(fd, ft)
  58. }
  59. cf := &coderFieldInfo{
  60. num: fd.Number(),
  61. offset: offsetOf(fs, mi.Exporter),
  62. wiretag: wiretag,
  63. tagsize: wire.SizeVarint(wiretag),
  64. funcs: funcs,
  65. isPointer: (fd.Cardinality() == pref.Repeated ||
  66. fd.Kind() == pref.MessageKind ||
  67. fd.Kind() == pref.GroupKind ||
  68. fd.Syntax() != pref.Proto3),
  69. isRequired: fd.Cardinality() == pref.Required,
  70. }
  71. mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
  72. mi.coderFields[cf.num] = cf
  73. }
  74. if messageset.IsMessageSet(mi.PBType.Descriptor()) {
  75. if !mi.extensionOffset.IsValid() {
  76. panic(fmt.Sprintf("%v: MessageSet with no extensions field", mi.PBType.FullName()))
  77. }
  78. cf := &coderFieldInfo{
  79. num: messageset.FieldItem,
  80. offset: si.extensionOffset,
  81. isPointer: true,
  82. funcs: makeMessageSetFieldCoder(mi),
  83. }
  84. mi.orderedCoderFields = append(mi.orderedCoderFields, cf)
  85. mi.coderFields[cf.num] = cf
  86. // Invalidate the extension offset, since the field codec handles extensions.
  87. mi.extensionOffset = invalidOffset
  88. }
  89. sort.Slice(mi.orderedCoderFields, func(i, j int) bool {
  90. return mi.orderedCoderFields[i].num < mi.orderedCoderFields[j].num
  91. })
  92. var maxDense pref.FieldNumber
  93. for _, cf := range mi.orderedCoderFields {
  94. if cf.num >= 16 && cf.num >= 2*maxDense {
  95. break
  96. }
  97. maxDense = cf.num
  98. }
  99. mi.denseCoderFields = make([]*coderFieldInfo, maxDense+1)
  100. for _, cf := range mi.orderedCoderFields {
  101. if int(cf.num) > len(mi.denseCoderFields) {
  102. break
  103. }
  104. mi.denseCoderFields[cf.num] = cf
  105. }
  106. mi.needsInitCheck = needsInitCheck(mi.PBType)
  107. mi.methods = piface.Methods{
  108. Flags: piface.SupportMarshalDeterministic | piface.SupportUnmarshalDiscardUnknown,
  109. MarshalAppend: mi.marshalAppend,
  110. Unmarshal: mi.unmarshal,
  111. Size: mi.size,
  112. IsInitialized: mi.isInitialized,
  113. }
  114. }