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:
Thomas Pelletier
2021-05-08 16:04:25 -04:00
committed by GitHub
parent 4545a3e94b
commit ea225df3ed
12 changed files with 325 additions and 656 deletions
+34 -67
View File
@@ -56,7 +56,7 @@ func (d *Decoder) SetStrict(strict bool) {
func (d *Decoder) Decode(v interface{}) error {
b, err := ioutil.ReadAll(d.r)
if err != nil {
return fmt.Errorf("Decode: %w", err)
return fmt.Errorf("toml: %w", err)
}
p := parser{}
@@ -130,20 +130,15 @@ func keyLocation(node ast.Node) []byte {
return unsafe.BytesRange(start, end)
}
var (
errFromParserExpectingPointer = errors.New("expecting a pointer as target")
errFromParserExpectingNonNilPointer = errors.New("expecting non nil pointer as target")
)
//nolint:funlen,cyclop
func (d *decoder) fromParser(p *parser, v interface{}) error {
r := reflect.ValueOf(v)
if r.Kind() != reflect.Ptr {
return fmt.Errorf("fromParser: %w, not %s", errFromParserExpectingPointer, r.Kind())
return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind())
}
if r.IsNil() {
return errFromParserExpectingNonNilPointer
return fmt.Errorf("toml: decoding pointer target cannot be nil")
}
var (
@@ -162,7 +157,7 @@ func (d *decoder) fromParser(p *parser, v interface{}) error {
err := d.seen.CheckExpression(node)
if err != nil {
return fmt.Errorf("fromParser: %w", err)
return err
}
var found bool
@@ -181,16 +176,13 @@ func (d *decoder) fromParser(p *parser, v interface{}) error {
// looks like a table. Otherwise the information
// of a table is lost, and marshal cannot do the
// round trip.
err := ensureMapIfInterface(current)
if err != nil {
panic(fmt.Sprintf("ensureMapIfInterface: %s", err))
}
ensureMapIfInterface(current)
}
case ast.ArrayTable:
d.strict.EnterArrayTable(node)
current, found, err = d.scopeWithArrayTable(root, node.Key())
default:
panic(fmt.Sprintf("fromParser: this should not be a top level node type: %s", node.Kind))
panic(fmt.Sprintf("this should not be a top level node type: %s", node.Kind))
}
if err != nil {
@@ -267,26 +259,18 @@ func (d *decoder) scopeWithArrayTable(x target, key ast.Iterator) (target, bool,
v := x.get()
if v.Kind() == reflect.Ptr {
x, err = scopePtr(x)
if err != nil {
return x, false, err
}
x = scopePtr(x)
v = x.get()
}
if v.Kind() == reflect.Interface {
x, err = scopeInterface(true, x)
if err != nil {
return x, found, err
}
x = scopeInterface(true, x)
v = x.get()
}
switch v.Kind() {
case reflect.Slice:
x, err = scopeSlice(true, x)
x = scopeSlice(true, x)
case reflect.Array:
x, err = d.scopeArray(true, x)
default:
@@ -334,7 +318,7 @@ func tryTextUnmarshaler(x target, node ast.Node) (bool, error) {
if v.Type().Implements(textUnmarshalerType) {
err := v.Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
if err != nil {
return false, fmt.Errorf("tryTextUnmarshaler: %w", err)
return false, newDecodeError(node.Data, "error calling UnmarshalText: %w", err)
}
return true, nil
@@ -343,7 +327,7 @@ func tryTextUnmarshaler(x target, node ast.Node) (bool, error) {
if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
if err != nil {
return false, fmt.Errorf("tryTextUnmarshaler: %w", err)
return false, newDecodeError(node.Data, "error calling UnmarshalText: %w", err)
}
return true, nil
@@ -358,11 +342,7 @@ func (d *decoder) unmarshalValue(x target, node ast.Node) error {
if v.Kind() == reflect.Ptr {
if !v.Elem().IsValid() {
err := x.set(reflect.New(v.Type().Elem()))
if err != nil {
return fmt.Errorf("unmarshalValue: %w", err)
}
x.set(reflect.New(v.Type().Elem()))
v = x.get()
}
@@ -394,7 +374,7 @@ func (d *decoder) unmarshalValue(x target, node ast.Node) error {
case ast.LocalDate:
return unmarshalLocalDate(x, node)
default:
panic(fmt.Sprintf("unmarshalValue: unhandled unmarshalValue kind %s", node.Kind))
panic(fmt.Sprintf("unhandled node kind %s", node.Kind))
}
}
@@ -406,7 +386,9 @@ func unmarshalLocalDate(x target, node ast.Node) error {
return err
}
return setDate(x, v)
setDate(x, v)
return nil
}
func unmarshalLocalDateTime(x target, node ast.Node) error {
@@ -421,7 +403,9 @@ func unmarshalLocalDateTime(x target, node ast.Node) error {
return newDecodeError(rest, "extra characters at the end of a local date time")
}
return setLocalDateTime(x, v)
setLocalDateTime(x, v)
return nil
}
func unmarshalDateTime(x target, node ast.Node) error {
@@ -432,48 +416,37 @@ func unmarshalDateTime(x target, node ast.Node) error {
return err
}
return setDateTime(x, v)
setDateTime(x, v)
return nil
}
func setLocalDateTime(x target, v LocalDateTime) error {
func setLocalDateTime(x target, v LocalDateTime) {
if x.get().Type() == timeType {
cast := v.In(time.Local)
return setDateTime(x, cast)
setDateTime(x, cast)
return
}
err := x.set(reflect.ValueOf(v))
if err != nil {
return fmt.Errorf("setLocalDateTime: %w", err)
}
return nil
x.set(reflect.ValueOf(v))
}
func setDateTime(x target, v time.Time) error {
err := x.set(reflect.ValueOf(v))
if err != nil {
return fmt.Errorf("setDateTime: %w", err)
}
return nil
func setDateTime(x target, v time.Time) {
x.set(reflect.ValueOf(v))
}
var timeType = reflect.TypeOf(time.Time{})
func setDate(x target, v LocalDate) error {
func setDate(x target, v LocalDate) {
if x.get().Type() == timeType {
cast := v.In(time.Local)
return setDateTime(x, cast)
setDateTime(x, cast)
return
}
err := x.set(reflect.ValueOf(v))
if err != nil {
return fmt.Errorf("setDate: %w", err)
}
return nil
x.set(reflect.ValueOf(v))
}
func unmarshalString(x target, node ast.Node) error {
@@ -514,10 +487,7 @@ func unmarshalFloat(x target, node ast.Node) error {
func (d *decoder) unmarshalInlineTable(x target, node ast.Node) error {
assertNode(ast.InlineTable, node)
err := ensureMapIfInterface(x)
if err != nil {
return fmt.Errorf("unmarshalInlineTable: %w", err)
}
ensureMapIfInterface(x)
it := node.Children()
for it.Next() {
@@ -546,10 +516,7 @@ func (d *decoder) unmarshalArray(x target, node ast.Node) error {
for it.Next() {
n := it.Node()
v, err := elementAt(x, idx)
if err != nil {
return err
}
v := elementAt(x, idx)
if v == nil {
// when we go out of bound for an array just stop processing it to