xref: /aosp_15_r20/external/golang-protobuf/encoding/prototext/decode.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
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
5package prototext
6
7import (
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	"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).
26func Unmarshal(b []byte, m proto.Message) error {
27	return UnmarshalOptions{}.Unmarshal(b, m)
28}
29
30// UnmarshalOptions is a configurable textproto format unmarshaler.
31type 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).
57func (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.
64func (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
81type decoder struct {
82	*text.Decoder
83	opts UnmarshalOptions
84}
85
86// newError returns an error object with position info.
87func (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.
94func (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.
99func (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.
106func (d decoder) unmarshalMessage(m protoreflect.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 protoreflect.Name
154		var fd protoreflect.FieldDescriptor
155		var xt protoreflect.ExtensionType
156		var xtErr error
157		var isFieldNumberName bool
158
159		switch tok.NameKind() {
160		case text.IdentName:
161			name = protoreflect.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(protoreflect.FullName(tok.TypeName()))
167
168		case text.FieldNumber:
169			isFieldNumberName = true
170			num := protoreflect.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 != protoreflect.MessageKind && kind != protoreflect.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 != protoreflect.MessageKind && kind != protoreflect.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.
265func (d decoder) unmarshalSingular(fd protoreflect.FieldDescriptor, m protoreflect.Message) error {
266	var val protoreflect.Value
267	var err error
268	switch fd.Kind() {
269	case protoreflect.MessageKind, protoreflect.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.
283func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
284	tok, err := d.Read()
285	if err != nil {
286		return protoreflect.Value{}, err
287	}
288
289	if tok.Kind() != text.Scalar {
290		return protoreflect.Value{}, d.unexpectedTokenError(tok)
291	}
292
293	kind := fd.Kind()
294	switch kind {
295	case protoreflect.BoolKind:
296		if b, ok := tok.Bool(); ok {
297			return protoreflect.ValueOfBool(b), nil
298		}
299
300	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
301		if n, ok := tok.Int32(); ok {
302			return protoreflect.ValueOfInt32(n), nil
303		}
304
305	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
306		if n, ok := tok.Int64(); ok {
307			return protoreflect.ValueOfInt64(n), nil
308		}
309
310	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
311		if n, ok := tok.Uint32(); ok {
312			return protoreflect.ValueOfUint32(n), nil
313		}
314
315	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
316		if n, ok := tok.Uint64(); ok {
317			return protoreflect.ValueOfUint64(n), nil
318		}
319
320	case protoreflect.FloatKind:
321		if n, ok := tok.Float32(); ok {
322			return protoreflect.ValueOfFloat32(n), nil
323		}
324
325	case protoreflect.DoubleKind:
326		if n, ok := tok.Float64(); ok {
327			return protoreflect.ValueOfFloat64(n), nil
328		}
329
330	case protoreflect.StringKind:
331		if s, ok := tok.String(); ok {
332			if strs.EnforceUTF8(fd) && !utf8.ValidString(s) {
333				return protoreflect.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8")
334			}
335			return protoreflect.ValueOfString(s), nil
336		}
337
338	case protoreflect.BytesKind:
339		if b, ok := tok.String(); ok {
340			return protoreflect.ValueOfBytes([]byte(b)), nil
341		}
342
343	case protoreflect.EnumKind:
344		if lit, ok := tok.Enum(); ok {
345			// Lookup EnumNumber based on name.
346			if enumVal := fd.Enum().Values().ByName(protoreflect.Name(lit)); enumVal != nil {
347				return protoreflect.ValueOfEnum(enumVal.Number()), nil
348			}
349		}
350		if num, ok := tok.Int32(); ok {
351			return protoreflect.ValueOfEnum(protoreflect.EnumNumber(num)), nil
352		}
353
354	default:
355		panic(fmt.Sprintf("invalid scalar kind %v", kind))
356	}
357
358	return protoreflect.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.
363func (d decoder) unmarshalList(fd protoreflect.FieldDescriptor, list protoreflect.List) error {
364	tok, err := d.Peek()
365	if err != nil {
366		return err
367	}
368
369	switch fd.Kind() {
370	case protoreflect.MessageKind, protoreflect.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>}.
444func (d decoder) unmarshalMap(fd protoreflect.FieldDescriptor, mmap protoreflect.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() (protoreflect.Value, error)
449	switch fd.MapValue().Kind() {
450	case protoreflect.MessageKind, protoreflect.GroupKind:
451		unmarshalMapValue = func() (protoreflect.Value, error) {
452			pval := mmap.NewValue()
453			if err := d.unmarshalMessage(pval.Message(), true); err != nil {
454				return protoreflect.Value{}, err
455			}
456			return pval, nil
457		}
458	default:
459		unmarshalMapValue = func() (protoreflect.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>}.
497func (d decoder) unmarshalMapEntry(fd protoreflect.FieldDescriptor, mmap protoreflect.Map, unmarshalMapValue func() (protoreflect.Value, error)) error {
498	var key protoreflect.MapKey
499	var pval protoreflect.Value
500Loop:
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 := protoreflect.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 != protoreflect.MessageKind) && (kind != protoreflect.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 protoreflect.MessageKind, protoreflect.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.
578func (d decoder) unmarshalAny(m protoreflect.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
596Loop:
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 := protoreflect.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), protoreflect.ValueOfString(typeURL))
690	}
691	if len(bValue) > 0 {
692		m.Set(fds.ByNumber(genid.Any_Value_field_number), protoreflect.ValueOfBytes(bValue))
693	}
694	return nil
695}
696
697func (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.
722func (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.
755func (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