1// Go support for Protocol Buffers - Google's data interchange format 2// 3// Copyright 2010 The Go Authors. All rights reserved. 4// https://github.com/golang/protobuf 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are 8// met: 9// 10// * Redistributions of source code must retain the above copyright 11// notice, this list of conditions and the following disclaimer. 12// * Redistributions in binary form must reproduce the above 13// copyright notice, this list of conditions and the following disclaimer 14// in the documentation and/or other materials provided with the 15// distribution. 16// * Neither the name of Google Inc. nor the names of its 17// contributors may be used to endorse or promote products derived from 18// this software without specific prior written permission. 19// 20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 32package proto 33 34// Functions for parsing the Text protocol buffer format. 35// TODO: message sets. 36 37import ( 38 "encoding" 39 "errors" 40 "fmt" 41 "reflect" 42 "strconv" 43 "strings" 44 "unicode/utf8" 45) 46 47// Error string emitted when deserializing Any and fields are already set 48const anyRepeatedlyUnpacked = "Any message unpacked multiple times, or %q already set" 49 50type ParseError struct { 51 Message string 52 Line int // 1-based line number 53 Offset int // 0-based byte offset from start of input 54} 55 56func (p *ParseError) Error() string { 57 if p.Line == 1 { 58 // show offset only for first line 59 return fmt.Sprintf("line 1.%d: %v", p.Offset, p.Message) 60 } 61 return fmt.Sprintf("line %d: %v", p.Line, p.Message) 62} 63 64type token struct { 65 value string 66 err *ParseError 67 line int // line number 68 offset int // byte number from start of input, not start of line 69 unquoted string // the unquoted version of value, if it was a quoted string 70} 71 72func (t *token) String() string { 73 if t.err == nil { 74 return fmt.Sprintf("%q (line=%d, offset=%d)", t.value, t.line, t.offset) 75 } 76 return fmt.Sprintf("parse error: %v", t.err) 77} 78 79type textParser struct { 80 s string // remaining input 81 done bool // whether the parsing is finished (success or error) 82 backed bool // whether back() was called 83 offset, line int 84 cur token 85} 86 87func newTextParser(s string) *textParser { 88 p := new(textParser) 89 p.s = s 90 p.line = 1 91 p.cur.line = 1 92 return p 93} 94 95func (p *textParser) errorf(format string, a ...interface{}) *ParseError { 96 pe := &ParseError{fmt.Sprintf(format, a...), p.cur.line, p.cur.offset} 97 p.cur.err = pe 98 p.done = true 99 return pe 100} 101 102// Numbers and identifiers are matched by [-+._A-Za-z0-9] 103func isIdentOrNumberChar(c byte) bool { 104 switch { 105 case 'A' <= c && c <= 'Z', 'a' <= c && c <= 'z': 106 return true 107 case '0' <= c && c <= '9': 108 return true 109 } 110 switch c { 111 case '-', '+', '.', '_': 112 return true 113 } 114 return false 115} 116 117func isWhitespace(c byte) bool { 118 switch c { 119 case ' ', '\t', '\n', '\r': 120 return true 121 } 122 return false 123} 124 125func isQuote(c byte) bool { 126 switch c { 127 case '"', '\'': 128 return true 129 } 130 return false 131} 132 133func (p *textParser) skipWhitespace() { 134 i := 0 135 for i < len(p.s) && (isWhitespace(p.s[i]) || p.s[i] == '#') { 136 if p.s[i] == '#' { 137 // comment; skip to end of line or input 138 for i < len(p.s) && p.s[i] != '\n' { 139 i++ 140 } 141 if i == len(p.s) { 142 break 143 } 144 } 145 if p.s[i] == '\n' { 146 p.line++ 147 } 148 i++ 149 } 150 p.offset += i 151 p.s = p.s[i:len(p.s)] 152 if len(p.s) == 0 { 153 p.done = true 154 } 155} 156 157func (p *textParser) advance() { 158 // Skip whitespace 159 p.skipWhitespace() 160 if p.done { 161 return 162 } 163 164 // Start of non-whitespace 165 p.cur.err = nil 166 p.cur.offset, p.cur.line = p.offset, p.line 167 p.cur.unquoted = "" 168 switch p.s[0] { 169 case '<', '>', '{', '}', ':', '[', ']', ';', ',', '/': 170 // Single symbol 171 p.cur.value, p.s = p.s[0:1], p.s[1:len(p.s)] 172 case '"', '\'': 173 // Quoted string 174 i := 1 175 for i < len(p.s) && p.s[i] != p.s[0] && p.s[i] != '\n' { 176 if p.s[i] == '\\' && i+1 < len(p.s) { 177 // skip escaped char 178 i++ 179 } 180 i++ 181 } 182 if i >= len(p.s) || p.s[i] != p.s[0] { 183 p.errorf("unmatched quote") 184 return 185 } 186 unq, err := unquoteC(p.s[1:i], rune(p.s[0])) 187 if err != nil { 188 p.errorf("invalid quoted string %s: %v", p.s[0:i+1], err) 189 return 190 } 191 p.cur.value, p.s = p.s[0:i+1], p.s[i+1:len(p.s)] 192 p.cur.unquoted = unq 193 default: 194 i := 0 195 for i < len(p.s) && isIdentOrNumberChar(p.s[i]) { 196 i++ 197 } 198 if i == 0 { 199 p.errorf("unexpected byte %#x", p.s[0]) 200 return 201 } 202 p.cur.value, p.s = p.s[0:i], p.s[i:len(p.s)] 203 } 204 p.offset += len(p.cur.value) 205} 206 207var ( 208 errBadUTF8 = errors.New("proto: bad UTF-8") 209) 210 211func unquoteC(s string, quote rune) (string, error) { 212 // This is based on C++'s tokenizer.cc. 213 // Despite its name, this is *not* parsing C syntax. 214 // For instance, "\0" is an invalid quoted string. 215 216 // Avoid allocation in trivial cases. 217 simple := true 218 for _, r := range s { 219 if r == '\\' || r == quote { 220 simple = false 221 break 222 } 223 } 224 if simple { 225 return s, nil 226 } 227 228 buf := make([]byte, 0, 3*len(s)/2) 229 for len(s) > 0 { 230 r, n := utf8.DecodeRuneInString(s) 231 if r == utf8.RuneError && n == 1 { 232 return "", errBadUTF8 233 } 234 s = s[n:] 235 if r != '\\' { 236 if r < utf8.RuneSelf { 237 buf = append(buf, byte(r)) 238 } else { 239 buf = append(buf, string(r)...) 240 } 241 continue 242 } 243 244 ch, tail, err := unescape(s) 245 if err != nil { 246 return "", err 247 } 248 buf = append(buf, ch...) 249 s = tail 250 } 251 return string(buf), nil 252} 253 254func unescape(s string) (ch string, tail string, err error) { 255 r, n := utf8.DecodeRuneInString(s) 256 if r == utf8.RuneError && n == 1 { 257 return "", "", errBadUTF8 258 } 259 s = s[n:] 260 switch r { 261 case 'a': 262 return "\a", s, nil 263 case 'b': 264 return "\b", s, nil 265 case 'f': 266 return "\f", s, nil 267 case 'n': 268 return "\n", s, nil 269 case 'r': 270 return "\r", s, nil 271 case 't': 272 return "\t", s, nil 273 case 'v': 274 return "\v", s, nil 275 case '?': 276 return "?", s, nil // trigraph workaround 277 case '\'', '"', '\\': 278 return string(r), s, nil 279 case '0', '1', '2', '3', '4', '5', '6', '7': 280 if len(s) < 2 { 281 return "", "", fmt.Errorf(`\%c requires 2 following digits`, r) 282 } 283 ss := string(r) + s[:2] 284 s = s[2:] 285 i, err := strconv.ParseUint(ss, 8, 8) 286 if err != nil { 287 return "", "", fmt.Errorf(`\%s contains non-octal digits`, ss) 288 } 289 return string([]byte{byte(i)}), s, nil 290 case 'x', 'X', 'u', 'U': 291 var n int 292 switch r { 293 case 'x', 'X': 294 n = 2 295 case 'u': 296 n = 4 297 case 'U': 298 n = 8 299 } 300 if len(s) < n { 301 return "", "", fmt.Errorf(`\%c requires %d following digits`, r, n) 302 } 303 ss := s[:n] 304 s = s[n:] 305 i, err := strconv.ParseUint(ss, 16, 64) 306 if err != nil { 307 return "", "", fmt.Errorf(`\%c%s contains non-hexadecimal digits`, r, ss) 308 } 309 if r == 'x' || r == 'X' { 310 return string([]byte{byte(i)}), s, nil 311 } 312 if i > utf8.MaxRune { 313 return "", "", fmt.Errorf(`\%c%s is not a valid Unicode code point`, r, ss) 314 } 315 return string(i), s, nil 316 } 317 return "", "", fmt.Errorf(`unknown escape \%c`, r) 318} 319 320// Back off the parser by one token. Can only be done between calls to next(). 321// It makes the next advance() a no-op. 322func (p *textParser) back() { p.backed = true } 323 324// Advances the parser and returns the new current token. 325func (p *textParser) next() *token { 326 if p.backed || p.done { 327 p.backed = false 328 return &p.cur 329 } 330 p.advance() 331 if p.done { 332 p.cur.value = "" 333 } else if len(p.cur.value) > 0 && isQuote(p.cur.value[0]) { 334 // Look for multiple quoted strings separated by whitespace, 335 // and concatenate them. 336 cat := p.cur 337 for { 338 p.skipWhitespace() 339 if p.done || !isQuote(p.s[0]) { 340 break 341 } 342 p.advance() 343 if p.cur.err != nil { 344 return &p.cur 345 } 346 cat.value += " " + p.cur.value 347 cat.unquoted += p.cur.unquoted 348 } 349 p.done = false // parser may have seen EOF, but we want to return cat 350 p.cur = cat 351 } 352 return &p.cur 353} 354 355func (p *textParser) consumeToken(s string) error { 356 tok := p.next() 357 if tok.err != nil { 358 return tok.err 359 } 360 if tok.value != s { 361 p.back() 362 return p.errorf("expected %q, found %q", s, tok.value) 363 } 364 return nil 365} 366 367// Return a RequiredNotSetError indicating which required field was not set. 368func (p *textParser) missingRequiredFieldError(sv reflect.Value) *RequiredNotSetError { 369 st := sv.Type() 370 sprops := GetProperties(st) 371 for i := 0; i < st.NumField(); i++ { 372 if !isNil(sv.Field(i)) { 373 continue 374 } 375 376 props := sprops.Prop[i] 377 if props.Required { 378 return &RequiredNotSetError{fmt.Sprintf("%v.%v", st, props.OrigName)} 379 } 380 } 381 return &RequiredNotSetError{fmt.Sprintf("%v.<unknown field name>", st)} // should not happen 382} 383 384// Returns the index in the struct for the named field, as well as the parsed tag properties. 385func structFieldByName(sprops *StructProperties, name string) (int, *Properties, bool) { 386 i, ok := sprops.decoderOrigNames[name] 387 if ok { 388 return i, sprops.Prop[i], true 389 } 390 return -1, nil, false 391} 392 393// Consume a ':' from the input stream (if the next token is a colon), 394// returning an error if a colon is needed but not present. 395func (p *textParser) checkForColon(props *Properties, typ reflect.Type) *ParseError { 396 tok := p.next() 397 if tok.err != nil { 398 return tok.err 399 } 400 if tok.value != ":" { 401 // Colon is optional when the field is a group or message. 402 needColon := true 403 switch props.Wire { 404 case "group": 405 needColon = false 406 case "bytes": 407 // A "bytes" field is either a message, a string, or a repeated field; 408 // those three become *T, *string and []T respectively, so we can check for 409 // this field being a pointer to a non-string. 410 if typ.Kind() == reflect.Ptr { 411 // *T or *string 412 if typ.Elem().Kind() == reflect.String { 413 break 414 } 415 } else if typ.Kind() == reflect.Slice { 416 // []T or []*T 417 if typ.Elem().Kind() != reflect.Ptr { 418 break 419 } 420 } else if typ.Kind() == reflect.String { 421 // The proto3 exception is for a string field, 422 // which requires a colon. 423 break 424 } 425 needColon = false 426 } 427 if needColon { 428 return p.errorf("expected ':', found %q", tok.value) 429 } 430 p.back() 431 } 432 return nil 433} 434 435func (p *textParser) readStruct(sv reflect.Value, terminator string) error { 436 st := sv.Type() 437 sprops := GetProperties(st) 438 reqCount := sprops.reqCount 439 var reqFieldErr error 440 fieldSet := make(map[string]bool) 441 // A struct is a sequence of "name: value", terminated by one of 442 // '>' or '}', or the end of the input. A name may also be 443 // "[extension]" or "[type/url]". 444 // 445 // The whole struct can also be an expanded Any message, like: 446 // [type/url] < ... struct contents ... > 447 for { 448 tok := p.next() 449 if tok.err != nil { 450 return tok.err 451 } 452 if tok.value == terminator { 453 break 454 } 455 if tok.value == "[" { 456 // Looks like an extension or an Any. 457 // 458 // TODO: Check whether we need to handle 459 // namespace rooted names (e.g. ".something.Foo"). 460 extName, err := p.consumeExtName() 461 if err != nil { 462 return err 463 } 464 465 if s := strings.LastIndex(extName, "/"); s >= 0 { 466 // If it contains a slash, it's an Any type URL. 467 messageName := extName[s+1:] 468 mt := MessageType(messageName) 469 if mt == nil { 470 return p.errorf("unrecognized message %q in google.protobuf.Any", messageName) 471 } 472 tok = p.next() 473 if tok.err != nil { 474 return tok.err 475 } 476 // consume an optional colon 477 if tok.value == ":" { 478 tok = p.next() 479 if tok.err != nil { 480 return tok.err 481 } 482 } 483 var terminator string 484 switch tok.value { 485 case "<": 486 terminator = ">" 487 case "{": 488 terminator = "}" 489 default: 490 return p.errorf("expected '{' or '<', found %q", tok.value) 491 } 492 v := reflect.New(mt.Elem()) 493 if pe := p.readStruct(v.Elem(), terminator); pe != nil { 494 return pe 495 } 496 b, err := Marshal(v.Interface().(Message)) 497 if err != nil { 498 return p.errorf("failed to marshal message of type %q: %v", messageName, err) 499 } 500 if fieldSet["type_url"] { 501 return p.errorf(anyRepeatedlyUnpacked, "type_url") 502 } 503 if fieldSet["value"] { 504 return p.errorf(anyRepeatedlyUnpacked, "value") 505 } 506 sv.FieldByName("TypeUrl").SetString(extName) 507 sv.FieldByName("Value").SetBytes(b) 508 fieldSet["type_url"] = true 509 fieldSet["value"] = true 510 continue 511 } 512 513 var desc *ExtensionDesc 514 // This could be faster, but it's functional. 515 // TODO: Do something smarter than a linear scan. 516 for _, d := range RegisteredExtensions(reflect.New(st).Interface().(Message)) { 517 if d.Name == extName { 518 desc = d 519 break 520 } 521 } 522 if desc == nil { 523 return p.errorf("unrecognized extension %q", extName) 524 } 525 526 props := &Properties{} 527 props.Parse(desc.Tag) 528 529 typ := reflect.TypeOf(desc.ExtensionType) 530 if err := p.checkForColon(props, typ); err != nil { 531 return err 532 } 533 534 rep := desc.repeated() 535 536 // Read the extension structure, and set it in 537 // the value we're constructing. 538 var ext reflect.Value 539 if !rep { 540 ext = reflect.New(typ).Elem() 541 } else { 542 ext = reflect.New(typ.Elem()).Elem() 543 } 544 if err := p.readAny(ext, props); err != nil { 545 if _, ok := err.(*RequiredNotSetError); !ok { 546 return err 547 } 548 reqFieldErr = err 549 } 550 ep := sv.Addr().Interface().(Message) 551 if !rep { 552 SetExtension(ep, desc, ext.Interface()) 553 } else { 554 old, err := GetExtension(ep, desc) 555 var sl reflect.Value 556 if err == nil { 557 sl = reflect.ValueOf(old) // existing slice 558 } else { 559 sl = reflect.MakeSlice(typ, 0, 1) 560 } 561 sl = reflect.Append(sl, ext) 562 SetExtension(ep, desc, sl.Interface()) 563 } 564 if err := p.consumeOptionalSeparator(); err != nil { 565 return err 566 } 567 continue 568 } 569 570 // This is a normal, non-extension field. 571 name := tok.value 572 var dst reflect.Value 573 fi, props, ok := structFieldByName(sprops, name) 574 if ok { 575 dst = sv.Field(fi) 576 } else if oop, ok := sprops.OneofTypes[name]; ok { 577 // It is a oneof. 578 props = oop.Prop 579 nv := reflect.New(oop.Type.Elem()) 580 dst = nv.Elem().Field(0) 581 field := sv.Field(oop.Field) 582 if !field.IsNil() { 583 return p.errorf("field '%s' would overwrite already parsed oneof '%s'", name, sv.Type().Field(oop.Field).Name) 584 } 585 field.Set(nv) 586 } 587 if !dst.IsValid() { 588 return p.errorf("unknown field name %q in %v", name, st) 589 } 590 591 if dst.Kind() == reflect.Map { 592 // Consume any colon. 593 if err := p.checkForColon(props, dst.Type()); err != nil { 594 return err 595 } 596 597 // Construct the map if it doesn't already exist. 598 if dst.IsNil() { 599 dst.Set(reflect.MakeMap(dst.Type())) 600 } 601 key := reflect.New(dst.Type().Key()).Elem() 602 val := reflect.New(dst.Type().Elem()).Elem() 603 604 // The map entry should be this sequence of tokens: 605 // < key : KEY value : VALUE > 606 // However, implementations may omit key or value, and technically 607 // we should support them in any order. See b/28924776 for a time 608 // this went wrong. 609 610 tok := p.next() 611 var terminator string 612 switch tok.value { 613 case "<": 614 terminator = ">" 615 case "{": 616 terminator = "}" 617 default: 618 return p.errorf("expected '{' or '<', found %q", tok.value) 619 } 620 for { 621 tok := p.next() 622 if tok.err != nil { 623 return tok.err 624 } 625 if tok.value == terminator { 626 break 627 } 628 switch tok.value { 629 case "key": 630 if err := p.consumeToken(":"); err != nil { 631 return err 632 } 633 if err := p.readAny(key, props.mkeyprop); err != nil { 634 return err 635 } 636 if err := p.consumeOptionalSeparator(); err != nil { 637 return err 638 } 639 case "value": 640 if err := p.checkForColon(props.mvalprop, dst.Type().Elem()); err != nil { 641 return err 642 } 643 if err := p.readAny(val, props.mvalprop); err != nil { 644 return err 645 } 646 if err := p.consumeOptionalSeparator(); err != nil { 647 return err 648 } 649 default: 650 p.back() 651 return p.errorf(`expected "key", "value", or %q, found %q`, terminator, tok.value) 652 } 653 } 654 655 dst.SetMapIndex(key, val) 656 continue 657 } 658 659 // Check that it's not already set if it's not a repeated field. 660 if !props.Repeated && fieldSet[name] { 661 return p.errorf("non-repeated field %q was repeated", name) 662 } 663 664 if err := p.checkForColon(props, dst.Type()); err != nil { 665 return err 666 } 667 668 // Parse into the field. 669 fieldSet[name] = true 670 if err := p.readAny(dst, props); err != nil { 671 if _, ok := err.(*RequiredNotSetError); !ok { 672 return err 673 } 674 reqFieldErr = err 675 } 676 if props.Required { 677 reqCount-- 678 } 679 680 if err := p.consumeOptionalSeparator(); err != nil { 681 return err 682 } 683 684 } 685 686 if reqCount > 0 { 687 return p.missingRequiredFieldError(sv) 688 } 689 return reqFieldErr 690} 691 692// consumeExtName consumes extension name or expanded Any type URL and the 693// following ']'. It returns the name or URL consumed. 694func (p *textParser) consumeExtName() (string, error) { 695 tok := p.next() 696 if tok.err != nil { 697 return "", tok.err 698 } 699 700 // If extension name or type url is quoted, it's a single token. 701 if len(tok.value) > 2 && isQuote(tok.value[0]) && tok.value[len(tok.value)-1] == tok.value[0] { 702 name, err := unquoteC(tok.value[1:len(tok.value)-1], rune(tok.value[0])) 703 if err != nil { 704 return "", err 705 } 706 return name, p.consumeToken("]") 707 } 708 709 // Consume everything up to "]" 710 var parts []string 711 for tok.value != "]" { 712 parts = append(parts, tok.value) 713 tok = p.next() 714 if tok.err != nil { 715 return "", p.errorf("unrecognized type_url or extension name: %s", tok.err) 716 } 717 if p.done && tok.value != "]" { 718 return "", p.errorf("unclosed type_url or extension name") 719 } 720 } 721 return strings.Join(parts, ""), nil 722} 723 724// consumeOptionalSeparator consumes an optional semicolon or comma. 725// It is used in readStruct to provide backward compatibility. 726func (p *textParser) consumeOptionalSeparator() error { 727 tok := p.next() 728 if tok.err != nil { 729 return tok.err 730 } 731 if tok.value != ";" && tok.value != "," { 732 p.back() 733 } 734 return nil 735} 736 737func (p *textParser) readAny(v reflect.Value, props *Properties) error { 738 tok := p.next() 739 if tok.err != nil { 740 return tok.err 741 } 742 if tok.value == "" { 743 return p.errorf("unexpected EOF") 744 } 745 746 switch fv := v; fv.Kind() { 747 case reflect.Slice: 748 at := v.Type() 749 if at.Elem().Kind() == reflect.Uint8 { 750 // Special case for []byte 751 if tok.value[0] != '"' && tok.value[0] != '\'' { 752 // Deliberately written out here, as the error after 753 // this switch statement would write "invalid []byte: ...", 754 // which is not as user-friendly. 755 return p.errorf("invalid string: %v", tok.value) 756 } 757 bytes := []byte(tok.unquoted) 758 fv.Set(reflect.ValueOf(bytes)) 759 return nil 760 } 761 // Repeated field. 762 if tok.value == "[" { 763 // Repeated field with list notation, like [1,2,3]. 764 for { 765 fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) 766 err := p.readAny(fv.Index(fv.Len()-1), props) 767 if err != nil { 768 return err 769 } 770 tok := p.next() 771 if tok.err != nil { 772 return tok.err 773 } 774 if tok.value == "]" { 775 break 776 } 777 if tok.value != "," { 778 return p.errorf("Expected ']' or ',' found %q", tok.value) 779 } 780 } 781 return nil 782 } 783 // One value of the repeated field. 784 p.back() 785 fv.Set(reflect.Append(fv, reflect.New(at.Elem()).Elem())) 786 return p.readAny(fv.Index(fv.Len()-1), props) 787 case reflect.Bool: 788 // true/1/t/True or false/f/0/False. 789 switch tok.value { 790 case "true", "1", "t", "True": 791 fv.SetBool(true) 792 return nil 793 case "false", "0", "f", "False": 794 fv.SetBool(false) 795 return nil 796 } 797 case reflect.Float32, reflect.Float64: 798 v := tok.value 799 // Ignore 'f' for compatibility with output generated by C++, but don't 800 // remove 'f' when the value is "-inf" or "inf". 801 if strings.HasSuffix(v, "f") && tok.value != "-inf" && tok.value != "inf" { 802 v = v[:len(v)-1] 803 } 804 if f, err := strconv.ParseFloat(v, fv.Type().Bits()); err == nil { 805 fv.SetFloat(f) 806 return nil 807 } 808 case reflect.Int32: 809 if x, err := strconv.ParseInt(tok.value, 0, 32); err == nil { 810 fv.SetInt(x) 811 return nil 812 } 813 814 if len(props.Enum) == 0 { 815 break 816 } 817 m, ok := enumValueMaps[props.Enum] 818 if !ok { 819 break 820 } 821 x, ok := m[tok.value] 822 if !ok { 823 break 824 } 825 fv.SetInt(int64(x)) 826 return nil 827 case reflect.Int64: 828 if x, err := strconv.ParseInt(tok.value, 0, 64); err == nil { 829 fv.SetInt(x) 830 return nil 831 } 832 833 case reflect.Ptr: 834 // A basic field (indirected through pointer), or a repeated message/group 835 p.back() 836 fv.Set(reflect.New(fv.Type().Elem())) 837 return p.readAny(fv.Elem(), props) 838 case reflect.String: 839 if tok.value[0] == '"' || tok.value[0] == '\'' { 840 fv.SetString(tok.unquoted) 841 return nil 842 } 843 case reflect.Struct: 844 var terminator string 845 switch tok.value { 846 case "{": 847 terminator = "}" 848 case "<": 849 terminator = ">" 850 default: 851 return p.errorf("expected '{' or '<', found %q", tok.value) 852 } 853 // TODO: Handle nested messages which implement encoding.TextUnmarshaler. 854 return p.readStruct(fv, terminator) 855 case reflect.Uint32: 856 if x, err := strconv.ParseUint(tok.value, 0, 32); err == nil { 857 fv.SetUint(uint64(x)) 858 return nil 859 } 860 case reflect.Uint64: 861 if x, err := strconv.ParseUint(tok.value, 0, 64); err == nil { 862 fv.SetUint(x) 863 return nil 864 } 865 } 866 return p.errorf("invalid %v: %v", v.Type(), tok.value) 867} 868 869// UnmarshalText reads a protocol buffer in Text format. UnmarshalText resets pb 870// before starting to unmarshal, so any existing data in pb is always removed. 871// If a required field is not set and no other error occurs, 872// UnmarshalText returns *RequiredNotSetError. 873func UnmarshalText(s string, pb Message) error { 874 if um, ok := pb.(encoding.TextUnmarshaler); ok { 875 return um.UnmarshalText([]byte(s)) 876 } 877 pb.Reset() 878 v := reflect.ValueOf(pb) 879 return newTextParser(s).readStruct(v.Elem(), "") 880} 881