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