equal
deleted
inserted
replaced
6 |
6 |
7 import ( |
7 import ( |
8 "bytes" |
8 "bytes" |
9 "fmt" |
9 "fmt" |
10 "io" |
10 "io" |
11 "regexp" |
|
12 "strconv" |
11 "strconv" |
13 "unicode/utf8" |
12 "unicode/utf8" |
14 |
13 |
15 "google.golang.org/protobuf/internal/errors" |
14 "google.golang.org/protobuf/internal/errors" |
16 ) |
15 ) |
379 case '<': |
378 case '<': |
380 return MessageOpen, '>' |
379 return MessageOpen, '>' |
381 case '[': |
380 case '[': |
382 return ListOpen, ']' |
381 return ListOpen, ']' |
383 } |
382 } |
384 panic(fmt.Sprintf("Decoder: openStack contains invalid byte %s", string(openCh))) |
383 panic(fmt.Sprintf("Decoder: openStack contains invalid byte %c", openCh)) |
385 } |
384 } |
386 |
385 |
387 func (d *Decoder) pushOpenStack(ch byte) { |
386 func (d *Decoder) pushOpenStack(ch byte) { |
388 d.openStack = append(d.openStack, ch) |
387 d.openStack = append(d.openStack, ch) |
389 } |
388 } |
419 } |
418 } |
420 } |
419 } |
421 return Token{}, d.newSyntaxError("invalid field number: %s", d.in[:num.size]) |
420 return Token{}, d.newSyntaxError("invalid field number: %s", d.in[:num.size]) |
422 } |
421 } |
423 |
422 |
424 return Token{}, d.newSyntaxError("invalid field name: %s", errRegexp.Find(d.in)) |
423 return Token{}, d.newSyntaxError("invalid field name: %s", errId(d.in)) |
425 } |
424 } |
426 |
425 |
427 // parseTypeName parses Any type URL or extension field name. The name is |
426 // parseTypeName parses Any type URL or extension field name. The name is |
428 // enclosed in [ and ] characters. The C++ parser does not handle many legal URL |
427 // enclosed in [ and ] characters. The C++ parser does not handle many legal URL |
429 // strings. This implementation is more liberal and allows for the pattern |
428 // strings. This implementation is more liberal and allows for the pattern |
569 |
568 |
570 if tok, ok := d.parseNumberValue(); ok { |
569 if tok, ok := d.parseNumberValue(); ok { |
571 return tok, nil |
570 return tok, nil |
572 } |
571 } |
573 |
572 |
574 return Token{}, d.newSyntaxError("invalid scalar value: %s", errRegexp.Find(d.in)) |
573 return Token{}, d.newSyntaxError("invalid scalar value: %s", errId(d.in)) |
575 } |
574 } |
576 |
575 |
577 // parseLiteralValue parses a literal value. A literal value is used for |
576 // parseLiteralValue parses a literal value. A literal value is used for |
578 // bools, special floats and enums. This function simply identifies that the |
577 // bools, special floats and enums. This function simply identifies that the |
579 // field value is a literal. |
578 // field value is a literal. |
651 } |
650 } |
652 } |
651 } |
653 return b |
652 return b |
654 } |
653 } |
655 |
654 |
656 // Any sequence that looks like a non-delimiter (for error reporting). |
655 // errId extracts a byte sequence that looks like an invalid ID |
657 var errRegexp = regexp.MustCompile(`^([-+._a-zA-Z0-9\/]+|.)`) |
656 // (for the purposes of error reporting). |
|
657 func errId(seq []byte) []byte { |
|
658 const maxLen = 32 |
|
659 for i := 0; i < len(seq); { |
|
660 if i > maxLen { |
|
661 return append(seq[:i:i], "…"...) |
|
662 } |
|
663 r, size := utf8.DecodeRune(seq[i:]) |
|
664 if r > utf8.RuneSelf || (r != '/' && isDelim(byte(r))) { |
|
665 if i == 0 { |
|
666 // Either the first byte is invalid UTF-8 or a |
|
667 // delimiter, or the first rune is non-ASCII. |
|
668 // Return it as-is. |
|
669 i = size |
|
670 } |
|
671 return seq[:i:i] |
|
672 } |
|
673 i += size |
|
674 } |
|
675 // No delimiter found. |
|
676 return seq |
|
677 } |
658 |
678 |
659 // isDelim returns true if given byte is a delimiter character. |
679 // isDelim returns true if given byte is a delimiter character. |
660 func isDelim(c byte) bool { |
680 func isDelim(c byte) bool { |
661 return !(c == '-' || c == '+' || c == '.' || c == '_' || |
681 return !(c == '-' || c == '+' || c == '.' || c == '_' || |
662 ('a' <= c && c <= 'z') || |
682 ('a' <= c && c <= 'z') || |