Test Failed
Push — main ( 973aa1...436074 )
by Christian
02:37
created

prototext.decoder.unmarshalAny   F

Complexity

Conditions 32

Size

Total Lines 117
Code Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 32
eloc 78
nop 2
dl 0
loc 117
rs 0
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Complexity

Complex classes like prototext.decoder.unmarshalAny often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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
}
771