1
2
3
4
5 package proto
6
7 import (
8 "google.golang.org/protobuf/encoding/protowire"
9 "google.golang.org/protobuf/internal/encoding/messageset"
10 "google.golang.org/protobuf/internal/order"
11 "google.golang.org/protobuf/internal/pragma"
12 "google.golang.org/protobuf/reflect/protoreflect"
13 "google.golang.org/protobuf/runtime/protoiface"
14 )
15
16
17
18
19
20
21 type MarshalOptions struct {
22 pragma.NoUnkeyedLiterals
23
24
25
26
27 AllowPartial bool
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50 Deterministic bool
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70 UseCachedSize bool
71 }
72
73
74 func Marshal(m Message) ([]byte, error) {
75
76 if m == nil {
77 return nil, nil
78 }
79
80 out, err := MarshalOptions{}.marshal(nil, m.ProtoReflect())
81 if len(out.Buf) == 0 && err == nil {
82 out.Buf = emptyBytesForMessage(m)
83 }
84 return out.Buf, err
85 }
86
87
88 func (o MarshalOptions) Marshal(m Message) ([]byte, error) {
89
90 if m == nil {
91 return nil, nil
92 }
93
94 out, err := o.marshal(nil, m.ProtoReflect())
95 if len(out.Buf) == 0 && err == nil {
96 out.Buf = emptyBytesForMessage(m)
97 }
98 return out.Buf, err
99 }
100
101
102
103
104
105
106
107
108
109
110 func emptyBytesForMessage(m Message) []byte {
111 if m == nil || !m.ProtoReflect().IsValid() {
112 return nil
113 }
114 return emptyBuf[:]
115 }
116
117
118
119 func (o MarshalOptions) MarshalAppend(b []byte, m Message) ([]byte, error) {
120
121 if m == nil {
122 return b, nil
123 }
124
125 out, err := o.marshal(b, m.ProtoReflect())
126 return out.Buf, err
127 }
128
129
130
131
132
133 func (o MarshalOptions) MarshalState(in protoiface.MarshalInput) (protoiface.MarshalOutput, error) {
134 return o.marshal(in.Buf, in.Message)
135 }
136
137
138
139
140 func (o MarshalOptions) marshal(b []byte, m protoreflect.Message) (out protoiface.MarshalOutput, err error) {
141 allowPartial := o.AllowPartial
142 o.AllowPartial = true
143 if methods := protoMethods(m); methods != nil && methods.Marshal != nil &&
144 !(o.Deterministic && methods.Flags&protoiface.SupportMarshalDeterministic == 0) {
145 in := protoiface.MarshalInput{
146 Message: m,
147 Buf: b,
148 }
149 if o.Deterministic {
150 in.Flags |= protoiface.MarshalDeterministic
151 }
152 if o.UseCachedSize {
153 in.Flags |= protoiface.MarshalUseCachedSize
154 }
155 if methods.Size != nil {
156 sout := methods.Size(protoiface.SizeInput{
157 Message: m,
158 Flags: in.Flags,
159 })
160 if cap(b) < len(b)+sout.Size {
161 in.Buf = make([]byte, len(b), growcap(cap(b), len(b)+sout.Size))
162 copy(in.Buf, b)
163 }
164 in.Flags |= protoiface.MarshalUseCachedSize
165 }
166 out, err = methods.Marshal(in)
167 } else {
168 out.Buf, err = o.marshalMessageSlow(b, m)
169 }
170 if err != nil {
171 return out, err
172 }
173 if allowPartial {
174 return out, nil
175 }
176 return out, checkInitialized(m)
177 }
178
179 func (o MarshalOptions) marshalMessage(b []byte, m protoreflect.Message) ([]byte, error) {
180 out, err := o.marshal(b, m)
181 return out.Buf, err
182 }
183
184
185
186
187
188
189
190 func growcap(oldcap, wantcap int) (newcap int) {
191 if wantcap > oldcap*2 {
192 newcap = wantcap
193 } else if oldcap < 1024 {
194
195
196
197 newcap = oldcap * 2
198 } else {
199 newcap = oldcap
200 for 0 < newcap && newcap < wantcap {
201 newcap += newcap / 4
202 }
203 if newcap <= 0 {
204 newcap = wantcap
205 }
206 }
207 return newcap
208 }
209
210 func (o MarshalOptions) marshalMessageSlow(b []byte, m protoreflect.Message) ([]byte, error) {
211 if messageset.IsMessageSet(m.Descriptor()) {
212 return o.marshalMessageSet(b, m)
213 }
214 fieldOrder := order.AnyFieldOrder
215 if o.Deterministic {
216
217
218
219 fieldOrder = order.LegacyFieldOrder
220 }
221 var err error
222 order.RangeFields(m, fieldOrder, func(fd protoreflect.FieldDescriptor, v protoreflect.Value) bool {
223 b, err = o.marshalField(b, fd, v)
224 return err == nil
225 })
226 if err != nil {
227 return b, err
228 }
229 b = append(b, m.GetUnknown()...)
230 return b, nil
231 }
232
233 func (o MarshalOptions) marshalField(b []byte, fd protoreflect.FieldDescriptor, value protoreflect.Value) ([]byte, error) {
234 switch {
235 case fd.IsList():
236 return o.marshalList(b, fd, value.List())
237 case fd.IsMap():
238 return o.marshalMap(b, fd, value.Map())
239 default:
240 b = protowire.AppendTag(b, fd.Number(), wireTypes[fd.Kind()])
241 return o.marshalSingular(b, fd, value)
242 }
243 }
244
245 func (o MarshalOptions) marshalList(b []byte, fd protoreflect.FieldDescriptor, list protoreflect.List) ([]byte, error) {
246 if fd.IsPacked() && list.Len() > 0 {
247 b = protowire.AppendTag(b, fd.Number(), protowire.BytesType)
248 b, pos := appendSpeculativeLength(b)
249 for i, llen := 0, list.Len(); i < llen; i++ {
250 var err error
251 b, err = o.marshalSingular(b, fd, list.Get(i))
252 if err != nil {
253 return b, err
254 }
255 }
256 b = finishSpeculativeLength(b, pos)
257 return b, nil
258 }
259
260 kind := fd.Kind()
261 for i, llen := 0, list.Len(); i < llen; i++ {
262 var err error
263 b = protowire.AppendTag(b, fd.Number(), wireTypes[kind])
264 b, err = o.marshalSingular(b, fd, list.Get(i))
265 if err != nil {
266 return b, err
267 }
268 }
269 return b, nil
270 }
271
272 func (o MarshalOptions) marshalMap(b []byte, fd protoreflect.FieldDescriptor, mapv protoreflect.Map) ([]byte, error) {
273 keyf := fd.MapKey()
274 valf := fd.MapValue()
275 keyOrder := order.AnyKeyOrder
276 if o.Deterministic {
277 keyOrder = order.GenericKeyOrder
278 }
279 var err error
280 order.RangeEntries(mapv, keyOrder, func(key protoreflect.MapKey, value protoreflect.Value) bool {
281 b = protowire.AppendTag(b, fd.Number(), protowire.BytesType)
282 var pos int
283 b, pos = appendSpeculativeLength(b)
284
285 b, err = o.marshalField(b, keyf, key.Value())
286 if err != nil {
287 return false
288 }
289 b, err = o.marshalField(b, valf, value)
290 if err != nil {
291 return false
292 }
293 b = finishSpeculativeLength(b, pos)
294 return true
295 })
296 return b, err
297 }
298
299
300
301
302 const speculativeLength = 1
303
304 func appendSpeculativeLength(b []byte) ([]byte, int) {
305 pos := len(b)
306 b = append(b, "\x00\x00\x00\x00"[:speculativeLength]...)
307 return b, pos
308 }
309
310 func finishSpeculativeLength(b []byte, pos int) []byte {
311 mlen := len(b) - pos - speculativeLength
312 msiz := protowire.SizeVarint(uint64(mlen))
313 if msiz != speculativeLength {
314 for i := 0; i < msiz-speculativeLength; i++ {
315 b = append(b, 0)
316 }
317 copy(b[pos+msiz:], b[pos+speculativeLength:])
318 b = b[:pos+msiz+mlen]
319 }
320 protowire.AppendVarint(b[:pos], uint64(mlen))
321 return b
322 }
323
View as plain text