decode.go (21218B)
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 "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 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. 265 func (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. 283 func (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. 363 func (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>}. 444 func (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>}. 497 func (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 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 := 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. 578 func (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 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 := 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 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 }