v2: errors (#534)
``` name old time/op new time/op delta UnmarshalDataset/config-32 86.7ms ± 2% 87.5ms ± 2% ~ (p=0.113 n=9+10) UnmarshalDataset/canada-32 129ms ± 4% 106ms ± 3% -17.94% (p=0.000 n=10+10) UnmarshalDataset/citm_catalog-32 59.4ms ± 5% 58.7ms ± 5% ~ (p=0.393 n=10+10) UnmarshalDataset/twitter-32 27.0ms ± 7% 26.9ms ± 6% ~ (p=0.720 n=10+9) UnmarshalDataset/code-32 326ms ± 4% 322ms ± 7% ~ (p=0.661 n=9+10) UnmarshalDataset/example-32 510µs ±11% 526µs ± 7% ~ (p=0.182 n=10+9) UnmarshalSimple-32 1.41µs ± 6% 1.41µs ± 4% ~ (p=0.736 n=10+9) ReferenceFile-32 45.6µs ± 3% 43.9µs ±10% ~ (p=0.089 n=10+10) name old speed new speed delta UnmarshalDataset/config-32 12.1MB/s ± 2% 12.0MB/s ± 2% ~ (p=0.108 n=9+10) UnmarshalDataset/canada-32 17.1MB/s ± 4% 20.9MB/s ± 3% +21.86% (p=0.000 n=10+10) UnmarshalDataset/citm_catalog-32 9.41MB/s ± 5% 9.51MB/s ± 5% ~ (p=0.362 n=10+10) UnmarshalDataset/twitter-32 16.4MB/s ± 8% 16.5MB/s ± 6% ~ (p=0.704 n=10+9) UnmarshalDataset/code-32 8.24MB/s ± 4% 8.34MB/s ± 7% ~ (p=0.675 n=9+10) UnmarshalDataset/example-32 15.9MB/s ±11% 15.4MB/s ± 7% ~ (p=0.182 n=10+9) ReferenceFile-32 115MB/s ± 4% 120MB/s ±10% ~ (p=0.085 n=10+10) name old alloc/op new alloc/op delta UnmarshalDataset/config-32 16.9MB ± 0% 16.9MB ± 0% -0.02% (p=0.000 n=10+10) UnmarshalDataset/canada-32 76.8MB ± 0% 74.3MB ± 0% -3.31% (p=0.000 n=10+10) UnmarshalDataset/citm_catalog-32 37.3MB ± 0% 37.1MB ± 0% -0.60% (p=0.000 n=9+10) UnmarshalDataset/twitter-32 15.6MB ± 0% 15.6MB ± 0% -0.09% (p=0.000 n=10+10) UnmarshalDataset/code-32 60.2MB ± 0% 59.3MB ± 0% -1.51% (p=0.000 n=10+9) UnmarshalDataset/example-32 238kB ± 0% 238kB ± 0% -0.18% (p=0.000 n=10+10) ReferenceFile-32 11.8kB ± 0% 11.8kB ± 0% ~ (all equal) name old allocs/op new allocs/op delta UnmarshalDataset/config-32 653k ± 0% 645k ± 0% -1.20% (p=0.000 n=10+6) UnmarshalDataset/canada-32 1.01M ± 0% 0.90M ± 0% -11.04% (p=0.000 n=9+10) UnmarshalDataset/citm_catalog-32 384k ± 0% 370k ± 0% -3.75% (p=0.000 n=10+10) UnmarshalDataset/twitter-32 160k ± 0% 157k ± 0% -1.32% (p=0.000 n=10+10) UnmarshalDataset/code-32 2.97M ± 0% 2.91M ± 0% -2.15% (p=0.000 n=10+7) UnmarshalDataset/example-32 3.69k ± 0% 3.63k ± 0% -1.52% (p=0.000 n=10+10) ReferenceFile-32 253 ± 0% 253 ± 0% ~ (all equal) ```
This commit is contained in:
@@ -2,7 +2,6 @@ package toml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
|
||||
@@ -225,19 +224,13 @@ func (p *parser) parseKeyval(b []byte) (ast.Reference, []byte, error) {
|
||||
return ref, b, err
|
||||
}
|
||||
|
||||
var (
|
||||
errExpectedValNotEOF = errors.New("expected value, not eof")
|
||||
errExpectedTrue = errors.New("expected 'true'")
|
||||
errExpectedFalse = errors.New("expected 'false'")
|
||||
)
|
||||
|
||||
//nolint:cyclop,funlen
|
||||
func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
|
||||
// val = string / boolean / array / inline-table / date-time / float / integer
|
||||
var ref ast.Reference
|
||||
|
||||
if len(b) == 0 {
|
||||
return ref, nil, errExpectedValNotEOF
|
||||
return ref, nil, newDecodeError(b, "expected value, not eof")
|
||||
}
|
||||
|
||||
var err error
|
||||
@@ -278,7 +271,7 @@ func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
|
||||
return ref, b, err
|
||||
case 't':
|
||||
if !scanFollowsTrue(b) {
|
||||
return ref, nil, errExpectedTrue
|
||||
return ref, nil, newDecodeError(atmost(b, 4), "expected 'true'")
|
||||
}
|
||||
|
||||
ref = p.builder.Push(ast.Node{
|
||||
@@ -289,7 +282,7 @@ func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
|
||||
return ref, b[4:], nil
|
||||
case 'f':
|
||||
if !scanFollowsFalse(b) {
|
||||
return ast.Reference{}, nil, errExpectedFalse
|
||||
return ref, nil, newDecodeError(atmost(b, 5), "expected 'false'")
|
||||
}
|
||||
|
||||
ref = p.builder.Push(ast.Node{
|
||||
@@ -307,6 +300,13 @@ func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func atmost(b []byte, n int) []byte {
|
||||
if n >= len(b) {
|
||||
return b
|
||||
}
|
||||
return b[:n]
|
||||
}
|
||||
|
||||
func (p *parser) parseLiteralString(b []byte) ([]byte, []byte, error) {
|
||||
v, rest, err := scanLiteralString(b)
|
||||
if err != nil {
|
||||
@@ -370,8 +370,6 @@ func (p *parser) parseInlineTable(b []byte) (ast.Reference, []byte, error) {
|
||||
return parent, rest, err
|
||||
}
|
||||
|
||||
var errArrayCannotStartWithComma = errors.New("array cannot start with comma")
|
||||
|
||||
//nolint:funlen,cyclop
|
||||
func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
|
||||
// array = array-open [ array-values ] ws-comment-newline array-close
|
||||
@@ -409,7 +407,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
|
||||
|
||||
if b[0] == ',' {
|
||||
if first {
|
||||
return parent, nil, errArrayCannotStartWithComma
|
||||
return parent, nil, newDecodeError(b[0:1], "array cannot start with comma")
|
||||
}
|
||||
b = b[1:]
|
||||
|
||||
@@ -494,8 +492,6 @@ func (p *parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, error) {
|
||||
return token[i : len(token)-3], rest, err
|
||||
}
|
||||
|
||||
var errInvalidEscapeChar = errors.New("invalid escaped character")
|
||||
|
||||
//nolint:funlen,gocognit,cyclop
|
||||
func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) {
|
||||
// ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
|
||||
@@ -582,7 +578,7 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) {
|
||||
builder.WriteString(x)
|
||||
i += 8
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("parseMultilineBasicString: %w - %#U", errInvalidEscapeChar, c)
|
||||
return nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
|
||||
}
|
||||
} else {
|
||||
builder.WriteByte(c)
|
||||
@@ -721,7 +717,7 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, error) {
|
||||
builder.WriteString(x)
|
||||
i += 8
|
||||
default:
|
||||
return nil, nil, fmt.Errorf("parseBasicString: %w - %#U", errInvalidEscapeChar, c)
|
||||
return nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
|
||||
}
|
||||
} else {
|
||||
builder.WriteByte(c)
|
||||
@@ -731,18 +727,17 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, error) {
|
||||
return builder.Bytes(), rest, nil
|
||||
}
|
||||
|
||||
var errUnicodePointNeedsRightCountChar = errors.New("unicode point needs right number of hex characters")
|
||||
|
||||
func hexToString(b []byte, length int) (string, error) {
|
||||
if len(b) < length {
|
||||
return "", fmt.Errorf("hexToString: %w - %d", errUnicodePointNeedsRightCountChar, length)
|
||||
return "", newDecodeError(b, "unicode point needs %d character, not %d", length, len(b))
|
||||
}
|
||||
b = b[:length]
|
||||
|
||||
//nolint:godox
|
||||
// TODO: slow
|
||||
intcode, err := strconv.ParseInt(string(b[:length]), 16, 32)
|
||||
intcode, err := strconv.ParseInt(string(b), 16, 32)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("hexToString: %w", err)
|
||||
return "", newDecodeError(b, "couldn't parse hexadecimal number: %w", err)
|
||||
}
|
||||
|
||||
return string(rune(intcode)), nil
|
||||
@@ -757,17 +752,12 @@ func (p *parser) parseWhitespace(b []byte) []byte {
|
||||
return rest
|
||||
}
|
||||
|
||||
var (
|
||||
errExpectedInf = errors.New("expected 'inf'")
|
||||
errExpectedNan = errors.New("expected 'nan'")
|
||||
)
|
||||
|
||||
//nolint:cyclop
|
||||
func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, error) {
|
||||
switch b[0] {
|
||||
case 'i':
|
||||
if !scanFollowsInf(b) {
|
||||
return ast.Reference{}, nil, errExpectedInf
|
||||
return ast.Reference{}, nil, newDecodeError(atmost(b, 3), "expected 'inf'")
|
||||
}
|
||||
|
||||
return p.builder.Push(ast.Node{
|
||||
@@ -776,7 +766,7 @@ func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, err
|
||||
}), b[3:], nil
|
||||
case 'n':
|
||||
if !scanFollowsNan(b) {
|
||||
return ast.Reference{}, nil, errExpectedNan
|
||||
return ast.Reference{}, nil, newDecodeError(atmost(b, 3), "expected 'nan'")
|
||||
}
|
||||
|
||||
return p.builder.Push(ast.Node{
|
||||
@@ -821,8 +811,6 @@ func digitsToInt(b []byte) int {
|
||||
return x
|
||||
}
|
||||
|
||||
var errTimezoneButNoTimeComponent = errors.New("possible DateTime cannot have a timezone but no time component")
|
||||
|
||||
//nolint:gocognit,cyclop
|
||||
func (p *parser) scanDateTime(b []byte) (ast.Reference, []byte, error) {
|
||||
// scans for contiguous characters in [0-9T:Z.+-], and up to one space if
|
||||
@@ -867,7 +855,7 @@ byteLoop:
|
||||
}
|
||||
} else {
|
||||
if hasTz {
|
||||
return ast.Reference{}, nil, errTimezoneButNoTimeComponent
|
||||
return ast.Reference{}, nil, newDecodeError(b, "date-time has timezone but not time component")
|
||||
}
|
||||
kind = ast.LocalDate
|
||||
}
|
||||
@@ -878,12 +866,6 @@ byteLoop:
|
||||
}), b[i:], nil
|
||||
}
|
||||
|
||||
var (
|
||||
errUnexpectedCharI = fmt.Errorf("unexpected character i while scanning for a number")
|
||||
errUnexpectedCharN = fmt.Errorf("unexpected character n while scanning for a number")
|
||||
errExpectedIntOrFloat = fmt.Errorf("expected integer or float")
|
||||
)
|
||||
|
||||
//nolint:funlen,gocognit,cyclop
|
||||
func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
|
||||
i := 0
|
||||
@@ -940,7 +922,7 @@ func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
|
||||
}), b[i+3:], nil
|
||||
}
|
||||
|
||||
return ast.Reference{}, nil, errUnexpectedCharI
|
||||
return ast.Reference{}, nil, newDecodeError(b[i:i+1], "unexpected character 'i' while scanning for a number")
|
||||
}
|
||||
|
||||
if c == 'n' {
|
||||
@@ -951,14 +933,14 @@ func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
|
||||
}), b[i+3:], nil
|
||||
}
|
||||
|
||||
return ast.Reference{}, nil, errUnexpectedCharN
|
||||
return ast.Reference{}, nil, newDecodeError(b[i:i+1], "unexpected character 'n' while scanning for a number")
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
if i == 0 {
|
||||
return ast.Reference{}, b, errExpectedIntOrFloat
|
||||
return ast.Reference{}, b, newDecodeError(b, "incomplete number")
|
||||
}
|
||||
|
||||
kind := ast.Integer
|
||||
|
||||
Reference in New Issue
Block a user