|
1 // Copyright 2018 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 prototext |
|
6 |
|
7 import ( |
|
8 "fmt" |
|
9 "unicode/utf8" |
|
10 |
|
11 "google.golang.org/protobuf/internal/encoding/messageset" |
|
12 "google.golang.org/protobuf/internal/encoding/text" |
|
13 "google.golang.org/protobuf/internal/errors" |
|
14 "google.golang.org/protobuf/internal/flags" |
|
15 "google.golang.org/protobuf/internal/genid" |
|
16 "google.golang.org/protobuf/internal/pragma" |
|
17 "google.golang.org/protobuf/internal/set" |
|
18 "google.golang.org/protobuf/internal/strs" |
|
19 "google.golang.org/protobuf/proto" |
|
20 pref "google.golang.org/protobuf/reflect/protoreflect" |
|
21 "google.golang.org/protobuf/reflect/protoregistry" |
|
22 ) |
|
23 |
|
24 // Unmarshal reads the given []byte into the given proto.Message. |
|
25 // The provided message must be mutable (e.g., a non-nil pointer to a message). |
|
26 func Unmarshal(b []byte, m proto.Message) error { |
|
27 return UnmarshalOptions{}.Unmarshal(b, m) |
|
28 } |
|
29 |
|
30 // UnmarshalOptions is a configurable textproto format unmarshaler. |
|
31 type UnmarshalOptions struct { |
|
32 pragma.NoUnkeyedLiterals |
|
33 |
|
34 // AllowPartial accepts input for messages that will result in missing |
|
35 // required fields. If AllowPartial is false (the default), Unmarshal will |
|
36 // return error if there are any missing required fields. |
|
37 AllowPartial bool |
|
38 |
|
39 // DiscardUnknown specifies whether to ignore unknown fields when parsing. |
|
40 // An unknown field is any field whose field name or field number does not |
|
41 // resolve to any known or extension field in the message. |
|
42 // By default, unmarshal rejects unknown fields as an error. |
|
43 DiscardUnknown bool |
|
44 |
|
45 // Resolver is used for looking up types when unmarshaling |
|
46 // google.protobuf.Any messages or extension fields. |
|
47 // If nil, this defaults to using protoregistry.GlobalTypes. |
|
48 Resolver interface { |
|
49 protoregistry.MessageTypeResolver |
|
50 protoregistry.ExtensionTypeResolver |
|
51 } |
|
52 } |
|
53 |
|
54 // Unmarshal reads the given []byte and populates the given proto.Message |
|
55 // using options in the UnmarshalOptions object. |
|
56 // The provided message must be mutable (e.g., a non-nil pointer to a message). |
|
57 func (o UnmarshalOptions) Unmarshal(b []byte, m proto.Message) error { |
|
58 return o.unmarshal(b, m) |
|
59 } |
|
60 |
|
61 // unmarshal is a centralized function that all unmarshal operations go through. |
|
62 // For profiling purposes, avoid changing the name of this function or |
|
63 // introducing other code paths for unmarshal that do not go through this. |
|
64 func (o UnmarshalOptions) unmarshal(b []byte, m proto.Message) error { |
|
65 proto.Reset(m) |
|
66 |
|
67 if o.Resolver == nil { |
|
68 o.Resolver = protoregistry.GlobalTypes |
|
69 } |
|
70 |
|
71 dec := decoder{text.NewDecoder(b), o} |
|
72 if err := dec.unmarshalMessage(m.ProtoReflect(), false); err != nil { |
|
73 return err |
|
74 } |
|
75 if o.AllowPartial { |
|
76 return nil |
|
77 } |
|
78 return proto.CheckInitialized(m) |
|
79 } |
|
80 |
|
81 type decoder struct { |
|
82 *text.Decoder |
|
83 opts UnmarshalOptions |
|
84 } |
|
85 |
|
86 // newError returns an error object with position info. |
|
87 func (d decoder) newError(pos int, f string, x ...interface{}) error { |
|
88 line, column := d.Position(pos) |
|
89 head := fmt.Sprintf("(line %d:%d): ", line, column) |
|
90 return errors.New(head+f, x...) |
|
91 } |
|
92 |
|
93 // unexpectedTokenError returns a syntax error for the given unexpected token. |
|
94 func (d decoder) unexpectedTokenError(tok text.Token) error { |
|
95 return d.syntaxError(tok.Pos(), "unexpected token: %s", tok.RawString()) |
|
96 } |
|
97 |
|
98 // syntaxError returns a syntax error for given position. |
|
99 func (d decoder) syntaxError(pos int, f string, x ...interface{}) error { |
|
100 line, column := d.Position(pos) |
|
101 head := fmt.Sprintf("syntax error (line %d:%d): ", line, column) |
|
102 return errors.New(head+f, x...) |
|
103 } |
|
104 |
|
105 // unmarshalMessage unmarshals into the given protoreflect.Message. |
|
106 func (d decoder) unmarshalMessage(m pref.Message, checkDelims bool) error { |
|
107 messageDesc := m.Descriptor() |
|
108 if !flags.ProtoLegacy && messageset.IsMessageSet(messageDesc) { |
|
109 return errors.New("no support for proto1 MessageSets") |
|
110 } |
|
111 |
|
112 if messageDesc.FullName() == genid.Any_message_fullname { |
|
113 return d.unmarshalAny(m, checkDelims) |
|
114 } |
|
115 |
|
116 if checkDelims { |
|
117 tok, err := d.Read() |
|
118 if err != nil { |
|
119 return err |
|
120 } |
|
121 |
|
122 if tok.Kind() != text.MessageOpen { |
|
123 return d.unexpectedTokenError(tok) |
|
124 } |
|
125 } |
|
126 |
|
127 var seenNums set.Ints |
|
128 var seenOneofs set.Ints |
|
129 fieldDescs := messageDesc.Fields() |
|
130 |
|
131 for { |
|
132 // Read field name. |
|
133 tok, err := d.Read() |
|
134 if err != nil { |
|
135 return err |
|
136 } |
|
137 switch typ := tok.Kind(); typ { |
|
138 case text.Name: |
|
139 // Continue below. |
|
140 case text.EOF: |
|
141 if checkDelims { |
|
142 return text.ErrUnexpectedEOF |
|
143 } |
|
144 return nil |
|
145 default: |
|
146 if checkDelims && typ == text.MessageClose { |
|
147 return nil |
|
148 } |
|
149 return d.unexpectedTokenError(tok) |
|
150 } |
|
151 |
|
152 // Resolve the field descriptor. |
|
153 var name pref.Name |
|
154 var fd pref.FieldDescriptor |
|
155 var xt pref.ExtensionType |
|
156 var xtErr error |
|
157 var isFieldNumberName bool |
|
158 |
|
159 switch tok.NameKind() { |
|
160 case text.IdentName: |
|
161 name = pref.Name(tok.IdentName()) |
|
162 fd = fieldDescs.ByTextName(string(name)) |
|
163 |
|
164 case text.TypeName: |
|
165 // Handle extensions only. This code path is not for Any. |
|
166 xt, xtErr = d.opts.Resolver.FindExtensionByName(pref.FullName(tok.TypeName())) |
|
167 |
|
168 case text.FieldNumber: |
|
169 isFieldNumberName = true |
|
170 num := pref.FieldNumber(tok.FieldNumber()) |
|
171 if !num.IsValid() { |
|
172 return d.newError(tok.Pos(), "invalid field number: %d", num) |
|
173 } |
|
174 fd = fieldDescs.ByNumber(num) |
|
175 if fd == nil { |
|
176 xt, xtErr = d.opts.Resolver.FindExtensionByNumber(messageDesc.FullName(), num) |
|
177 } |
|
178 } |
|
179 |
|
180 if xt != nil { |
|
181 fd = xt.TypeDescriptor() |
|
182 if !messageDesc.ExtensionRanges().Has(fd.Number()) || fd.ContainingMessage().FullName() != messageDesc.FullName() { |
|
183 return d.newError(tok.Pos(), "message %v cannot be extended by %v", messageDesc.FullName(), fd.FullName()) |
|
184 } |
|
185 } else if xtErr != nil && xtErr != protoregistry.NotFound { |
|
186 return d.newError(tok.Pos(), "unable to resolve [%s]: %v", tok.RawString(), xtErr) |
|
187 } |
|
188 if flags.ProtoLegacy { |
|
189 if fd != nil && fd.IsWeak() && fd.Message().IsPlaceholder() { |
|
190 fd = nil // reset since the weak reference is not linked in |
|
191 } |
|
192 } |
|
193 |
|
194 // Handle unknown fields. |
|
195 if fd == nil { |
|
196 if d.opts.DiscardUnknown || messageDesc.ReservedNames().Has(name) { |
|
197 d.skipValue() |
|
198 continue |
|
199 } |
|
200 return d.newError(tok.Pos(), "unknown field: %v", tok.RawString()) |
|
201 } |
|
202 |
|
203 // Handle fields identified by field number. |
|
204 if isFieldNumberName { |
|
205 // TODO: Add an option to permit parsing field numbers. |
|
206 // |
|
207 // This requires careful thought as the MarshalOptions.EmitUnknown |
|
208 // option allows formatting unknown fields as the field number and the |
|
209 // best-effort textual representation of the field value. In that case, |
|
210 // it may not be possible to unmarshal the value from a parser that does |
|
211 // have information about the unknown field. |
|
212 return d.newError(tok.Pos(), "cannot specify field by number: %v", tok.RawString()) |
|
213 } |
|
214 |
|
215 switch { |
|
216 case fd.IsList(): |
|
217 kind := fd.Kind() |
|
218 if kind != pref.MessageKind && kind != pref.GroupKind && !tok.HasSeparator() { |
|
219 return d.syntaxError(tok.Pos(), "missing field separator :") |
|
220 } |
|
221 |
|
222 list := m.Mutable(fd).List() |
|
223 if err := d.unmarshalList(fd, list); err != nil { |
|
224 return err |
|
225 } |
|
226 |
|
227 case fd.IsMap(): |
|
228 mmap := m.Mutable(fd).Map() |
|
229 if err := d.unmarshalMap(fd, mmap); err != nil { |
|
230 return err |
|
231 } |
|
232 |
|
233 default: |
|
234 kind := fd.Kind() |
|
235 if kind != pref.MessageKind && kind != pref.GroupKind && !tok.HasSeparator() { |
|
236 return d.syntaxError(tok.Pos(), "missing field separator :") |
|
237 } |
|
238 |
|
239 // If field is a oneof, check if it has already been set. |
|
240 if od := fd.ContainingOneof(); od != nil { |
|
241 idx := uint64(od.Index()) |
|
242 if seenOneofs.Has(idx) { |
|
243 return d.newError(tok.Pos(), "error parsing %q, oneof %v is already set", tok.RawString(), od.FullName()) |
|
244 } |
|
245 seenOneofs.Set(idx) |
|
246 } |
|
247 |
|
248 num := uint64(fd.Number()) |
|
249 if seenNums.Has(num) { |
|
250 return d.newError(tok.Pos(), "non-repeated field %q is repeated", tok.RawString()) |
|
251 } |
|
252 |
|
253 if err := d.unmarshalSingular(fd, m); err != nil { |
|
254 return err |
|
255 } |
|
256 seenNums.Set(num) |
|
257 } |
|
258 } |
|
259 |
|
260 return nil |
|
261 } |
|
262 |
|
263 // unmarshalSingular unmarshals a non-repeated field value specified by the |
|
264 // given FieldDescriptor. |
|
265 func (d decoder) unmarshalSingular(fd pref.FieldDescriptor, m pref.Message) error { |
|
266 var val pref.Value |
|
267 var err error |
|
268 switch fd.Kind() { |
|
269 case pref.MessageKind, pref.GroupKind: |
|
270 val = m.NewField(fd) |
|
271 err = d.unmarshalMessage(val.Message(), true) |
|
272 default: |
|
273 val, err = d.unmarshalScalar(fd) |
|
274 } |
|
275 if err == nil { |
|
276 m.Set(fd, val) |
|
277 } |
|
278 return err |
|
279 } |
|
280 |
|
281 // unmarshalScalar unmarshals a scalar/enum protoreflect.Value specified by the |
|
282 // given FieldDescriptor. |
|
283 func (d decoder) unmarshalScalar(fd pref.FieldDescriptor) (pref.Value, error) { |
|
284 tok, err := d.Read() |
|
285 if err != nil { |
|
286 return pref.Value{}, err |
|
287 } |
|
288 |
|
289 if tok.Kind() != text.Scalar { |
|
290 return pref.Value{}, d.unexpectedTokenError(tok) |
|
291 } |
|
292 |
|
293 kind := fd.Kind() |
|
294 switch kind { |
|
295 case pref.BoolKind: |
|
296 if b, ok := tok.Bool(); ok { |
|
297 return pref.ValueOfBool(b), nil |
|
298 } |
|
299 |
|
300 case pref.Int32Kind, pref.Sint32Kind, pref.Sfixed32Kind: |
|
301 if n, ok := tok.Int32(); ok { |
|
302 return pref.ValueOfInt32(n), nil |
|
303 } |
|
304 |
|
305 case pref.Int64Kind, pref.Sint64Kind, pref.Sfixed64Kind: |
|
306 if n, ok := tok.Int64(); ok { |
|
307 return pref.ValueOfInt64(n), nil |
|
308 } |
|
309 |
|
310 case pref.Uint32Kind, pref.Fixed32Kind: |
|
311 if n, ok := tok.Uint32(); ok { |
|
312 return pref.ValueOfUint32(n), nil |
|
313 } |
|
314 |
|
315 case pref.Uint64Kind, pref.Fixed64Kind: |
|
316 if n, ok := tok.Uint64(); ok { |
|
317 return pref.ValueOfUint64(n), nil |
|
318 } |
|
319 |
|
320 case pref.FloatKind: |
|
321 if n, ok := tok.Float32(); ok { |
|
322 return pref.ValueOfFloat32(n), nil |
|
323 } |
|
324 |
|
325 case pref.DoubleKind: |
|
326 if n, ok := tok.Float64(); ok { |
|
327 return pref.ValueOfFloat64(n), nil |
|
328 } |
|
329 |
|
330 case pref.StringKind: |
|
331 if s, ok := tok.String(); ok { |
|
332 if strs.EnforceUTF8(fd) && !utf8.ValidString(s) { |
|
333 return pref.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8") |
|
334 } |
|
335 return pref.ValueOfString(s), nil |
|
336 } |
|
337 |
|
338 case pref.BytesKind: |
|
339 if b, ok := tok.String(); ok { |
|
340 return pref.ValueOfBytes([]byte(b)), nil |
|
341 } |
|
342 |
|
343 case pref.EnumKind: |
|
344 if lit, ok := tok.Enum(); ok { |
|
345 // Lookup EnumNumber based on name. |
|
346 if enumVal := fd.Enum().Values().ByName(pref.Name(lit)); enumVal != nil { |
|
347 return pref.ValueOfEnum(enumVal.Number()), nil |
|
348 } |
|
349 } |
|
350 if num, ok := tok.Int32(); ok { |
|
351 return pref.ValueOfEnum(pref.EnumNumber(num)), nil |
|
352 } |
|
353 |
|
354 default: |
|
355 panic(fmt.Sprintf("invalid scalar kind %v", kind)) |
|
356 } |
|
357 |
|
358 return pref.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString()) |
|
359 } |
|
360 |
|
361 // unmarshalList unmarshals into given protoreflect.List. A list value can |
|
362 // either be in [] syntax or simply just a single scalar/message value. |
|
363 func (d decoder) unmarshalList(fd pref.FieldDescriptor, list pref.List) error { |
|
364 tok, err := d.Peek() |
|
365 if err != nil { |
|
366 return err |
|
367 } |
|
368 |
|
369 switch fd.Kind() { |
|
370 case pref.MessageKind, pref.GroupKind: |
|
371 switch tok.Kind() { |
|
372 case text.ListOpen: |
|
373 d.Read() |
|
374 for { |
|
375 tok, err := d.Peek() |
|
376 if err != nil { |
|
377 return err |
|
378 } |
|
379 |
|
380 switch tok.Kind() { |
|
381 case text.ListClose: |
|
382 d.Read() |
|
383 return nil |
|
384 case text.MessageOpen: |
|
385 pval := list.NewElement() |
|
386 if err := d.unmarshalMessage(pval.Message(), true); err != nil { |
|
387 return err |
|
388 } |
|
389 list.Append(pval) |
|
390 default: |
|
391 return d.unexpectedTokenError(tok) |
|
392 } |
|
393 } |
|
394 |
|
395 case text.MessageOpen: |
|
396 pval := list.NewElement() |
|
397 if err := d.unmarshalMessage(pval.Message(), true); err != nil { |
|
398 return err |
|
399 } |
|
400 list.Append(pval) |
|
401 return nil |
|
402 } |
|
403 |
|
404 default: |
|
405 switch tok.Kind() { |
|
406 case text.ListOpen: |
|
407 d.Read() |
|
408 for { |
|
409 tok, err := d.Peek() |
|
410 if err != nil { |
|
411 return err |
|
412 } |
|
413 |
|
414 switch tok.Kind() { |
|
415 case text.ListClose: |
|
416 d.Read() |
|
417 return nil |
|
418 case text.Scalar: |
|
419 pval, err := d.unmarshalScalar(fd) |
|
420 if err != nil { |
|
421 return err |
|
422 } |
|
423 list.Append(pval) |
|
424 default: |
|
425 return d.unexpectedTokenError(tok) |
|
426 } |
|
427 } |
|
428 |
|
429 case text.Scalar: |
|
430 pval, err := d.unmarshalScalar(fd) |
|
431 if err != nil { |
|
432 return err |
|
433 } |
|
434 list.Append(pval) |
|
435 return nil |
|
436 } |
|
437 } |
|
438 |
|
439 return d.unexpectedTokenError(tok) |
|
440 } |
|
441 |
|
442 // unmarshalMap unmarshals into given protoreflect.Map. A map value is a |
|
443 // textproto message containing {key: <kvalue>, value: <mvalue>}. |
|
444 func (d decoder) unmarshalMap(fd pref.FieldDescriptor, mmap pref.Map) error { |
|
445 // Determine ahead whether map entry is a scalar type or a message type in |
|
446 // order to call the appropriate unmarshalMapValue func inside |
|
447 // unmarshalMapEntry. |
|
448 var unmarshalMapValue func() (pref.Value, error) |
|
449 switch fd.MapValue().Kind() { |
|
450 case pref.MessageKind, pref.GroupKind: |
|
451 unmarshalMapValue = func() (pref.Value, error) { |
|
452 pval := mmap.NewValue() |
|
453 if err := d.unmarshalMessage(pval.Message(), true); err != nil { |
|
454 return pref.Value{}, err |
|
455 } |
|
456 return pval, nil |
|
457 } |
|
458 default: |
|
459 unmarshalMapValue = func() (pref.Value, error) { |
|
460 return d.unmarshalScalar(fd.MapValue()) |
|
461 } |
|
462 } |
|
463 |
|
464 tok, err := d.Read() |
|
465 if err != nil { |
|
466 return err |
|
467 } |
|
468 switch tok.Kind() { |
|
469 case text.MessageOpen: |
|
470 return d.unmarshalMapEntry(fd, mmap, unmarshalMapValue) |
|
471 |
|
472 case text.ListOpen: |
|
473 for { |
|
474 tok, err := d.Read() |
|
475 if err != nil { |
|
476 return err |
|
477 } |
|
478 switch tok.Kind() { |
|
479 case text.ListClose: |
|
480 return nil |
|
481 case text.MessageOpen: |
|
482 if err := d.unmarshalMapEntry(fd, mmap, unmarshalMapValue); err != nil { |
|
483 return err |
|
484 } |
|
485 default: |
|
486 return d.unexpectedTokenError(tok) |
|
487 } |
|
488 } |
|
489 |
|
490 default: |
|
491 return d.unexpectedTokenError(tok) |
|
492 } |
|
493 } |
|
494 |
|
495 // unmarshalMap unmarshals into given protoreflect.Map. A map value is a |
|
496 // textproto message containing {key: <kvalue>, value: <mvalue>}. |
|
497 func (d decoder) unmarshalMapEntry(fd pref.FieldDescriptor, mmap pref.Map, unmarshalMapValue func() (pref.Value, error)) error { |
|
498 var key pref.MapKey |
|
499 var pval pref.Value |
|
500 Loop: |
|
501 for { |
|
502 // Read field name. |
|
503 tok, err := d.Read() |
|
504 if err != nil { |
|
505 return err |
|
506 } |
|
507 switch tok.Kind() { |
|
508 case text.Name: |
|
509 if tok.NameKind() != text.IdentName { |
|
510 if !d.opts.DiscardUnknown { |
|
511 return d.newError(tok.Pos(), "unknown map entry field %q", tok.RawString()) |
|
512 } |
|
513 d.skipValue() |
|
514 continue Loop |
|
515 } |
|
516 // Continue below. |
|
517 case text.MessageClose: |
|
518 break Loop |
|
519 default: |
|
520 return d.unexpectedTokenError(tok) |
|
521 } |
|
522 |
|
523 switch name := pref.Name(tok.IdentName()); name { |
|
524 case genid.MapEntry_Key_field_name: |
|
525 if !tok.HasSeparator() { |
|
526 return d.syntaxError(tok.Pos(), "missing field separator :") |
|
527 } |
|
528 if key.IsValid() { |
|
529 return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) |
|
530 } |
|
531 val, err := d.unmarshalScalar(fd.MapKey()) |
|
532 if err != nil { |
|
533 return err |
|
534 } |
|
535 key = val.MapKey() |
|
536 |
|
537 case genid.MapEntry_Value_field_name: |
|
538 if kind := fd.MapValue().Kind(); (kind != pref.MessageKind) && (kind != pref.GroupKind) { |
|
539 if !tok.HasSeparator() { |
|
540 return d.syntaxError(tok.Pos(), "missing field separator :") |
|
541 } |
|
542 } |
|
543 if pval.IsValid() { |
|
544 return d.newError(tok.Pos(), "map entry %q cannot be repeated", name) |
|
545 } |
|
546 pval, err = unmarshalMapValue() |
|
547 if err != nil { |
|
548 return err |
|
549 } |
|
550 |
|
551 default: |
|
552 if !d.opts.DiscardUnknown { |
|
553 return d.newError(tok.Pos(), "unknown map entry field %q", name) |
|
554 } |
|
555 d.skipValue() |
|
556 } |
|
557 } |
|
558 |
|
559 if !key.IsValid() { |
|
560 key = fd.MapKey().Default().MapKey() |
|
561 } |
|
562 if !pval.IsValid() { |
|
563 switch fd.MapValue().Kind() { |
|
564 case pref.MessageKind, pref.GroupKind: |
|
565 // If value field is not set for message/group types, construct an |
|
566 // empty one as default. |
|
567 pval = mmap.NewValue() |
|
568 default: |
|
569 pval = fd.MapValue().Default() |
|
570 } |
|
571 } |
|
572 mmap.Set(key, pval) |
|
573 return nil |
|
574 } |
|
575 |
|
576 // unmarshalAny unmarshals an Any textproto. It can either be in expanded form |
|
577 // or non-expanded form. |
|
578 func (d decoder) unmarshalAny(m pref.Message, checkDelims bool) error { |
|
579 var typeURL string |
|
580 var bValue []byte |
|
581 var seenTypeUrl bool |
|
582 var seenValue bool |
|
583 var isExpanded bool |
|
584 |
|
585 if checkDelims { |
|
586 tok, err := d.Read() |
|
587 if err != nil { |
|
588 return err |
|
589 } |
|
590 |
|
591 if tok.Kind() != text.MessageOpen { |
|
592 return d.unexpectedTokenError(tok) |
|
593 } |
|
594 } |
|
595 |
|
596 Loop: |
|
597 for { |
|
598 // Read field name. Can only have 3 possible field names, i.e. type_url, |
|
599 // value and type URL name inside []. |
|
600 tok, err := d.Read() |
|
601 if err != nil { |
|
602 return err |
|
603 } |
|
604 if typ := tok.Kind(); typ != text.Name { |
|
605 if checkDelims { |
|
606 if typ == text.MessageClose { |
|
607 break Loop |
|
608 } |
|
609 } else if typ == text.EOF { |
|
610 break Loop |
|
611 } |
|
612 return d.unexpectedTokenError(tok) |
|
613 } |
|
614 |
|
615 switch tok.NameKind() { |
|
616 case text.IdentName: |
|
617 // Both type_url and value fields require field separator :. |
|
618 if !tok.HasSeparator() { |
|
619 return d.syntaxError(tok.Pos(), "missing field separator :") |
|
620 } |
|
621 |
|
622 switch name := pref.Name(tok.IdentName()); name { |
|
623 case genid.Any_TypeUrl_field_name: |
|
624 if seenTypeUrl { |
|
625 return d.newError(tok.Pos(), "duplicate %v field", genid.Any_TypeUrl_field_fullname) |
|
626 } |
|
627 if isExpanded { |
|
628 return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) |
|
629 } |
|
630 tok, err := d.Read() |
|
631 if err != nil { |
|
632 return err |
|
633 } |
|
634 var ok bool |
|
635 typeURL, ok = tok.String() |
|
636 if !ok { |
|
637 return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_TypeUrl_field_fullname, tok.RawString()) |
|
638 } |
|
639 seenTypeUrl = true |
|
640 |
|
641 case genid.Any_Value_field_name: |
|
642 if seenValue { |
|
643 return d.newError(tok.Pos(), "duplicate %v field", genid.Any_Value_field_fullname) |
|
644 } |
|
645 if isExpanded { |
|
646 return d.newError(tok.Pos(), "conflict with [%s] field", typeURL) |
|
647 } |
|
648 tok, err := d.Read() |
|
649 if err != nil { |
|
650 return err |
|
651 } |
|
652 s, ok := tok.String() |
|
653 if !ok { |
|
654 return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_Value_field_fullname, tok.RawString()) |
|
655 } |
|
656 bValue = []byte(s) |
|
657 seenValue = true |
|
658 |
|
659 default: |
|
660 if !d.opts.DiscardUnknown { |
|
661 return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) |
|
662 } |
|
663 } |
|
664 |
|
665 case text.TypeName: |
|
666 if isExpanded { |
|
667 return d.newError(tok.Pos(), "cannot have more than one type") |
|
668 } |
|
669 if seenTypeUrl { |
|
670 return d.newError(tok.Pos(), "conflict with type_url field") |
|
671 } |
|
672 typeURL = tok.TypeName() |
|
673 var err error |
|
674 bValue, err = d.unmarshalExpandedAny(typeURL, tok.Pos()) |
|
675 if err != nil { |
|
676 return err |
|
677 } |
|
678 isExpanded = true |
|
679 |
|
680 default: |
|
681 if !d.opts.DiscardUnknown { |
|
682 return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname) |
|
683 } |
|
684 } |
|
685 } |
|
686 |
|
687 fds := m.Descriptor().Fields() |
|
688 if len(typeURL) > 0 { |
|
689 m.Set(fds.ByNumber(genid.Any_TypeUrl_field_number), pref.ValueOfString(typeURL)) |
|
690 } |
|
691 if len(bValue) > 0 { |
|
692 m.Set(fds.ByNumber(genid.Any_Value_field_number), pref.ValueOfBytes(bValue)) |
|
693 } |
|
694 return nil |
|
695 } |
|
696 |
|
697 func (d decoder) unmarshalExpandedAny(typeURL string, pos int) ([]byte, error) { |
|
698 mt, err := d.opts.Resolver.FindMessageByURL(typeURL) |
|
699 if err != nil { |
|
700 return nil, d.newError(pos, "unable to resolve message [%v]: %v", typeURL, err) |
|
701 } |
|
702 // Create new message for the embedded message type and unmarshal the value |
|
703 // field into it. |
|
704 m := mt.New() |
|
705 if err := d.unmarshalMessage(m, true); err != nil { |
|
706 return nil, err |
|
707 } |
|
708 // Serialize the embedded message and return the resulting bytes. |
|
709 b, err := proto.MarshalOptions{ |
|
710 AllowPartial: true, // Never check required fields inside an Any. |
|
711 Deterministic: true, |
|
712 }.Marshal(m.Interface()) |
|
713 if err != nil { |
|
714 return nil, d.newError(pos, "error in marshaling message into Any.value: %v", err) |
|
715 } |
|
716 return b, nil |
|
717 } |
|
718 |
|
719 // skipValue makes the decoder parse a field value in order to advance the read |
|
720 // to the next field. It relies on Read returning an error if the types are not |
|
721 // in valid sequence. |
|
722 func (d decoder) skipValue() error { |
|
723 tok, err := d.Read() |
|
724 if err != nil { |
|
725 return err |
|
726 } |
|
727 // Only need to continue reading for messages and lists. |
|
728 switch tok.Kind() { |
|
729 case text.MessageOpen: |
|
730 return d.skipMessageValue() |
|
731 |
|
732 case text.ListOpen: |
|
733 for { |
|
734 tok, err := d.Read() |
|
735 if err != nil { |
|
736 return err |
|
737 } |
|
738 switch tok.Kind() { |
|
739 case text.ListClose: |
|
740 return nil |
|
741 case text.MessageOpen: |
|
742 return d.skipMessageValue() |
|
743 default: |
|
744 // Skip items. This will not validate whether skipped values are |
|
745 // of the same type or not, same behavior as C++ |
|
746 // TextFormat::Parser::AllowUnknownField(true) version 3.8.0. |
|
747 } |
|
748 } |
|
749 } |
|
750 return nil |
|
751 } |
|
752 |
|
753 // skipMessageValue makes the decoder parse and skip over all fields in a |
|
754 // message. It assumes that the previous read type is MessageOpen. |
|
755 func (d decoder) skipMessageValue() error { |
|
756 for { |
|
757 tok, err := d.Read() |
|
758 if err != nil { |
|
759 return err |
|
760 } |
|
761 switch tok.Kind() { |
|
762 case text.MessageClose: |
|
763 return nil |
|
764 case text.Name: |
|
765 if err := d.skipValue(); err != nil { |
|
766 return err |
|
767 } |
|
768 } |
|
769 } |
|
770 } |