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