Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 171a592663 | |||
| 5aaf5ef13b |
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
|
|
||||||
Copyright (c) 2013 - 2021 Thomas Pelletier, Eric Anderton
|
Copyright (c) 2013 - 2022 Thomas Pelletier, Eric Anderton
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -4,17 +4,6 @@ Go library for the [TOML](https://toml.io/en/) format.
|
|||||||
|
|
||||||
This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0).
|
This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0).
|
||||||
|
|
||||||
## Development status
|
|
||||||
|
|
||||||
This is the upcoming major version of go-toml. It is currently in active
|
|
||||||
development. As of release v2.0.0-beta.1, the library has reached feature parity
|
|
||||||
with v1, and fixes a lot known bugs and performance issues along the way.
|
|
||||||
|
|
||||||
If you do not need the advanced document editing features of v1, you are
|
|
||||||
encouraged to try out this version.
|
|
||||||
|
|
||||||
[👉 Roadmap for v2](https://github.com/pelletier/go-toml/discussions/506)
|
|
||||||
|
|
||||||
[🐞 Bug Reports](https://github.com/pelletier/go-toml/issues)
|
[🐞 Bug Reports](https://github.com/pelletier/go-toml/issues)
|
||||||
|
|
||||||
[💬 Anything else](https://github.com/pelletier/go-toml/discussions)
|
[💬 Anything else](https://github.com/pelletier/go-toml/discussions)
|
||||||
|
|||||||
@@ -11,5 +11,6 @@ func TestEntrySize(t *testing.T) {
|
|||||||
// Validate no regression on the size of entry{}. This is a critical bit for
|
// Validate no regression on the size of entry{}. This is a critical bit for
|
||||||
// performance of unmarshaling documents. Should only be increased with care
|
// performance of unmarshaling documents. Should only be increased with care
|
||||||
// and a very good reason.
|
// and a very good reason.
|
||||||
require.LessOrEqual(t, 48, int(unsafe.Sizeof(entry{})))
|
maxExpectedEntrySize := 48
|
||||||
|
require.LessOrEqual(t, int(unsafe.Sizeof(entry{})), maxExpectedEntrySize)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-92
@@ -230,6 +230,15 @@ func (d *decoder) fromParser(root reflect.Value) error {
|
|||||||
return d.p.Error()
|
return d.p.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Rules for the unmarshal code:
|
||||||
|
|
||||||
|
- The stack is used to keep track of which values need to be set where.
|
||||||
|
- handle* functions <=> switch on a given ast.Kind.
|
||||||
|
- unmarshalX* functions need to unmarshal a node of kind X.
|
||||||
|
- An "object" is either a struct or a map.
|
||||||
|
*/
|
||||||
|
|
||||||
func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
|
func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
|
||||||
var x reflect.Value
|
var x reflect.Value
|
||||||
var err error
|
var err error
|
||||||
@@ -391,84 +400,6 @@ func (d *decoder) handleArrayTableCollection(key ast.Iterator, v reflect.Value)
|
|||||||
return d.handleArrayTable(key, v)
|
return d.handleArrayTable(key, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *decoder) handleKeyValuePartMapStringInterface(key ast.Iterator, value *ast.Node, m map[string]interface{}) (reflect.Value, error) {
|
|
||||||
k := string(key.Node().Data)
|
|
||||||
|
|
||||||
newMap := false
|
|
||||||
if m == nil {
|
|
||||||
newMap = true
|
|
||||||
m = make(map[string]interface{}, 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
set := false
|
|
||||||
v, ok := m[k]
|
|
||||||
if !ok || key.IsLast() {
|
|
||||||
set = true
|
|
||||||
v = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
mv := reflect.ValueOf(&v).Elem()
|
|
||||||
|
|
||||||
x, err := d.handleKeyValueInner(key, value, mv)
|
|
||||||
if err != nil {
|
|
||||||
return reflect.Value{}, err
|
|
||||||
}
|
|
||||||
if x.IsValid() {
|
|
||||||
mv = x
|
|
||||||
set = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if set {
|
|
||||||
m[k] = mv.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
if newMap {
|
|
||||||
return reflect.ValueOf(m), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return reflect.Value{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) handleKeyPartMapStringInterface(key ast.Iterator, m map[string]interface{}, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
|
|
||||||
newMap := false
|
|
||||||
|
|
||||||
k := string(key.Node().Data)
|
|
||||||
if m == nil {
|
|
||||||
newMap = true
|
|
||||||
m = make(map[string]interface{}, 8)
|
|
||||||
}
|
|
||||||
|
|
||||||
v, ok := m[k]
|
|
||||||
set := false
|
|
||||||
|
|
||||||
if !ok || v == nil {
|
|
||||||
set = true
|
|
||||||
v = makeFn().Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
mv := reflect.ValueOf(v)
|
|
||||||
|
|
||||||
x, err := nextFn(key, mv)
|
|
||||||
if err != nil {
|
|
||||||
return reflect.Value{}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if x.IsValid() {
|
|
||||||
mv = x
|
|
||||||
set = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if set {
|
|
||||||
m[k] = mv.Interface()
|
|
||||||
}
|
|
||||||
|
|
||||||
if newMap {
|
|
||||||
return reflect.ValueOf(m), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return reflect.Value{}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
|
func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
|
||||||
var rv reflect.Value
|
var rv reflect.Value
|
||||||
|
|
||||||
@@ -485,11 +416,6 @@ func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handle
|
|||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
vt := v.Type()
|
vt := v.Type()
|
||||||
|
|
||||||
if vt == mapStringInterfaceType {
|
|
||||||
m := v.Interface().(map[string]interface{})
|
|
||||||
return d.handleKeyPartMapStringInterface(key, m, nextFn, makeFn)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create the key for the map element. Convert to key type.
|
// Create the key for the map element. Convert to key type.
|
||||||
mk := reflect.ValueOf(string(key.Node().Data)).Convert(vt.Key())
|
mk := reflect.ValueOf(string(key.Node().Data)).Convert(vt.Key())
|
||||||
|
|
||||||
@@ -1073,11 +999,6 @@ func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflec
|
|||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
vt := v.Type()
|
vt := v.Type()
|
||||||
|
|
||||||
if vt == mapStringInterfaceType {
|
|
||||||
m := v.Interface().(map[string]interface{})
|
|
||||||
return d.handleKeyValuePartMapStringInterface(key, value, m)
|
|
||||||
}
|
|
||||||
|
|
||||||
mk := reflect.ValueOf(string(key.Node().Data))
|
mk := reflect.ValueOf(string(key.Node().Data))
|
||||||
mkt := stringType
|
mkt := stringType
|
||||||
|
|
||||||
@@ -1101,10 +1022,12 @@ func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflec
|
|||||||
if !mv.IsValid() {
|
if !mv.IsValid() {
|
||||||
set = true
|
set = true
|
||||||
mv = reflect.New(v.Type().Elem()).Elem()
|
mv = reflect.New(v.Type().Elem()).Elem()
|
||||||
} else if key.IsLast() {
|
} else {
|
||||||
var x interface{}
|
if key.IsLast() {
|
||||||
mv = reflect.ValueOf(&x).Elem()
|
var x interface{}
|
||||||
set = true
|
mv = reflect.ValueOf(&x).Elem()
|
||||||
|
set = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nv, err := d.handleKeyValueInner(key, value, mv)
|
nv, err := d.handleKeyValueInner(key, value, mv)
|
||||||
|
|||||||
Reference in New Issue
Block a user