decode.go

  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 ...any) 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 ...any) 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
189		// Handle unknown fields.
190		if fd == nil {
191			if d.opts.DiscardUnknown || messageDesc.ReservedNames().Has(name) {
192				d.skipValue()
193				continue
194			}
195			return d.newError(tok.Pos(), "unknown field: %v", tok.RawString())
196		}
197
198		// Handle fields identified by field number.
199		if isFieldNumberName {
200			// TODO: Add an option to permit parsing field numbers.
201			//
202			// This requires careful thought as the MarshalOptions.EmitUnknown
203			// option allows formatting unknown fields as the field number and the
204			// best-effort textual representation of the field value.  In that case,
205			// it may not be possible to unmarshal the value from a parser that does
206			// have information about the unknown field.
207			return d.newError(tok.Pos(), "cannot specify field by number: %v", tok.RawString())
208		}
209
210		switch {
211		case fd.IsList():
212			kind := fd.Kind()
213			if kind != protoreflect.MessageKind && kind != protoreflect.GroupKind && !tok.HasSeparator() {
214				return d.syntaxError(tok.Pos(), "missing field separator :")
215			}
216
217			list := m.Mutable(fd).List()
218			if err := d.unmarshalList(fd, list); err != nil {
219				return err
220			}
221
222		case fd.IsMap():
223			mmap := m.Mutable(fd).Map()
224			if err := d.unmarshalMap(fd, mmap); err != nil {
225				return err
226			}
227
228		default:
229			kind := fd.Kind()
230			if kind != protoreflect.MessageKind && kind != protoreflect.GroupKind && !tok.HasSeparator() {
231				return d.syntaxError(tok.Pos(), "missing field separator :")
232			}
233
234			// If field is a oneof, check if it has already been set.
235			if od := fd.ContainingOneof(); od != nil {
236				idx := uint64(od.Index())
237				if seenOneofs.Has(idx) {
238					return d.newError(tok.Pos(), "error parsing %q, oneof %v is already set", tok.RawString(), od.FullName())
239				}
240				seenOneofs.Set(idx)
241			}
242
243			num := uint64(fd.Number())
244			if seenNums.Has(num) {
245				return d.newError(tok.Pos(), "non-repeated field %q is repeated", tok.RawString())
246			}
247
248			if err := d.unmarshalSingular(fd, m); err != nil {
249				return err
250			}
251			seenNums.Set(num)
252		}
253	}
254
255	return nil
256}
257
258// unmarshalSingular unmarshals a non-repeated field value specified by the
259// given FieldDescriptor.
260func (d decoder) unmarshalSingular(fd protoreflect.FieldDescriptor, m protoreflect.Message) error {
261	var val protoreflect.Value
262	var err error
263	switch fd.Kind() {
264	case protoreflect.MessageKind, protoreflect.GroupKind:
265		val = m.NewField(fd)
266		err = d.unmarshalMessage(val.Message(), true)
267	default:
268		val, err = d.unmarshalScalar(fd)
269	}
270	if err == nil {
271		m.Set(fd, val)
272	}
273	return err
274}
275
276// unmarshalScalar unmarshals a scalar/enum protoreflect.Value specified by the
277// given FieldDescriptor.
278func (d decoder) unmarshalScalar(fd protoreflect.FieldDescriptor) (protoreflect.Value, error) {
279	tok, err := d.Read()
280	if err != nil {
281		return protoreflect.Value{}, err
282	}
283
284	if tok.Kind() != text.Scalar {
285		return protoreflect.Value{}, d.unexpectedTokenError(tok)
286	}
287
288	kind := fd.Kind()
289	switch kind {
290	case protoreflect.BoolKind:
291		if b, ok := tok.Bool(); ok {
292			return protoreflect.ValueOfBool(b), nil
293		}
294
295	case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
296		if n, ok := tok.Int32(); ok {
297			return protoreflect.ValueOfInt32(n), nil
298		}
299
300	case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
301		if n, ok := tok.Int64(); ok {
302			return protoreflect.ValueOfInt64(n), nil
303		}
304
305	case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
306		if n, ok := tok.Uint32(); ok {
307			return protoreflect.ValueOfUint32(n), nil
308		}
309
310	case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
311		if n, ok := tok.Uint64(); ok {
312			return protoreflect.ValueOfUint64(n), nil
313		}
314
315	case protoreflect.FloatKind:
316		if n, ok := tok.Float32(); ok {
317			return protoreflect.ValueOfFloat32(n), nil
318		}
319
320	case protoreflect.DoubleKind:
321		if n, ok := tok.Float64(); ok {
322			return protoreflect.ValueOfFloat64(n), nil
323		}
324
325	case protoreflect.StringKind:
326		if s, ok := tok.String(); ok {
327			if strs.EnforceUTF8(fd) && !utf8.ValidString(s) {
328				return protoreflect.Value{}, d.newError(tok.Pos(), "contains invalid UTF-8")
329			}
330			return protoreflect.ValueOfString(s), nil
331		}
332
333	case protoreflect.BytesKind:
334		if b, ok := tok.String(); ok {
335			return protoreflect.ValueOfBytes([]byte(b)), nil
336		}
337
338	case protoreflect.EnumKind:
339		if lit, ok := tok.Enum(); ok {
340			// Lookup EnumNumber based on name.
341			if enumVal := fd.Enum().Values().ByName(protoreflect.Name(lit)); enumVal != nil {
342				return protoreflect.ValueOfEnum(enumVal.Number()), nil
343			}
344		}
345		if num, ok := tok.Int32(); ok {
346			return protoreflect.ValueOfEnum(protoreflect.EnumNumber(num)), nil
347		}
348
349	default:
350		panic(fmt.Sprintf("invalid scalar kind %v", kind))
351	}
352
353	return protoreflect.Value{}, d.newError(tok.Pos(), "invalid value for %v type: %v", kind, tok.RawString())
354}
355
356// unmarshalList unmarshals into given protoreflect.List. A list value can
357// either be in [] syntax or simply just a single scalar/message value.
358func (d decoder) unmarshalList(fd protoreflect.FieldDescriptor, list protoreflect.List) error {
359	tok, err := d.Peek()
360	if err != nil {
361		return err
362	}
363
364	switch fd.Kind() {
365	case protoreflect.MessageKind, protoreflect.GroupKind:
366		switch tok.Kind() {
367		case text.ListOpen:
368			d.Read()
369			for {
370				tok, err := d.Peek()
371				if err != nil {
372					return err
373				}
374
375				switch tok.Kind() {
376				case text.ListClose:
377					d.Read()
378					return nil
379				case text.MessageOpen:
380					pval := list.NewElement()
381					if err := d.unmarshalMessage(pval.Message(), true); err != nil {
382						return err
383					}
384					list.Append(pval)
385				default:
386					return d.unexpectedTokenError(tok)
387				}
388			}
389
390		case text.MessageOpen:
391			pval := list.NewElement()
392			if err := d.unmarshalMessage(pval.Message(), true); err != nil {
393				return err
394			}
395			list.Append(pval)
396			return nil
397		}
398
399	default:
400		switch tok.Kind() {
401		case text.ListOpen:
402			d.Read()
403			for {
404				tok, err := d.Peek()
405				if err != nil {
406					return err
407				}
408
409				switch tok.Kind() {
410				case text.ListClose:
411					d.Read()
412					return nil
413				case text.Scalar:
414					pval, err := d.unmarshalScalar(fd)
415					if err != nil {
416						return err
417					}
418					list.Append(pval)
419				default:
420					return d.unexpectedTokenError(tok)
421				}
422			}
423
424		case text.Scalar:
425			pval, err := d.unmarshalScalar(fd)
426			if err != nil {
427				return err
428			}
429			list.Append(pval)
430			return nil
431		}
432	}
433
434	return d.unexpectedTokenError(tok)
435}
436
437// unmarshalMap unmarshals into given protoreflect.Map. A map value is a
438// textproto message containing {key: <kvalue>, value: <mvalue>}.
439func (d decoder) unmarshalMap(fd protoreflect.FieldDescriptor, mmap protoreflect.Map) error {
440	// Determine ahead whether map entry is a scalar type or a message type in
441	// order to call the appropriate unmarshalMapValue func inside
442	// unmarshalMapEntry.
443	var unmarshalMapValue func() (protoreflect.Value, error)
444	switch fd.MapValue().Kind() {
445	case protoreflect.MessageKind, protoreflect.GroupKind:
446		unmarshalMapValue = func() (protoreflect.Value, error) {
447			pval := mmap.NewValue()
448			if err := d.unmarshalMessage(pval.Message(), true); err != nil {
449				return protoreflect.Value{}, err
450			}
451			return pval, nil
452		}
453	default:
454		unmarshalMapValue = func() (protoreflect.Value, error) {
455			return d.unmarshalScalar(fd.MapValue())
456		}
457	}
458
459	tok, err := d.Read()
460	if err != nil {
461		return err
462	}
463	switch tok.Kind() {
464	case text.MessageOpen:
465		return d.unmarshalMapEntry(fd, mmap, unmarshalMapValue)
466
467	case text.ListOpen:
468		for {
469			tok, err := d.Read()
470			if err != nil {
471				return err
472			}
473			switch tok.Kind() {
474			case text.ListClose:
475				return nil
476			case text.MessageOpen:
477				if err := d.unmarshalMapEntry(fd, mmap, unmarshalMapValue); err != nil {
478					return err
479				}
480			default:
481				return d.unexpectedTokenError(tok)
482			}
483		}
484
485	default:
486		return d.unexpectedTokenError(tok)
487	}
488}
489
490// unmarshalMap unmarshals into given protoreflect.Map. A map value is a
491// textproto message containing {key: <kvalue>, value: <mvalue>}.
492func (d decoder) unmarshalMapEntry(fd protoreflect.FieldDescriptor, mmap protoreflect.Map, unmarshalMapValue func() (protoreflect.Value, error)) error {
493	var key protoreflect.MapKey
494	var pval protoreflect.Value
495Loop:
496	for {
497		// Read field name.
498		tok, err := d.Read()
499		if err != nil {
500			return err
501		}
502		switch tok.Kind() {
503		case text.Name:
504			if tok.NameKind() != text.IdentName {
505				if !d.opts.DiscardUnknown {
506					return d.newError(tok.Pos(), "unknown map entry field %q", tok.RawString())
507				}
508				d.skipValue()
509				continue Loop
510			}
511			// Continue below.
512		case text.MessageClose:
513			break Loop
514		default:
515			return d.unexpectedTokenError(tok)
516		}
517
518		switch name := protoreflect.Name(tok.IdentName()); name {
519		case genid.MapEntry_Key_field_name:
520			if !tok.HasSeparator() {
521				return d.syntaxError(tok.Pos(), "missing field separator :")
522			}
523			if key.IsValid() {
524				return d.newError(tok.Pos(), "map entry %q cannot be repeated", name)
525			}
526			val, err := d.unmarshalScalar(fd.MapKey())
527			if err != nil {
528				return err
529			}
530			key = val.MapKey()
531
532		case genid.MapEntry_Value_field_name:
533			if kind := fd.MapValue().Kind(); (kind != protoreflect.MessageKind) && (kind != protoreflect.GroupKind) {
534				if !tok.HasSeparator() {
535					return d.syntaxError(tok.Pos(), "missing field separator :")
536				}
537			}
538			if pval.IsValid() {
539				return d.newError(tok.Pos(), "map entry %q cannot be repeated", name)
540			}
541			pval, err = unmarshalMapValue()
542			if err != nil {
543				return err
544			}
545
546		default:
547			if !d.opts.DiscardUnknown {
548				return d.newError(tok.Pos(), "unknown map entry field %q", name)
549			}
550			d.skipValue()
551		}
552	}
553
554	if !key.IsValid() {
555		key = fd.MapKey().Default().MapKey()
556	}
557	if !pval.IsValid() {
558		switch fd.MapValue().Kind() {
559		case protoreflect.MessageKind, protoreflect.GroupKind:
560			// If value field is not set for message/group types, construct an
561			// empty one as default.
562			pval = mmap.NewValue()
563		default:
564			pval = fd.MapValue().Default()
565		}
566	}
567	mmap.Set(key, pval)
568	return nil
569}
570
571// unmarshalAny unmarshals an Any textproto. It can either be in expanded form
572// or non-expanded form.
573func (d decoder) unmarshalAny(m protoreflect.Message, checkDelims bool) error {
574	var typeURL string
575	var bValue []byte
576	var seenTypeUrl bool
577	var seenValue bool
578	var isExpanded bool
579
580	if checkDelims {
581		tok, err := d.Read()
582		if err != nil {
583			return err
584		}
585
586		if tok.Kind() != text.MessageOpen {
587			return d.unexpectedTokenError(tok)
588		}
589	}
590
591Loop:
592	for {
593		// Read field name. Can only have 3 possible field names, i.e. type_url,
594		// value and type URL name inside [].
595		tok, err := d.Read()
596		if err != nil {
597			return err
598		}
599		if typ := tok.Kind(); typ != text.Name {
600			if checkDelims {
601				if typ == text.MessageClose {
602					break Loop
603				}
604			} else if typ == text.EOF {
605				break Loop
606			}
607			return d.unexpectedTokenError(tok)
608		}
609
610		switch tok.NameKind() {
611		case text.IdentName:
612			// Both type_url and value fields require field separator :.
613			if !tok.HasSeparator() {
614				return d.syntaxError(tok.Pos(), "missing field separator :")
615			}
616
617			switch name := protoreflect.Name(tok.IdentName()); name {
618			case genid.Any_TypeUrl_field_name:
619				if seenTypeUrl {
620					return d.newError(tok.Pos(), "duplicate %v field", genid.Any_TypeUrl_field_fullname)
621				}
622				if isExpanded {
623					return d.newError(tok.Pos(), "conflict with [%s] field", typeURL)
624				}
625				tok, err := d.Read()
626				if err != nil {
627					return err
628				}
629				var ok bool
630				typeURL, ok = tok.String()
631				if !ok {
632					return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_TypeUrl_field_fullname, tok.RawString())
633				}
634				seenTypeUrl = true
635
636			case genid.Any_Value_field_name:
637				if seenValue {
638					return d.newError(tok.Pos(), "duplicate %v field", genid.Any_Value_field_fullname)
639				}
640				if isExpanded {
641					return d.newError(tok.Pos(), "conflict with [%s] field", typeURL)
642				}
643				tok, err := d.Read()
644				if err != nil {
645					return err
646				}
647				s, ok := tok.String()
648				if !ok {
649					return d.newError(tok.Pos(), "invalid %v field value: %v", genid.Any_Value_field_fullname, tok.RawString())
650				}
651				bValue = []byte(s)
652				seenValue = true
653
654			default:
655				if !d.opts.DiscardUnknown {
656					return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname)
657				}
658			}
659
660		case text.TypeName:
661			if isExpanded {
662				return d.newError(tok.Pos(), "cannot have more than one type")
663			}
664			if seenTypeUrl {
665				return d.newError(tok.Pos(), "conflict with type_url field")
666			}
667			typeURL = tok.TypeName()
668			var err error
669			bValue, err = d.unmarshalExpandedAny(typeURL, tok.Pos())
670			if err != nil {
671				return err
672			}
673			isExpanded = true
674
675		default:
676			if !d.opts.DiscardUnknown {
677				return d.newError(tok.Pos(), "invalid field name %q in %v message", tok.RawString(), genid.Any_message_fullname)
678			}
679		}
680	}
681
682	fds := m.Descriptor().Fields()
683	if len(typeURL) > 0 {
684		m.Set(fds.ByNumber(genid.Any_TypeUrl_field_number), protoreflect.ValueOfString(typeURL))
685	}
686	if len(bValue) > 0 {
687		m.Set(fds.ByNumber(genid.Any_Value_field_number), protoreflect.ValueOfBytes(bValue))
688	}
689	return nil
690}
691
692func (d decoder) unmarshalExpandedAny(typeURL string, pos int) ([]byte, error) {
693	mt, err := d.opts.Resolver.FindMessageByURL(typeURL)
694	if err != nil {
695		return nil, d.newError(pos, "unable to resolve message [%v]: %v", typeURL, err)
696	}
697	// Create new message for the embedded message type and unmarshal the value
698	// field into it.
699	m := mt.New()
700	if err := d.unmarshalMessage(m, true); err != nil {
701		return nil, err
702	}
703	// Serialize the embedded message and return the resulting bytes.
704	b, err := proto.MarshalOptions{
705		AllowPartial:  true, // Never check required fields inside an Any.
706		Deterministic: true,
707	}.Marshal(m.Interface())
708	if err != nil {
709		return nil, d.newError(pos, "error in marshaling message into Any.value: %v", err)
710	}
711	return b, nil
712}
713
714// skipValue makes the decoder parse a field value in order to advance the read
715// to the next field. It relies on Read returning an error if the types are not
716// in valid sequence.
717func (d decoder) skipValue() error {
718	tok, err := d.Read()
719	if err != nil {
720		return err
721	}
722	// Only need to continue reading for messages and lists.
723	switch tok.Kind() {
724	case text.MessageOpen:
725		return d.skipMessageValue()
726
727	case text.ListOpen:
728		for {
729			tok, err := d.Read()
730			if err != nil {
731				return err
732			}
733			switch tok.Kind() {
734			case text.ListClose:
735				return nil
736			case text.MessageOpen:
737				if err := d.skipMessageValue(); err != nil {
738					return err
739				}
740			default:
741				// Skip items. This will not validate whether skipped values are
742				// of the same type or not, same behavior as C++
743				// TextFormat::Parser::AllowUnknownField(true) version 3.8.0.
744			}
745		}
746	}
747	return nil
748}
749
750// skipMessageValue makes the decoder parse and skip over all fields in a
751// message. It assumes that the previous read type is MessageOpen.
752func (d decoder) skipMessageValue() error {
753	for {
754		tok, err := d.Read()
755		if err != nil {
756			return err
757		}
758		switch tok.Kind() {
759		case text.MessageClose:
760			return nil
761		case text.Name:
762			if err := d.skipValue(); err != nil {
763				return err
764			}
765		}
766	}
767}