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