decode.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729
  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. package text
  5. import (
  6. "bytes"
  7. "fmt"
  8. "io"
  9. "strconv"
  10. "unicode/utf8"
  11. "google.golang.org/protobuf/internal/errors"
  12. )
  13. // Decoder is a token-based textproto decoder.
  14. type Decoder struct {
  15. // lastCall is last method called, either readCall or peekCall.
  16. // Initial value is readCall.
  17. lastCall call
  18. // lastToken contains the last read token.
  19. lastToken Token
  20. // lastErr contains the last read error.
  21. lastErr error
  22. // openStack is a stack containing the byte characters for MessageOpen and
  23. // ListOpen kinds. The top of stack represents the message or the list that
  24. // the current token is nested in. An empty stack means the current token is
  25. // at the top level message. The characters '{' and '<' both represent the
  26. // MessageOpen kind.
  27. openStack []byte
  28. // orig is used in reporting line and column.
  29. orig []byte
  30. // in contains the unconsumed input.
  31. in []byte
  32. }
  33. // NewDecoder returns a Decoder to read the given []byte.
  34. func NewDecoder(b []byte) *Decoder {
  35. return &Decoder{orig: b, in: b}
  36. }
  37. // ErrUnexpectedEOF means that EOF was encountered in the middle of the input.
  38. var ErrUnexpectedEOF = errors.New("%v", io.ErrUnexpectedEOF)
  39. // call specifies which Decoder method was invoked.
  40. type call uint8
  41. const (
  42. readCall call = iota
  43. peekCall
  44. )
  45. // Peek looks ahead and returns the next token and error without advancing a read.
  46. func (d *Decoder) Peek() (Token, error) {
  47. defer func() { d.lastCall = peekCall }()
  48. if d.lastCall == readCall {
  49. d.lastToken, d.lastErr = d.Read()
  50. }
  51. return d.lastToken, d.lastErr
  52. }
  53. // Read returns the next token.
  54. // It will return an error if there is no valid token.
  55. func (d *Decoder) Read() (Token, error) {
  56. defer func() { d.lastCall = readCall }()
  57. if d.lastCall == peekCall {
  58. return d.lastToken, d.lastErr
  59. }
  60. tok, err := d.parseNext(d.lastToken.kind)
  61. if err != nil {
  62. return Token{}, err
  63. }
  64. switch tok.kind {
  65. case comma, semicolon:
  66. tok, err = d.parseNext(tok.kind)
  67. if err != nil {
  68. return Token{}, err
  69. }
  70. }
  71. d.lastToken = tok
  72. return tok, nil
  73. }
  74. const (
  75. mismatchedFmt = "mismatched close character %q"
  76. unexpectedFmt = "unexpected character %q"
  77. )
  78. // parseNext parses the next Token based on given last kind.
  79. func (d *Decoder) parseNext(lastKind Kind) (Token, error) {
  80. // Trim leading spaces.
  81. d.consume(0)
  82. isEOF := false
  83. if len(d.in) == 0 {
  84. isEOF = true
  85. }
  86. switch lastKind {
  87. case EOF:
  88. return d.consumeToken(EOF, 0, 0), nil
  89. case bof:
  90. // Start of top level message. Next token can be EOF or Name.
  91. if isEOF {
  92. return d.consumeToken(EOF, 0, 0), nil
  93. }
  94. return d.parseFieldName()
  95. case Name:
  96. // Next token can be MessageOpen, ListOpen or Scalar.
  97. if isEOF {
  98. return Token{}, ErrUnexpectedEOF
  99. }
  100. switch ch := d.in[0]; ch {
  101. case '{', '<':
  102. d.pushOpenStack(ch)
  103. return d.consumeToken(MessageOpen, 1, 0), nil
  104. case '[':
  105. d.pushOpenStack(ch)
  106. return d.consumeToken(ListOpen, 1, 0), nil
  107. default:
  108. return d.parseScalar()
  109. }
  110. case Scalar:
  111. openKind, closeCh := d.currentOpenKind()
  112. switch openKind {
  113. case bof:
  114. // Top level message.
  115. // Next token can be EOF, comma, semicolon or Name.
  116. if isEOF {
  117. return d.consumeToken(EOF, 0, 0), nil
  118. }
  119. switch d.in[0] {
  120. case ',':
  121. return d.consumeToken(comma, 1, 0), nil
  122. case ';':
  123. return d.consumeToken(semicolon, 1, 0), nil
  124. default:
  125. return d.parseFieldName()
  126. }
  127. case MessageOpen:
  128. // Next token can be MessageClose, comma, semicolon or Name.
  129. if isEOF {
  130. return Token{}, ErrUnexpectedEOF
  131. }
  132. switch ch := d.in[0]; ch {
  133. case closeCh:
  134. d.popOpenStack()
  135. return d.consumeToken(MessageClose, 1, 0), nil
  136. case otherCloseChar[closeCh]:
  137. return Token{}, d.newSyntaxError(mismatchedFmt, ch)
  138. case ',':
  139. return d.consumeToken(comma, 1, 0), nil
  140. case ';':
  141. return d.consumeToken(semicolon, 1, 0), nil
  142. default:
  143. return d.parseFieldName()
  144. }
  145. case ListOpen:
  146. // Next token can be ListClose or comma.
  147. if isEOF {
  148. return Token{}, ErrUnexpectedEOF
  149. }
  150. switch ch := d.in[0]; ch {
  151. case ']':
  152. d.popOpenStack()
  153. return d.consumeToken(ListClose, 1, 0), nil
  154. case ',':
  155. return d.consumeToken(comma, 1, 0), nil
  156. default:
  157. return Token{}, d.newSyntaxError(unexpectedFmt, ch)
  158. }
  159. }
  160. case MessageOpen:
  161. // Next token can be MessageClose or Name.
  162. if isEOF {
  163. return Token{}, ErrUnexpectedEOF
  164. }
  165. _, closeCh := d.currentOpenKind()
  166. switch ch := d.in[0]; ch {
  167. case closeCh:
  168. d.popOpenStack()
  169. return d.consumeToken(MessageClose, 1, 0), nil
  170. case otherCloseChar[closeCh]:
  171. return Token{}, d.newSyntaxError(mismatchedFmt, ch)
  172. default:
  173. return d.parseFieldName()
  174. }
  175. case MessageClose:
  176. openKind, closeCh := d.currentOpenKind()
  177. switch openKind {
  178. case bof:
  179. // Top level message.
  180. // Next token can be EOF, comma, semicolon or Name.
  181. if isEOF {
  182. return d.consumeToken(EOF, 0, 0), nil
  183. }
  184. switch ch := d.in[0]; ch {
  185. case ',':
  186. return d.consumeToken(comma, 1, 0), nil
  187. case ';':
  188. return d.consumeToken(semicolon, 1, 0), nil
  189. default:
  190. return d.parseFieldName()
  191. }
  192. case MessageOpen:
  193. // Next token can be MessageClose, comma, semicolon or Name.
  194. if isEOF {
  195. return Token{}, ErrUnexpectedEOF
  196. }
  197. switch ch := d.in[0]; ch {
  198. case closeCh:
  199. d.popOpenStack()
  200. return d.consumeToken(MessageClose, 1, 0), nil
  201. case otherCloseChar[closeCh]:
  202. return Token{}, d.newSyntaxError(mismatchedFmt, ch)
  203. case ',':
  204. return d.consumeToken(comma, 1, 0), nil
  205. case ';':
  206. return d.consumeToken(semicolon, 1, 0), nil
  207. default:
  208. return d.parseFieldName()
  209. }
  210. case ListOpen:
  211. // Next token can be ListClose or comma
  212. if isEOF {
  213. return Token{}, ErrUnexpectedEOF
  214. }
  215. switch ch := d.in[0]; ch {
  216. case closeCh:
  217. d.popOpenStack()
  218. return d.consumeToken(ListClose, 1, 0), nil
  219. case ',':
  220. return d.consumeToken(comma, 1, 0), nil
  221. default:
  222. return Token{}, d.newSyntaxError(unexpectedFmt, ch)
  223. }
  224. }
  225. case ListOpen:
  226. // Next token can be ListClose, MessageStart or Scalar.
  227. if isEOF {
  228. return Token{}, ErrUnexpectedEOF
  229. }
  230. switch ch := d.in[0]; ch {
  231. case ']':
  232. d.popOpenStack()
  233. return d.consumeToken(ListClose, 1, 0), nil
  234. case '{', '<':
  235. d.pushOpenStack(ch)
  236. return d.consumeToken(MessageOpen, 1, 0), nil
  237. default:
  238. return d.parseScalar()
  239. }
  240. case ListClose:
  241. openKind, closeCh := d.currentOpenKind()
  242. switch openKind {
  243. case bof:
  244. // Top level message.
  245. // Next token can be EOF, comma, semicolon or Name.
  246. if isEOF {
  247. return d.consumeToken(EOF, 0, 0), nil
  248. }
  249. switch ch := d.in[0]; ch {
  250. case ',':
  251. return d.consumeToken(comma, 1, 0), nil
  252. case ';':
  253. return d.consumeToken(semicolon, 1, 0), nil
  254. default:
  255. return d.parseFieldName()
  256. }
  257. case MessageOpen:
  258. // Next token can be MessageClose, comma, semicolon or Name.
  259. if isEOF {
  260. return Token{}, ErrUnexpectedEOF
  261. }
  262. switch ch := d.in[0]; ch {
  263. case closeCh:
  264. d.popOpenStack()
  265. return d.consumeToken(MessageClose, 1, 0), nil
  266. case otherCloseChar[closeCh]:
  267. return Token{}, d.newSyntaxError(mismatchedFmt, ch)
  268. case ',':
  269. return d.consumeToken(comma, 1, 0), nil
  270. case ';':
  271. return d.consumeToken(semicolon, 1, 0), nil
  272. default:
  273. return d.parseFieldName()
  274. }
  275. default:
  276. // It is not possible to have this case. Let it panic below.
  277. }
  278. case comma, semicolon:
  279. openKind, closeCh := d.currentOpenKind()
  280. switch openKind {
  281. case bof:
  282. // Top level message. Next token can be EOF or Name.
  283. if isEOF {
  284. return d.consumeToken(EOF, 0, 0), nil
  285. }
  286. return d.parseFieldName()
  287. case MessageOpen:
  288. // Next token can be MessageClose or Name.
  289. if isEOF {
  290. return Token{}, ErrUnexpectedEOF
  291. }
  292. switch ch := d.in[0]; ch {
  293. case closeCh:
  294. d.popOpenStack()
  295. return d.consumeToken(MessageClose, 1, 0), nil
  296. case otherCloseChar[closeCh]:
  297. return Token{}, d.newSyntaxError(mismatchedFmt, ch)
  298. default:
  299. return d.parseFieldName()
  300. }
  301. case ListOpen:
  302. if lastKind == semicolon {
  303. // It is not be possible to have this case as logic here
  304. // should not have produced a semicolon Token when inside a
  305. // list. Let it panic below.
  306. break
  307. }
  308. // Next token can be MessageOpen or Scalar.
  309. if isEOF {
  310. return Token{}, ErrUnexpectedEOF
  311. }
  312. switch ch := d.in[0]; ch {
  313. case '{', '<':
  314. d.pushOpenStack(ch)
  315. return d.consumeToken(MessageOpen, 1, 0), nil
  316. default:
  317. return d.parseScalar()
  318. }
  319. }
  320. }
  321. line, column := d.Position(len(d.orig) - len(d.in))
  322. panic(fmt.Sprintf("Decoder.parseNext: bug at handling line %d:%d with lastKind=%v", line, column, lastKind))
  323. }
  324. var otherCloseChar = map[byte]byte{
  325. '}': '>',
  326. '>': '}',
  327. }
  328. // currentOpenKind indicates whether current position is inside a message, list
  329. // or top-level message by returning MessageOpen, ListOpen or bof respectively.
  330. // If the returned kind is either a MessageOpen or ListOpen, it also returns the
  331. // corresponding closing character.
  332. func (d *Decoder) currentOpenKind() (Kind, byte) {
  333. if len(d.openStack) == 0 {
  334. return bof, 0
  335. }
  336. openCh := d.openStack[len(d.openStack)-1]
  337. switch openCh {
  338. case '{':
  339. return MessageOpen, '}'
  340. case '<':
  341. return MessageOpen, '>'
  342. case '[':
  343. return ListOpen, ']'
  344. }
  345. panic(fmt.Sprintf("Decoder: openStack contains invalid byte %c", openCh))
  346. }
  347. func (d *Decoder) pushOpenStack(ch byte) {
  348. d.openStack = append(d.openStack, ch)
  349. }
  350. func (d *Decoder) popOpenStack() {
  351. d.openStack = d.openStack[:len(d.openStack)-1]
  352. }
  353. // parseFieldName parses field name and separator.
  354. func (d *Decoder) parseFieldName() (tok Token, err error) {
  355. defer func() {
  356. if err == nil && d.tryConsumeChar(':') {
  357. tok.attrs |= hasSeparator
  358. }
  359. }()
  360. // Extension or Any type URL.
  361. if d.in[0] == '[' {
  362. return d.parseTypeName()
  363. }
  364. // Identifier.
  365. if size := parseIdent(d.in, false); size > 0 {
  366. return d.consumeToken(Name, size, uint8(IdentName)), nil
  367. }
  368. // Field number. Identify if input is a valid number that is not negative
  369. // and is decimal integer within 32-bit range.
  370. if num := parseNumber(d.in); num.size > 0 {
  371. str := num.string(d.in)
  372. if !num.neg && num.kind == numDec {
  373. if _, err := strconv.ParseInt(str, 10, 32); err == nil {
  374. return d.consumeToken(Name, num.size, uint8(FieldNumber)), nil
  375. }
  376. }
  377. return Token{}, d.newSyntaxError("invalid field number: %s", str)
  378. }
  379. return Token{}, d.newSyntaxError("invalid field name: %s", errId(d.in))
  380. }
  381. // parseTypeName parses an Any type URL or an extension field name. The name is
  382. // enclosed in [ and ] characters. We allow almost arbitrary type URL prefixes,
  383. // closely following the text-format spec [1,2]. We implement "ExtensionName |
  384. // AnyName" as follows (with some exceptions for backwards compatibility):
  385. //
  386. // char = [-_a-zA-Z0-9]
  387. // url_char = char | [.~!$&'()*+,;=] | "%", hex, hex
  388. //
  389. // Ident = char, { char }
  390. // TypeName = Ident, { ".", Ident } ;
  391. // UrlPrefix = url_char, { url_char | "/" } ;
  392. // ExtensionName = "[", TypeName, "]" ;
  393. // AnyName = "[", UrlPrefix, "/", TypeName, "]" ;
  394. //
  395. // Additionally, we allow arbitrary whitespace and comments between [ and ].
  396. //
  397. // [1] https://protobuf.dev/reference/protobuf/textformat-spec/#characters
  398. // [2] https://protobuf.dev/reference/protobuf/textformat-spec/#field-names
  399. func (d *Decoder) parseTypeName() (Token, error) {
  400. // Use alias s to advance first in order to use d.in for error handling.
  401. // Caller already checks for [ as first character (d.in[0] == '[').
  402. s := consume(d.in[1:], 0)
  403. if len(s) == 0 {
  404. return Token{}, ErrUnexpectedEOF
  405. }
  406. // Collect everything between [ and ] in name.
  407. var name []byte
  408. var closed bool
  409. for len(s) > 0 && !closed {
  410. switch {
  411. case s[0] == ']':
  412. s = s[1:]
  413. closed = true
  414. case s[0] == '/' || isTypeNameChar(s[0]) || isUrlExtraChar(s[0]):
  415. name = append(name, s[0])
  416. s = consume(s[1:], 0)
  417. // URL percent-encoded chars
  418. case s[0] == '%':
  419. if len(s) < 3 || !isHexChar(s[1]) || !isHexChar(s[2]) {
  420. return Token{}, d.parseTypeNameError(s, 3)
  421. }
  422. name = append(name, s[0], s[1], s[2])
  423. s = consume(s[3:], 0)
  424. default:
  425. return Token{}, d.parseTypeNameError(s, 1)
  426. }
  427. }
  428. if !closed {
  429. return Token{}, ErrUnexpectedEOF
  430. }
  431. // Split collected name on last '/' into urlPrefix and typeName (if '/' is
  432. // present).
  433. typeName := name
  434. if i := bytes.LastIndexByte(name, '/'); i != -1 {
  435. urlPrefix := name[:i]
  436. typeName = name[i+1:]
  437. // urlPrefix may be empty (for backwards compatibility).
  438. // If non-empty, it must not start with '/'.
  439. if len(urlPrefix) > 0 && urlPrefix[0] == '/' {
  440. return Token{}, d.parseTypeNameError(s, 0)
  441. }
  442. }
  443. // typeName must not be empty (note: "" splits to [""]) and all identifier
  444. // parts must not be empty.
  445. for _, ident := range bytes.Split(typeName, []byte{'.'}) {
  446. if len(ident) == 0 {
  447. return Token{}, d.parseTypeNameError(s, 0)
  448. }
  449. }
  450. // typeName must not contain any percent-encoded or special URL chars.
  451. for _, b := range typeName {
  452. if b == '%' || (b != '.' && isUrlExtraChar(b)) {
  453. return Token{}, d.parseTypeNameError(s, 0)
  454. }
  455. }
  456. startPos := len(d.orig) - len(d.in)
  457. endPos := len(d.orig) - len(s)
  458. d.in = s
  459. d.consume(0)
  460. return Token{
  461. kind: Name,
  462. attrs: uint8(TypeName),
  463. pos: startPos,
  464. raw: d.orig[startPos:endPos],
  465. str: string(name),
  466. }, nil
  467. }
  468. func (d *Decoder) parseTypeNameError(s []byte, numUnconsumedChars int) error {
  469. return d.newSyntaxError(
  470. "invalid type URL/extension field name: %s",
  471. d.in[:len(d.in)-len(s)+min(numUnconsumedChars, len(s))],
  472. )
  473. }
  474. func isHexChar(b byte) bool {
  475. return ('0' <= b && b <= '9') ||
  476. ('a' <= b && b <= 'f') ||
  477. ('A' <= b && b <= 'F')
  478. }
  479. func isTypeNameChar(b byte) bool {
  480. return b == '-' || b == '_' ||
  481. ('0' <= b && b <= '9') ||
  482. ('a' <= b && b <= 'z') ||
  483. ('A' <= b && b <= 'Z')
  484. }
  485. // isUrlExtraChar complements isTypeNameChar with extra characters that we allow
  486. // in URLs but not in type names. Note that '/' is not included so that it can
  487. // be treated specially.
  488. func isUrlExtraChar(b byte) bool {
  489. switch b {
  490. case '.', '~', '!', '$', '&', '(', ')', '*', '+', ',', ';', '=':
  491. return true
  492. default:
  493. return false
  494. }
  495. }
  496. // parseIdent parses an unquoted proto identifier and returns size.
  497. // If allowNeg is true, it allows '-' to be the first character in the
  498. // identifier. This is used when parsing literal values like -infinity, etc.
  499. // Regular expression matches an identifier: `^[_a-zA-Z][_a-zA-Z0-9]*`
  500. func parseIdent(input []byte, allowNeg bool) int {
  501. var size int
  502. s := input
  503. if len(s) == 0 {
  504. return 0
  505. }
  506. if allowNeg && s[0] == '-' {
  507. s = s[1:]
  508. size++
  509. if len(s) == 0 {
  510. return 0
  511. }
  512. }
  513. switch {
  514. case s[0] == '_',
  515. 'a' <= s[0] && s[0] <= 'z',
  516. 'A' <= s[0] && s[0] <= 'Z':
  517. s = s[1:]
  518. size++
  519. default:
  520. return 0
  521. }
  522. for len(s) > 0 && (s[0] == '_' ||
  523. 'a' <= s[0] && s[0] <= 'z' ||
  524. 'A' <= s[0] && s[0] <= 'Z' ||
  525. '0' <= s[0] && s[0] <= '9') {
  526. s = s[1:]
  527. size++
  528. }
  529. if len(s) > 0 && !isDelim(s[0]) {
  530. return 0
  531. }
  532. return size
  533. }
  534. // parseScalar parses for a string, literal or number value.
  535. func (d *Decoder) parseScalar() (Token, error) {
  536. if d.in[0] == '"' || d.in[0] == '\'' {
  537. return d.parseStringValue()
  538. }
  539. if tok, ok := d.parseLiteralValue(); ok {
  540. return tok, nil
  541. }
  542. if tok, ok := d.parseNumberValue(); ok {
  543. return tok, nil
  544. }
  545. return Token{}, d.newSyntaxError("invalid scalar value: %s", errId(d.in))
  546. }
  547. // parseLiteralValue parses a literal value. A literal value is used for
  548. // bools, special floats and enums. This function simply identifies that the
  549. // field value is a literal.
  550. func (d *Decoder) parseLiteralValue() (Token, bool) {
  551. size := parseIdent(d.in, true)
  552. if size == 0 {
  553. return Token{}, false
  554. }
  555. return d.consumeToken(Scalar, size, literalValue), true
  556. }
  557. // consumeToken constructs a Token for given Kind from d.in and consumes given
  558. // size-length from it.
  559. func (d *Decoder) consumeToken(kind Kind, size int, attrs uint8) Token {
  560. // Important to compute raw and pos before consuming.
  561. tok := Token{
  562. kind: kind,
  563. attrs: attrs,
  564. pos: len(d.orig) - len(d.in),
  565. raw: d.in[:size],
  566. }
  567. d.consume(size)
  568. return tok
  569. }
  570. // newSyntaxError returns a syntax error with line and column information for
  571. // current position.
  572. func (d *Decoder) newSyntaxError(f string, x ...any) error {
  573. e := errors.New(f, x...)
  574. line, column := d.Position(len(d.orig) - len(d.in))
  575. return errors.New("syntax error (line %d:%d): %v", line, column, e)
  576. }
  577. // Position returns line and column number of given index of the original input.
  578. // It will panic if index is out of range.
  579. func (d *Decoder) Position(idx int) (line int, column int) {
  580. b := d.orig[:idx]
  581. line = bytes.Count(b, []byte("\n")) + 1
  582. if i := bytes.LastIndexByte(b, '\n'); i >= 0 {
  583. b = b[i+1:]
  584. }
  585. column = utf8.RuneCount(b) + 1 // ignore multi-rune characters
  586. return line, column
  587. }
  588. func (d *Decoder) tryConsumeChar(c byte) bool {
  589. if len(d.in) > 0 && d.in[0] == c {
  590. d.consume(1)
  591. return true
  592. }
  593. return false
  594. }
  595. // consume consumes n bytes of input and any subsequent whitespace or comments.
  596. func (d *Decoder) consume(n int) {
  597. d.in = consume(d.in, n)
  598. return
  599. }
  600. // consume consumes n bytes of input and any subsequent whitespace or comments.
  601. func consume(b []byte, n int) []byte {
  602. b = b[n:]
  603. for len(b) > 0 {
  604. switch b[0] {
  605. case ' ', '\n', '\r', '\t':
  606. b = b[1:]
  607. case '#':
  608. if i := bytes.IndexByte(b, '\n'); i >= 0 {
  609. b = b[i+len("\n"):]
  610. } else {
  611. b = nil
  612. }
  613. default:
  614. return b
  615. }
  616. }
  617. return b
  618. }
  619. // errId extracts a byte sequence that looks like an invalid ID
  620. // (for the purposes of error reporting).
  621. func errId(seq []byte) []byte {
  622. const maxLen = 32
  623. for i := 0; i < len(seq); {
  624. if i > maxLen {
  625. return append(seq[:i:i], "…"...)
  626. }
  627. r, size := utf8.DecodeRune(seq[i:])
  628. if r > utf8.RuneSelf || (r != '/' && isDelim(byte(r))) {
  629. if i == 0 {
  630. // Either the first byte is invalid UTF-8 or a
  631. // delimiter, or the first rune is non-ASCII.
  632. // Return it as-is.
  633. i = size
  634. }
  635. return seq[:i:i]
  636. }
  637. i += size
  638. }
  639. // No delimiter found.
  640. return seq
  641. }
  642. // isDelim returns true if given byte is a delimiter character.
  643. func isDelim(c byte) bool {
  644. return !(c == '-' || c == '+' || c == '.' || c == '_' ||
  645. ('a' <= c && c <= 'z') ||
  646. ('A' <= c && c <= 'Z') ||
  647. ('0' <= c && c <= '9'))
  648. }