@@ -16,7 +16,7 @@ This library supports TOML version
|
|||||||
Go-toml provides the following features for using data parsed from TOML documents:
|
Go-toml provides the following features for using data parsed from TOML documents:
|
||||||
|
|
||||||
* Load TOML documents from files and string data
|
* Load TOML documents from files and string data
|
||||||
* Easily navigate TOML structure using TomlTree
|
* Easily navigate TOML structure using Tree
|
||||||
* Line & column position data for all parsed elements
|
* Line & column position data for all parsed elements
|
||||||
* [Query support similar to JSON-Path](query/)
|
* [Query support similar to JSON-Path](query/)
|
||||||
* Syntax errors contain line and column numbers
|
* Syntax errors contain line and column numbers
|
||||||
@@ -61,7 +61,7 @@ if err != nil {
|
|||||||
password := config.Get("postgres.password").(string)
|
password := config.Get("postgres.password").(string)
|
||||||
|
|
||||||
// or using an intermediate object
|
// or using an intermediate object
|
||||||
configTree := config.Get("postgres").(*toml.TomlTree)
|
configTree := config.Get("postgres").(*toml.Tree)
|
||||||
user = configTree.Get("user").(string)
|
user = configTree.Get("user").(string)
|
||||||
password = configTree.Get("password").(string)
|
password = configTree.Get("password").(string)
|
||||||
fmt.Println("User is ", user, ". Password is ", password)
|
fmt.Println("User is ", user, ". Password is ", password)
|
||||||
|
|||||||
+3
-3
@@ -41,16 +41,16 @@ func translate(tomlData interface{}) interface{} {
|
|||||||
typed[k] = translate(v)
|
typed[k] = translate(v)
|
||||||
}
|
}
|
||||||
return typed
|
return typed
|
||||||
case *toml.TomlTree:
|
case *toml.Tree:
|
||||||
return translate(*orig)
|
return translate(*orig)
|
||||||
case toml.TomlTree:
|
case toml.Tree:
|
||||||
keys := orig.Keys()
|
keys := orig.Keys()
|
||||||
typed := make(map[string]interface{}, len(keys))
|
typed := make(map[string]interface{}, len(keys))
|
||||||
for _, k := range keys {
|
for _, k := range keys {
|
||||||
typed[k] = translate(orig.GetPath([]string{k}))
|
typed[k] = translate(orig.GetPath([]string{k}))
|
||||||
}
|
}
|
||||||
return typed
|
return typed
|
||||||
case []*toml.TomlTree:
|
case []*toml.Tree:
|
||||||
typed := make([]map[string]interface{}, len(orig))
|
typed := make([]map[string]interface{}, len(orig))
|
||||||
for i, v := range orig {
|
for i, v := range orig {
|
||||||
typed[i] = translate(v).(map[string]interface{})
|
typed[i] = translate(v).(map[string]interface{})
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ func reader(r io.Reader) (string, error) {
|
|||||||
return mapToJSON(tree)
|
return mapToJSON(tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapToJSON(tree *toml.TomlTree) (string, error) {
|
func mapToJSON(tree *toml.Tree) (string, error) {
|
||||||
treeMap := tree.ToMap()
|
treeMap := tree.ToMap()
|
||||||
bytes, err := json.MarshalIndent(treeMap, "", " ")
|
bytes, err := json.MarshalIndent(treeMap, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -13,14 +13,14 @@
|
|||||||
// // load TOML data stored in a string
|
// // load TOML data stored in a string
|
||||||
// tree, err := toml.Load(stringContainingTomlData)
|
// tree, err := toml.Load(stringContainingTomlData)
|
||||||
//
|
//
|
||||||
// Either way, the result is a TomlTree object that can be used to navigate the
|
// Either way, the result is a Tree object that can be used to navigate the
|
||||||
// structure and data within the original document.
|
// structure and data within the original document.
|
||||||
//
|
//
|
||||||
//
|
//
|
||||||
// Getting data from the TomlTree
|
// Getting data from the Tree
|
||||||
//
|
//
|
||||||
// After parsing TOML data with Load() or LoadFile(), use the Has() and Get()
|
// After parsing TOML data with Load() or LoadFile(), use the Has() and Get()
|
||||||
// methods on the returned TomlTree, to find your way through the document data.
|
// methods on the returned Tree, to find your way through the document data.
|
||||||
//
|
//
|
||||||
// if tree.Has("foo") {
|
// if tree.Has("foo") {
|
||||||
// fmt.Println("foo is:", tree.Get("foo"))
|
// fmt.Println("foo is:", tree.Get("foo"))
|
||||||
@@ -50,11 +50,11 @@
|
|||||||
// tree.GetPath([]string{"foo","bar","baz"})
|
// tree.GetPath([]string{"foo","bar","baz"})
|
||||||
//
|
//
|
||||||
// Note that this is distinct from the heavyweight query syntax supported by
|
// Note that this is distinct from the heavyweight query syntax supported by
|
||||||
// TomlTree.Query() and the Query() struct (see below).
|
// Tree.Query() and the Query() struct (see below).
|
||||||
//
|
//
|
||||||
// Position Support
|
// Position Support
|
||||||
//
|
//
|
||||||
// Each element within the TomlTree is stored with position metadata, which is
|
// Each element within the Tree is stored with position metadata, which is
|
||||||
// invaluable for providing semantic feedback to a user. This helps in
|
// invaluable for providing semantic feedback to a user. This helps in
|
||||||
// situations where the TOML file parses correctly, but contains data that is
|
// situations where the TOML file parses correctly, but contains data that is
|
||||||
// not correct for the application. In such cases, an error message can be
|
// not correct for the application. In such cases, an error message can be
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@ func Example_comprehensiveExample() {
|
|||||||
password := config.Get("postgres.password").(string)
|
password := config.Get("postgres.password").(string)
|
||||||
|
|
||||||
// or using an intermediate object
|
// or using an intermediate object
|
||||||
configTree := config.Get("postgres").(*TomlTree)
|
configTree := config.Get("postgres").(*Tree)
|
||||||
user = configTree.Get("user").(string)
|
user = configTree.Get("user").(string)
|
||||||
password = configTree.Get("password").(string)
|
password = configTree.Get("password").(string)
|
||||||
fmt.Println("User is ", user, ". Password is ", password)
|
fmt.Println("User is ", user, ". Password is ", password)
|
||||||
|
|||||||
+18
-18
@@ -10,14 +10,14 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
TomlTree structural types and corresponding marshal types
|
Tree structural types and corresponding marshal types
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
*TomlTree (*)struct, (*)map[string]interface{}
|
*Tree (*)struct, (*)map[string]interface{}
|
||||||
[]*TomlTree (*)[](*)struct, (*)[](*)map[string]interface{}
|
[]*Tree (*)[](*)struct, (*)[](*)map[string]interface{}
|
||||||
[]interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
|
[]interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{})
|
||||||
interface{} (*)primitive
|
interface{} (*)primitive
|
||||||
|
|
||||||
TomlTree primitive types and corresponding marshal types
|
Tree primitive types and corresponding marshal types
|
||||||
-----------------------------------------------------------
|
-----------------------------------------------------------
|
||||||
uint64 uint, uint8-uint64, pointers to same
|
uint64 uint, uint8-uint64, pointers to same
|
||||||
int64 int, int8-uint64, pointers to same
|
int64 int, int8-uint64, pointers to same
|
||||||
@@ -36,7 +36,7 @@ type tomlOpts struct {
|
|||||||
var timeType = reflect.TypeOf(time.Time{})
|
var timeType = reflect.TypeOf(time.Time{})
|
||||||
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
|
var marshalerType = reflect.TypeOf(new(Marshaler)).Elem()
|
||||||
|
|
||||||
// Check if the given marshall type maps to a TomlTree primitive
|
// Check if the given marshall type maps to a Tree primitive
|
||||||
func isPrimitive(mtype reflect.Type) bool {
|
func isPrimitive(mtype reflect.Type) bool {
|
||||||
switch mtype.Kind() {
|
switch mtype.Kind() {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
@@ -58,7 +58,7 @@ func isPrimitive(mtype reflect.Type) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the given marshall type maps to a TomlTree slice
|
// Check if the given marshall type maps to a Tree slice
|
||||||
func isTreeSlice(mtype reflect.Type) bool {
|
func isTreeSlice(mtype reflect.Type) bool {
|
||||||
switch mtype.Kind() {
|
switch mtype.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
@@ -68,7 +68,7 @@ func isTreeSlice(mtype reflect.Type) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the given marshall type maps to a non-TomlTree slice
|
// Check if the given marshall type maps to a non-Tree slice
|
||||||
func isOtherSlice(mtype reflect.Type) bool {
|
func isOtherSlice(mtype reflect.Type) bool {
|
||||||
switch mtype.Kind() {
|
switch mtype.Kind() {
|
||||||
case reflect.Ptr:
|
case reflect.Ptr:
|
||||||
@@ -80,7 +80,7 @@ func isOtherSlice(mtype reflect.Type) bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the given marshall type maps to a TomlTree
|
// Check if the given marshall type maps to a Tree
|
||||||
func isTree(mtype reflect.Type) bool {
|
func isTree(mtype reflect.Type) bool {
|
||||||
switch mtype.Kind() {
|
switch mtype.Kind() {
|
||||||
case reflect.Map:
|
case reflect.Map:
|
||||||
@@ -134,11 +134,11 @@ func Marshal(v interface{}) ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert given marshal struct or map value to toml tree
|
// Convert given marshal struct or map value to toml tree
|
||||||
func valueToTree(mtype reflect.Type, mval reflect.Value) (*TomlTree, error) {
|
func valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) {
|
||||||
if mtype.Kind() == reflect.Ptr {
|
if mtype.Kind() == reflect.Ptr {
|
||||||
return valueToTree(mtype.Elem(), mval.Elem())
|
return valueToTree(mtype.Elem(), mval.Elem())
|
||||||
}
|
}
|
||||||
tval := newTomlTree()
|
tval := newTree()
|
||||||
switch mtype.Kind() {
|
switch mtype.Kind() {
|
||||||
case reflect.Struct:
|
case reflect.Struct:
|
||||||
for i := 0; i < mtype.NumField(); i++ {
|
for i := 0; i < mtype.NumField(); i++ {
|
||||||
@@ -166,8 +166,8 @@ func valueToTree(mtype reflect.Type, mval reflect.Value) (*TomlTree, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert given marshal slice to slice of Toml trees
|
// Convert given marshal slice to slice of Toml trees
|
||||||
func valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*TomlTree, error) {
|
func valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) {
|
||||||
tval := make([]*TomlTree, mval.Len(), mval.Len())
|
tval := make([]*Tree, mval.Len(), mval.Len())
|
||||||
for i := 0; i < mval.Len(); i++ {
|
for i := 0; i < mval.Len(); i++ {
|
||||||
val, err := valueToTree(mtype.Elem(), mval.Index(i))
|
val, err := valueToTree(mtype.Elem(), mval.Index(i))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -225,10 +225,10 @@ func valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmarshal attempts to unmarshal the TomlTree into a Go struct pointed by v.
|
// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v.
|
||||||
// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
|
// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for
|
||||||
// sub-structs, and only definite types can be unmarshaled.
|
// sub-structs, and only definite types can be unmarshaled.
|
||||||
func (t *TomlTree) Unmarshal(v interface{}) error {
|
func (t *Tree) Unmarshal(v interface{}) error {
|
||||||
mtype := reflect.TypeOf(v)
|
mtype := reflect.TypeOf(v)
|
||||||
if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
|
if mtype.Kind() != reflect.Ptr || mtype.Elem().Kind() != reflect.Struct {
|
||||||
return errors.New("Only a pointer to struct can be unmarshaled from TOML")
|
return errors.New("Only a pointer to struct can be unmarshaled from TOML")
|
||||||
@@ -256,7 +256,7 @@ func Unmarshal(data []byte, v interface{}) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert toml tree to marshal struct or map, using marshal type
|
// Convert toml tree to marshal struct or map, using marshal type
|
||||||
func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) {
|
func valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) {
|
||||||
if mtype.Kind() == reflect.Ptr {
|
if mtype.Kind() == reflect.Ptr {
|
||||||
return unwrapPointer(mtype, tval)
|
return unwrapPointer(mtype, tval)
|
||||||
}
|
}
|
||||||
@@ -295,7 +295,7 @@ func valueFromTree(mtype reflect.Type, tval *TomlTree) (reflect.Value, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert toml value to marshal struct/map slice, using marshal type
|
// Convert toml value to marshal struct/map slice, using marshal type
|
||||||
func valueFromTreeSlice(mtype reflect.Type, tval []*TomlTree) (reflect.Value, error) {
|
func valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) {
|
||||||
mval := reflect.MakeSlice(mtype, len(tval), len(tval))
|
mval := reflect.MakeSlice(mtype, len(tval), len(tval))
|
||||||
for i := 0; i < len(tval); i++ {
|
for i := 0; i < len(tval); i++ {
|
||||||
val, err := valueFromTree(mtype.Elem(), tval[i])
|
val, err := valueFromTree(mtype.Elem(), tval[i])
|
||||||
@@ -327,9 +327,9 @@ func valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error)
|
|||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
case isTree(mtype):
|
case isTree(mtype):
|
||||||
return valueFromTree(mtype, tval.(*TomlTree))
|
return valueFromTree(mtype, tval.(*Tree))
|
||||||
case isTreeSlice(mtype):
|
case isTreeSlice(mtype):
|
||||||
return valueFromTreeSlice(mtype, tval.([]*TomlTree))
|
return valueFromTreeSlice(mtype, tval.([]*Tree))
|
||||||
case isOtherSlice(mtype):
|
case isOtherSlice(mtype):
|
||||||
return valueFromOtherSlice(mtype, tval.([]interface{}))
|
return valueFromOtherSlice(mtype, tval.([]interface{}))
|
||||||
default:
|
default:
|
||||||
|
|||||||
+1
-1
@@ -181,7 +181,7 @@ func TestDocPartialUnmarshal(t *testing.T) {
|
|||||||
result := testDocSubs{}
|
result := testDocSubs{}
|
||||||
|
|
||||||
tree, _ := LoadFile("marshal_test.toml")
|
tree, _ := LoadFile("marshal_test.toml")
|
||||||
subTree := tree.Get("subdoc").(*TomlTree)
|
subTree := tree.Get("subdoc").(*Tree)
|
||||||
err := subTree.Unmarshal(&result)
|
err := subTree.Unmarshal(&result)
|
||||||
expected := docData.Subdocs
|
expected := docData.Subdocs
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
type tomlParser struct {
|
type tomlParser struct {
|
||||||
flow chan token
|
flow chan token
|
||||||
tree *TomlTree
|
tree *Tree
|
||||||
tokensBuffer []token
|
tokensBuffer []token
|
||||||
currentTable []string
|
currentTable []string
|
||||||
seenTableKeys []string
|
seenTableKeys []string
|
||||||
@@ -106,18 +106,18 @@ func (p *tomlParser) parseGroupArray() tomlParserStateFn {
|
|||||||
}
|
}
|
||||||
p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
|
p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
|
||||||
destTree := p.tree.GetPath(keys)
|
destTree := p.tree.GetPath(keys)
|
||||||
var array []*TomlTree
|
var array []*Tree
|
||||||
if destTree == nil {
|
if destTree == nil {
|
||||||
array = make([]*TomlTree, 0)
|
array = make([]*Tree, 0)
|
||||||
} else if target, ok := destTree.([]*TomlTree); ok && target != nil {
|
} else if target, ok := destTree.([]*Tree); ok && target != nil {
|
||||||
array = destTree.([]*TomlTree)
|
array = destTree.([]*Tree)
|
||||||
} else {
|
} else {
|
||||||
p.raiseError(key, "key %s is already assigned and not of type table array", key)
|
p.raiseError(key, "key %s is already assigned and not of type table array", key)
|
||||||
}
|
}
|
||||||
p.currentTable = keys
|
p.currentTable = keys
|
||||||
|
|
||||||
// add a new tree to the end of the table array
|
// add a new tree to the end of the table array
|
||||||
newTree := newTomlTree()
|
newTree := newTree()
|
||||||
newTree.position = startToken.Position
|
newTree.position = startToken.Position
|
||||||
array = append(array, newTree)
|
array = append(array, newTree)
|
||||||
p.tree.SetPath(p.currentTable, array)
|
p.tree.SetPath(p.currentTable, array)
|
||||||
@@ -183,11 +183,11 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// find the table to assign, looking out for arrays of tables
|
// find the table to assign, looking out for arrays of tables
|
||||||
var targetNode *TomlTree
|
var targetNode *Tree
|
||||||
switch node := p.tree.GetPath(tableKey).(type) {
|
switch node := p.tree.GetPath(tableKey).(type) {
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
targetNode = node[len(node)-1]
|
targetNode = node[len(node)-1]
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
targetNode = node
|
targetNode = node
|
||||||
default:
|
default:
|
||||||
p.raiseError(key, "Unknown table type for path: %s",
|
p.raiseError(key, "Unknown table type for path: %s",
|
||||||
@@ -212,7 +212,7 @@ func (p *tomlParser) parseAssign() tomlParserStateFn {
|
|||||||
var toInsert interface{}
|
var toInsert interface{}
|
||||||
|
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case *TomlTree, []*TomlTree:
|
case *Tree, []*Tree:
|
||||||
toInsert = value
|
toInsert = value
|
||||||
default:
|
default:
|
||||||
toInsert = &tomlValue{value, key.Position}
|
toInsert = &tomlValue{value, key.Position}
|
||||||
@@ -289,8 +289,8 @@ func tokenIsComma(t *token) bool {
|
|||||||
return t != nil && t.typ == tokenComma
|
return t != nil && t.typ == tokenComma
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *tomlParser) parseInlineTable() *TomlTree {
|
func (p *tomlParser) parseInlineTable() *Tree {
|
||||||
tree := newTomlTree()
|
tree := newTree()
|
||||||
var previous *token
|
var previous *token
|
||||||
Loop:
|
Loop:
|
||||||
for {
|
for {
|
||||||
@@ -360,22 +360,22 @@ func (p *tomlParser) parseArray() interface{} {
|
|||||||
p.getToken()
|
p.getToken()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// An array of TomlTrees is actually an array of inline
|
// An array of Trees is actually an array of inline
|
||||||
// tables, which is a shorthand for a table array. If the
|
// tables, which is a shorthand for a table array. If the
|
||||||
// array was not converted from []interface{} to []*TomlTree,
|
// array was not converted from []interface{} to []*Tree,
|
||||||
// the two notations would not be equivalent.
|
// the two notations would not be equivalent.
|
||||||
if arrayType == reflect.TypeOf(newTomlTree()) {
|
if arrayType == reflect.TypeOf(newTree()) {
|
||||||
tomlArray := make([]*TomlTree, len(array))
|
tomlArray := make([]*Tree, len(array))
|
||||||
for i, v := range array {
|
for i, v := range array {
|
||||||
tomlArray[i] = v.(*TomlTree)
|
tomlArray[i] = v.(*Tree)
|
||||||
}
|
}
|
||||||
return tomlArray
|
return tomlArray
|
||||||
}
|
}
|
||||||
return array
|
return array
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseToml(flow chan token) *TomlTree {
|
func parseToml(flow chan token) *Tree {
|
||||||
result := newTomlTree()
|
result := newTree()
|
||||||
result.position = Position{1, 1}
|
result.position = Position{1, 1}
|
||||||
parser := &tomlParser{
|
parser := &tomlParser{
|
||||||
flow: flow,
|
flow: flow,
|
||||||
|
|||||||
+5
-5
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertSubTree(t *testing.T, path []string, tree *TomlTree, err error, ref map[string]interface{}) {
|
func assertSubTree(t *testing.T, path []string, tree *Tree, err error, ref map[string]interface{}) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error("Non-nil error:", err.Error())
|
t.Error("Non-nil error:", err.Error())
|
||||||
return
|
return
|
||||||
@@ -20,12 +20,12 @@ func assertSubTree(t *testing.T, path []string, tree *TomlTree, err error, ref m
|
|||||||
// NOTE: directly access key instead of resolve by path
|
// NOTE: directly access key instead of resolve by path
|
||||||
// NOTE: see TestSpecialKV
|
// NOTE: see TestSpecialKV
|
||||||
switch node := tree.GetPath([]string{k}).(type) {
|
switch node := tree.GetPath([]string{k}).(type) {
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
t.Log("\tcomparing key", nextPath, "by array iteration")
|
t.Log("\tcomparing key", nextPath, "by array iteration")
|
||||||
for idx, item := range node {
|
for idx, item := range node {
|
||||||
assertSubTree(t, nextPath, item, err, v.([]map[string]interface{})[idx])
|
assertSubTree(t, nextPath, item, err, v.([]map[string]interface{})[idx])
|
||||||
}
|
}
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
t.Log("\tcomparing key", nextPath, "by subtree assestion")
|
t.Log("\tcomparing key", nextPath, "by subtree assestion")
|
||||||
assertSubTree(t, nextPath, node, err, v.(map[string]interface{}))
|
assertSubTree(t, nextPath, node, err, v.(map[string]interface{}))
|
||||||
default:
|
default:
|
||||||
@@ -37,14 +37,14 @@ func assertSubTree(t *testing.T, path []string, tree *TomlTree, err error, ref m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertTree(t *testing.T, tree *TomlTree, err error, ref map[string]interface{}) {
|
func assertTree(t *testing.T, tree *Tree, err error, ref map[string]interface{}) {
|
||||||
t.Log("Asserting tree:\n", spew.Sdump(tree))
|
t.Log("Asserting tree:\n", spew.Sdump(tree))
|
||||||
assertSubTree(t, []string{}, tree, err, ref)
|
assertSubTree(t, []string{}, tree, err, ref)
|
||||||
t.Log("Finished tree assertion.")
|
t.Log("Finished tree assertion.")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateSubTree(t *testing.T) {
|
func TestCreateSubTree(t *testing.T) {
|
||||||
tree := newTomlTree()
|
tree := newTree()
|
||||||
tree.createSubTree([]string{"a", "b", "c"}, Position{})
|
tree.createSubTree([]string{"a", "b", "c"}, Position{})
|
||||||
tree.Set("a.b.c", 42)
|
tree.Set("a.b.c", 42)
|
||||||
if tree.Get("a.b.c") != 42 {
|
if tree.Get("a.b.c") != 42 {
|
||||||
|
|||||||
+3
-3
@@ -112,7 +112,7 @@
|
|||||||
// There are several filters provided with the library:
|
// There are several filters provided with the library:
|
||||||
//
|
//
|
||||||
// tree
|
// tree
|
||||||
// Allows nodes of type TomlTree.
|
// Allows nodes of type Tree.
|
||||||
// int
|
// int
|
||||||
// Allows nodes of type int64.
|
// Allows nodes of type int64.
|
||||||
// float
|
// float
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
//
|
//
|
||||||
// Compiled Queries
|
// Compiled Queries
|
||||||
//
|
//
|
||||||
// Queries may be executed directly on a TomlTree object, or compiled ahead
|
// Queries may be executed directly on a Tree object, or compiled ahead
|
||||||
// of time and executed discretely. The former is more convienent, but has the
|
// of time and executed discretely. The former is more convienent, but has the
|
||||||
// penalty of having to recompile the query expression each time.
|
// penalty of having to recompile the query expression each time.
|
||||||
//
|
//
|
||||||
@@ -163,7 +163,7 @@
|
|||||||
//
|
//
|
||||||
// // define the filter, and assign it to the query
|
// // define the filter, and assign it to the query
|
||||||
// query.SetFilter("bazOnly", func(node interface{}) bool{
|
// query.SetFilter("bazOnly", func(node interface{}) bool{
|
||||||
// if tree, ok := node.(*TomlTree); ok {
|
// if tree, ok := node.(*Tree); ok {
|
||||||
// return tree.Has("baz")
|
// return tree.Has("baz")
|
||||||
// }
|
// }
|
||||||
// return false // reject all other node types
|
// return false // reject all other node types
|
||||||
|
|||||||
+12
-12
@@ -42,7 +42,7 @@ func newMatchKeyFn(name string) *matchKeyFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
|
func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
|
||||||
if array, ok := node.([]*toml.TomlTree); ok {
|
if array, ok := node.([]*toml.Tree); ok {
|
||||||
for _, tree := range array {
|
for _, tree := range array {
|
||||||
item := tree.Get(f.Name)
|
item := tree.Get(f.Name)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
@@ -50,7 +50,7 @@ func (f *matchKeyFn) call(node interface{}, ctx *queryContext) {
|
|||||||
f.next.call(item, ctx)
|
f.next.call(item, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if tree, ok := node.(*toml.TomlTree); ok {
|
} else if tree, ok := node.(*toml.Tree); ok {
|
||||||
item := tree.Get(f.Name)
|
item := tree.Get(f.Name)
|
||||||
if item != nil {
|
if item != nil {
|
||||||
ctx.lastPosition = tree.GetPosition(f.Name)
|
ctx.lastPosition = tree.GetPosition(f.Name)
|
||||||
@@ -72,7 +72,7 @@ func newMatchIndexFn(idx int) *matchIndexFn {
|
|||||||
func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
|
func (f *matchIndexFn) call(node interface{}, ctx *queryContext) {
|
||||||
if arr, ok := node.([]interface{}); ok {
|
if arr, ok := node.([]interface{}); ok {
|
||||||
if f.Idx < len(arr) && f.Idx >= 0 {
|
if f.Idx < len(arr) && f.Idx >= 0 {
|
||||||
if treesArray, ok := node.([]*toml.TomlTree); ok {
|
if treesArray, ok := node.([]*toml.Tree); ok {
|
||||||
if len(treesArray) > 0 {
|
if len(treesArray) > 0 {
|
||||||
ctx.lastPosition = treesArray[0].Position()
|
ctx.lastPosition = treesArray[0].Position()
|
||||||
}
|
}
|
||||||
@@ -107,7 +107,7 @@ func (f *matchSliceFn) call(node interface{}, ctx *queryContext) {
|
|||||||
}
|
}
|
||||||
// loop and gather
|
// loop and gather
|
||||||
for idx := realStart; idx < realEnd; idx += f.Step {
|
for idx := realStart; idx < realEnd; idx += f.Step {
|
||||||
if treesArray, ok := node.([]*toml.TomlTree); ok {
|
if treesArray, ok := node.([]*toml.Tree); ok {
|
||||||
if len(treesArray) > 0 {
|
if len(treesArray) > 0 {
|
||||||
ctx.lastPosition = treesArray[0].Position()
|
ctx.lastPosition = treesArray[0].Position()
|
||||||
}
|
}
|
||||||
@@ -127,7 +127,7 @@ func newMatchAnyFn() *matchAnyFn {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
|
func (f *matchAnyFn) call(node interface{}, ctx *queryContext) {
|
||||||
if tree, ok := node.(*toml.TomlTree); ok {
|
if tree, ok := node.(*toml.Tree); ok {
|
||||||
for _, k := range tree.Keys() {
|
for _, k := range tree.Keys() {
|
||||||
v := tree.Get(k)
|
v := tree.Get(k)
|
||||||
ctx.lastPosition = tree.GetPosition(k)
|
ctx.lastPosition = tree.GetPosition(k)
|
||||||
@@ -164,17 +164,17 @@ func newMatchRecursiveFn() *matchRecursiveFn {
|
|||||||
|
|
||||||
func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
|
func (f *matchRecursiveFn) call(node interface{}, ctx *queryContext) {
|
||||||
originalPosition := ctx.lastPosition
|
originalPosition := ctx.lastPosition
|
||||||
if tree, ok := node.(*toml.TomlTree); ok {
|
if tree, ok := node.(*toml.Tree); ok {
|
||||||
var visit func(tree *toml.TomlTree)
|
var visit func(tree *toml.Tree)
|
||||||
visit = func(tree *toml.TomlTree) {
|
visit = func(tree *toml.Tree) {
|
||||||
for _, k := range tree.Keys() {
|
for _, k := range tree.Keys() {
|
||||||
v := tree.Get(k)
|
v := tree.Get(k)
|
||||||
ctx.lastPosition = tree.GetPosition(k)
|
ctx.lastPosition = tree.GetPosition(k)
|
||||||
f.next.call(v, ctx)
|
f.next.call(v, ctx)
|
||||||
switch node := v.(type) {
|
switch node := v.(type) {
|
||||||
case *toml.TomlTree:
|
case *toml.Tree:
|
||||||
visit(node)
|
visit(node)
|
||||||
case []*toml.TomlTree:
|
case []*toml.Tree:
|
||||||
for _, subtree := range node {
|
for _, subtree := range node {
|
||||||
visit(subtree)
|
visit(subtree)
|
||||||
}
|
}
|
||||||
@@ -205,7 +205,7 @@ func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
|
|||||||
f.Pos.String(), f.Name))
|
f.Pos.String(), f.Name))
|
||||||
}
|
}
|
||||||
switch castNode := node.(type) {
|
switch castNode := node.(type) {
|
||||||
case *toml.TomlTree:
|
case *toml.Tree:
|
||||||
for _, k := range castNode.Keys() {
|
for _, k := range castNode.Keys() {
|
||||||
v := castNode.Get(k)
|
v := castNode.Get(k)
|
||||||
if fn(v) {
|
if fn(v) {
|
||||||
@@ -213,7 +213,7 @@ func (f *matchFilterFn) call(node interface{}, ctx *queryContext) {
|
|||||||
f.next.call(v, ctx)
|
f.next.call(v, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case []*toml.TomlTree:
|
case []*toml.Tree:
|
||||||
for _, v := range castNode {
|
for _, v := range castNode {
|
||||||
if fn(v) {
|
if fn(v) {
|
||||||
if len(castNode) > 0 {
|
if len(castNode) > 0 {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ func valueString(root interface{}) string {
|
|||||||
}
|
}
|
||||||
sort.Strings(items)
|
sort.Strings(items)
|
||||||
result = "[" + strings.Join(items, ", ") + "]"
|
result = "[" + strings.Join(items, ", ") + "]"
|
||||||
case *toml.TomlTree:
|
case *toml.Tree:
|
||||||
// workaround for unreliable map key ordering
|
// workaround for unreliable map key ordering
|
||||||
items := []string{}
|
items := []string{}
|
||||||
for _, k := range node.Keys() {
|
for _, k := range node.Keys() {
|
||||||
|
|||||||
+6
-6
@@ -53,7 +53,7 @@ type queryContext struct {
|
|||||||
type pathFn interface {
|
type pathFn interface {
|
||||||
setNext(next pathFn)
|
setNext(next pathFn)
|
||||||
// it is the caller's responsibility to set the ctx.lastPosition before invoking call()
|
// it is the caller's responsibility to set the ctx.lastPosition before invoking call()
|
||||||
// node can be one of: *toml.TomlTree, []*toml.TomlTree, or a scalar
|
// node can be one of: *toml.Tree, []*toml.Tree, or a scalar
|
||||||
call(node interface{}, ctx *queryContext)
|
call(node interface{}, ctx *queryContext)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,13 +84,13 @@ func (q *Query) appendPath(next pathFn) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Compile compiles a TOML path expression. The returned Query can be used
|
// Compile compiles a TOML path expression. The returned Query can be used
|
||||||
// to match elements within a TomlTree and its descendants. See Execute.
|
// to match elements within a Tree and its descendants. See Execute.
|
||||||
func Compile(path string) (*Query, error) {
|
func Compile(path string) (*Query, error) {
|
||||||
return parseQuery(lexQuery(path))
|
return parseQuery(lexQuery(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute executes a query against a TomlTree, and returns the result of the query.
|
// Execute executes a query against a Tree, and returns the result of the query.
|
||||||
func (q *Query) Execute(tree *toml.TomlTree) *Result {
|
func (q *Query) Execute(tree *toml.Tree) *Result {
|
||||||
result := &Result{
|
result := &Result{
|
||||||
items: []interface{}{},
|
items: []interface{}{},
|
||||||
positions: []toml.Position{},
|
positions: []toml.Position{},
|
||||||
@@ -109,7 +109,7 @@ func (q *Query) Execute(tree *toml.TomlTree) *Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CompileAndExecute is a shorthand for Compile(path) followed by Execute(tree).
|
// CompileAndExecute is a shorthand for Compile(path) followed by Execute(tree).
|
||||||
func CompileAndExecute(path string, tree *toml.TomlTree) (*Result, error) {
|
func CompileAndExecute(path string, tree *toml.Tree) (*Result, error) {
|
||||||
query, err := Compile(path)
|
query, err := Compile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -132,7 +132,7 @@ func (q *Query) SetFilter(name string, fn NodeFilterFn) {
|
|||||||
|
|
||||||
var defaultFilterFunctions = map[string]NodeFilterFn{
|
var defaultFilterFunctions = map[string]NodeFilterFn{
|
||||||
"tree": func(node interface{}) bool {
|
"tree": func(node interface{}) bool {
|
||||||
_, ok := node.(*toml.TomlTree)
|
_, ok := node.(*toml.Tree)
|
||||||
return ok
|
return ok
|
||||||
},
|
},
|
||||||
"int": func(node interface{}) bool {
|
"int": func(node interface{}) bool {
|
||||||
|
|||||||
+4
-4
@@ -99,13 +99,13 @@ func ExampleNodeFilterFn_filterExample() {
|
|||||||
|
|
||||||
// define the filter, and assign it to the query
|
// define the filter, and assign it to the query
|
||||||
query.SetFilter("bazOnly", func(node interface{}) bool {
|
query.SetFilter("bazOnly", func(node interface{}) bool {
|
||||||
if tree, ok := node.(*toml.TomlTree); ok {
|
if tree, ok := node.(*toml.Tree); ok {
|
||||||
return tree.Has("baz")
|
return tree.Has("baz")
|
||||||
}
|
}
|
||||||
return false // reject all other node types
|
return false // reject all other node types
|
||||||
})
|
})
|
||||||
|
|
||||||
// results contain only the 'struct_two' TomlTree
|
// results contain only the 'struct_two' Tree
|
||||||
query.Execute(tree)
|
query.Execute(tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,8 +147,8 @@ func TestTomlQuery(t *testing.T) {
|
|||||||
t.Errorf("Expected resultset of 1, got %d instead: %v", len(values), values)
|
t.Errorf("Expected resultset of 1, got %d instead: %v", len(values), values)
|
||||||
}
|
}
|
||||||
|
|
||||||
if tt, ok := values[0].(*toml.TomlTree); !ok {
|
if tt, ok := values[0].(*toml.Tree); !ok {
|
||||||
t.Errorf("Expected type of TomlTree: %T", values[0])
|
t.Errorf("Expected type of Tree: %T", values[0])
|
||||||
} else if tt.Get("a") != int64(1) {
|
} else if tt.Get("a") != int64(1) {
|
||||||
t.Errorf("Expected 'a' with a value 1: %v", tt.Get("a"))
|
t.Errorf("Expected 'a' with a value 1: %v", tt.Get("a"))
|
||||||
} else if tt.Get("b") != int64(2) {
|
} else if tt.Get("b") != int64(2) {
|
||||||
|
|||||||
@@ -14,35 +14,35 @@ type tomlValue struct {
|
|||||||
position Position
|
position Position
|
||||||
}
|
}
|
||||||
|
|
||||||
// TomlTree is the result of the parsing of a TOML file.
|
// Tree is the result of the parsing of a TOML file.
|
||||||
type TomlTree struct {
|
type Tree struct {
|
||||||
values map[string]interface{} // string -> *tomlValue, *TomlTree, []*TomlTree
|
values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree
|
||||||
position Position
|
position Position
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTomlTree() *TomlTree {
|
func newTree() *Tree {
|
||||||
return &TomlTree{
|
return &Tree{
|
||||||
values: make(map[string]interface{}),
|
values: make(map[string]interface{}),
|
||||||
position: Position{},
|
position: Position{},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TreeFromMap initializes a new TomlTree object using the given map.
|
// TreeFromMap initializes a new Tree object using the given map.
|
||||||
func TreeFromMap(m map[string]interface{}) (*TomlTree, error) {
|
func TreeFromMap(m map[string]interface{}) (*Tree, error) {
|
||||||
result, err := toTree(m)
|
result, err := toTree(m)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return result.(*TomlTree), nil
|
return result.(*Tree), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Position returns the position of the tree.
|
// Position returns the position of the tree.
|
||||||
func (t *TomlTree) Position() Position {
|
func (t *Tree) Position() Position {
|
||||||
return t.position
|
return t.position
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has returns a boolean indicating if the given key exists.
|
// Has returns a boolean indicating if the given key exists.
|
||||||
func (t *TomlTree) Has(key string) bool {
|
func (t *Tree) Has(key string) bool {
|
||||||
if key == "" {
|
if key == "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -50,13 +50,13 @@ func (t *TomlTree) Has(key string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// HasPath returns true if the given path of keys exists, false otherwise.
|
// HasPath returns true if the given path of keys exists, false otherwise.
|
||||||
func (t *TomlTree) HasPath(keys []string) bool {
|
func (t *Tree) HasPath(keys []string) bool {
|
||||||
return t.GetPath(keys) != nil
|
return t.GetPath(keys) != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keys returns the keys of the toplevel tree.
|
// Keys returns the keys of the toplevel tree.
|
||||||
// Warning: this is a costly operation.
|
// Warning: this is a costly operation.
|
||||||
func (t *TomlTree) Keys() []string {
|
func (t *Tree) Keys() []string {
|
||||||
keys := make([]string, len(t.values))
|
keys := make([]string, len(t.values))
|
||||||
i := 0
|
i := 0
|
||||||
for k := range t.values {
|
for k := range t.values {
|
||||||
@@ -66,11 +66,11 @@ func (t *TomlTree) Keys() []string {
|
|||||||
return keys
|
return keys
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the value at key in the TomlTree.
|
// Get the value at key in the Tree.
|
||||||
// Key is a dot-separated path (e.g. a.b.c).
|
// Key is a dot-separated path (e.g. a.b.c).
|
||||||
// Returns nil if the path does not exist in the tree.
|
// Returns nil if the path does not exist in the tree.
|
||||||
// If keys is of length zero, the current tree is returned.
|
// If keys is of length zero, the current tree is returned.
|
||||||
func (t *TomlTree) Get(key string) interface{} {
|
func (t *Tree) Get(key string) interface{} {
|
||||||
if key == "" {
|
if key == "" {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ func (t *TomlTree) Get(key string) interface{} {
|
|||||||
|
|
||||||
// GetPath returns the element in the tree indicated by 'keys'.
|
// GetPath returns the element in the tree indicated by 'keys'.
|
||||||
// If keys is of length zero, the current tree is returned.
|
// If keys is of length zero, the current tree is returned.
|
||||||
func (t *TomlTree) GetPath(keys []string) interface{} {
|
func (t *Tree) GetPath(keys []string) interface{} {
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
@@ -94,9 +94,9 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
switch node := value.(type) {
|
switch node := value.(type) {
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
subtree = node
|
subtree = node
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
// go to most recent element
|
// go to most recent element
|
||||||
if len(node) == 0 {
|
if len(node) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@@ -116,7 +116,7 @@ func (t *TomlTree) GetPath(keys []string) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetPosition returns the position of the given key.
|
// GetPosition returns the position of the given key.
|
||||||
func (t *TomlTree) GetPosition(key string) Position {
|
func (t *Tree) GetPosition(key string) Position {
|
||||||
if key == "" {
|
if key == "" {
|
||||||
return t.position
|
return t.position
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,7 @@ func (t *TomlTree) GetPosition(key string) Position {
|
|||||||
|
|
||||||
// GetPositionPath returns the element in the tree indicated by 'keys'.
|
// GetPositionPath returns the element in the tree indicated by 'keys'.
|
||||||
// If keys is of length zero, the current tree is returned.
|
// If keys is of length zero, the current tree is returned.
|
||||||
func (t *TomlTree) GetPositionPath(keys []string) Position {
|
func (t *Tree) GetPositionPath(keys []string) Position {
|
||||||
if len(keys) == 0 {
|
if len(keys) == 0 {
|
||||||
return t.position
|
return t.position
|
||||||
}
|
}
|
||||||
@@ -136,9 +136,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
|
|||||||
return Position{0, 0}
|
return Position{0, 0}
|
||||||
}
|
}
|
||||||
switch node := value.(type) {
|
switch node := value.(type) {
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
subtree = node
|
subtree = node
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
// go to most recent element
|
// go to most recent element
|
||||||
if len(node) == 0 {
|
if len(node) == 0 {
|
||||||
return Position{0, 0}
|
return Position{0, 0}
|
||||||
@@ -152,9 +152,9 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
|
|||||||
switch node := subtree.values[keys[len(keys)-1]].(type) {
|
switch node := subtree.values[keys[len(keys)-1]].(type) {
|
||||||
case *tomlValue:
|
case *tomlValue:
|
||||||
return node.position
|
return node.position
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
return node.position
|
return node.position
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
// go to most recent element
|
// go to most recent element
|
||||||
if len(node) == 0 {
|
if len(node) == 0 {
|
||||||
return Position{0, 0}
|
return Position{0, 0}
|
||||||
@@ -166,7 +166,7 @@ func (t *TomlTree) GetPositionPath(keys []string) Position {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetDefault works like Get but with a default value
|
// GetDefault works like Get but with a default value
|
||||||
func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
|
func (t *Tree) GetDefault(key string, def interface{}) interface{} {
|
||||||
val := t.Get(key)
|
val := t.Get(key)
|
||||||
if val == nil {
|
if val == nil {
|
||||||
return def
|
return def
|
||||||
@@ -177,29 +177,29 @@ func (t *TomlTree) GetDefault(key string, def interface{}) interface{} {
|
|||||||
// Set an element in the tree.
|
// Set an element in the tree.
|
||||||
// Key is a dot-separated path (e.g. a.b.c).
|
// Key is a dot-separated path (e.g. a.b.c).
|
||||||
// Creates all necessary intermediate trees, if needed.
|
// Creates all necessary intermediate trees, if needed.
|
||||||
func (t *TomlTree) Set(key string, value interface{}) {
|
func (t *Tree) Set(key string, value interface{}) {
|
||||||
t.SetPath(strings.Split(key, "."), value)
|
t.SetPath(strings.Split(key, "."), value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetPath sets an element in the tree.
|
// SetPath sets an element in the tree.
|
||||||
// Keys is an array of path elements (e.g. {"a","b","c"}).
|
// Keys is an array of path elements (e.g. {"a","b","c"}).
|
||||||
// Creates all necessary intermediate trees, if needed.
|
// Creates all necessary intermediate trees, if needed.
|
||||||
func (t *TomlTree) SetPath(keys []string, value interface{}) {
|
func (t *Tree) SetPath(keys []string, value interface{}) {
|
||||||
subtree := t
|
subtree := t
|
||||||
for _, intermediateKey := range keys[:len(keys)-1] {
|
for _, intermediateKey := range keys[:len(keys)-1] {
|
||||||
nextTree, exists := subtree.values[intermediateKey]
|
nextTree, exists := subtree.values[intermediateKey]
|
||||||
if !exists {
|
if !exists {
|
||||||
nextTree = newTomlTree()
|
nextTree = newTree()
|
||||||
subtree.values[intermediateKey] = nextTree // add new element here
|
subtree.values[intermediateKey] = nextTree // add new element here
|
||||||
}
|
}
|
||||||
switch node := nextTree.(type) {
|
switch node := nextTree.(type) {
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
subtree = node
|
subtree = node
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
// go to most recent element
|
// go to most recent element
|
||||||
if len(node) == 0 {
|
if len(node) == 0 {
|
||||||
// create element if it does not exist
|
// create element if it does not exist
|
||||||
subtree.values[intermediateKey] = append(node, newTomlTree())
|
subtree.values[intermediateKey] = append(node, newTree())
|
||||||
}
|
}
|
||||||
subtree = node[len(node)-1]
|
subtree = node[len(node)-1]
|
||||||
}
|
}
|
||||||
@@ -208,9 +208,9 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
|
|||||||
var toInsert interface{}
|
var toInsert interface{}
|
||||||
|
|
||||||
switch value.(type) {
|
switch value.(type) {
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
toInsert = value
|
toInsert = value
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
toInsert = value
|
toInsert = value
|
||||||
case *tomlValue:
|
case *tomlValue:
|
||||||
toInsert = value
|
toInsert = value
|
||||||
@@ -228,21 +228,21 @@ func (t *TomlTree) SetPath(keys []string, value interface{}) {
|
|||||||
// and tree[a][b][c]
|
// and tree[a][b][c]
|
||||||
//
|
//
|
||||||
// Returns nil on success, error object on failure
|
// Returns nil on success, error object on failure
|
||||||
func (t *TomlTree) createSubTree(keys []string, pos Position) error {
|
func (t *Tree) createSubTree(keys []string, pos Position) error {
|
||||||
subtree := t
|
subtree := t
|
||||||
for _, intermediateKey := range keys {
|
for _, intermediateKey := range keys {
|
||||||
nextTree, exists := subtree.values[intermediateKey]
|
nextTree, exists := subtree.values[intermediateKey]
|
||||||
if !exists {
|
if !exists {
|
||||||
tree := newTomlTree()
|
tree := newTree()
|
||||||
tree.position = pos
|
tree.position = pos
|
||||||
subtree.values[intermediateKey] = tree
|
subtree.values[intermediateKey] = tree
|
||||||
nextTree = tree
|
nextTree = tree
|
||||||
}
|
}
|
||||||
|
|
||||||
switch node := nextTree.(type) {
|
switch node := nextTree.(type) {
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
subtree = node[len(node)-1]
|
subtree = node[len(node)-1]
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
subtree = node
|
subtree = node
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
|
return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
|
||||||
@@ -252,8 +252,8 @@ func (t *TomlTree) createSubTree(keys []string, pos Position) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadReader creates a TomlTree from any io.Reader.
|
// LoadReader creates a Tree from any io.Reader.
|
||||||
func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
|
func LoadReader(reader io.Reader) (tree *Tree, err error) {
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
if _, ok := r.(runtime.Error); ok {
|
if _, ok := r.(runtime.Error); ok {
|
||||||
@@ -266,13 +266,13 @@ func LoadReader(reader io.Reader) (tree *TomlTree, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load creates a TomlTree from a string.
|
// Load creates a Tree from a string.
|
||||||
func Load(content string) (tree *TomlTree, err error) {
|
func Load(content string) (tree *Tree, err error) {
|
||||||
return LoadReader(strings.NewReader(content))
|
return LoadReader(strings.NewReader(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadFile creates a TomlTree from a file.
|
// LoadFile creates a Tree from a file.
|
||||||
func LoadFile(path string) (tree *TomlTree, err error) {
|
func LoadFile(path string) (tree *Tree, err error) {
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
+2
-2
@@ -70,12 +70,12 @@ func TestTomlHasPath(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlGetPath(t *testing.T) {
|
func TestTomlGetPath(t *testing.T) {
|
||||||
node := newTomlTree()
|
node := newTree()
|
||||||
//TODO: set other node data
|
//TODO: set other node data
|
||||||
|
|
||||||
for idx, item := range []struct {
|
for idx, item := range []struct {
|
||||||
Path []string
|
Path []string
|
||||||
Expected *TomlTree
|
Expected *Tree
|
||||||
}{
|
}{
|
||||||
{ // empty path test
|
{ // empty path test
|
||||||
[]string{},
|
[]string{},
|
||||||
|
|||||||
+5
-5
@@ -51,7 +51,7 @@ func simpleValueCoercion(object interface{}) (interface{}, error) {
|
|||||||
case fmt.Stringer:
|
case fmt.Stringer:
|
||||||
return original.String(), nil
|
return original.String(), nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("cannot convert type %T to TomlTree", object)
|
return nil, fmt.Errorf("cannot convert type %T to Tree", object)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ func sliceToTree(object interface{}) (interface{}, error) {
|
|||||||
// arrays are a bit tricky, since they can represent either a
|
// arrays are a bit tricky, since they can represent either a
|
||||||
// collection of simple values, which is represented by one
|
// collection of simple values, which is represented by one
|
||||||
// *tomlValue, or an array of tables, which is represented by an
|
// *tomlValue, or an array of tables, which is represented by an
|
||||||
// array of *TomlTree.
|
// array of *Tree.
|
||||||
|
|
||||||
// holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
|
// holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
|
||||||
value := reflect.ValueOf(object)
|
value := reflect.ValueOf(object)
|
||||||
@@ -70,14 +70,14 @@ func sliceToTree(object interface{}) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
if insideType.Kind() == reflect.Map {
|
if insideType.Kind() == reflect.Map {
|
||||||
// this is considered as an array of tables
|
// this is considered as an array of tables
|
||||||
tablesArray := make([]*TomlTree, 0, length)
|
tablesArray := make([]*Tree, 0, length)
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
table := value.Index(i)
|
table := value.Index(i)
|
||||||
tree, err := toTree(table.Interface())
|
tree, err := toTree(table.Interface())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
tablesArray = append(tablesArray, tree.(*TomlTree))
|
tablesArray = append(tablesArray, tree.(*Tree))
|
||||||
}
|
}
|
||||||
return tablesArray, nil
|
return tablesArray, nil
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ func toTree(object interface{}) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
values[key.String()] = newValue
|
values[key.String()] = newValue
|
||||||
}
|
}
|
||||||
return &TomlTree{values, Position{}}, nil
|
return &Tree{values, Position{}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
|
if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
|
||||||
|
|||||||
+12
-12
@@ -1,9 +1,9 @@
|
|||||||
package toml
|
package toml
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"strconv"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type customString string
|
type customString string
|
||||||
@@ -16,11 +16,11 @@ func (s stringer) String() string {
|
|||||||
|
|
||||||
func validate(t *testing.T, path string, object interface{}) {
|
func validate(t *testing.T, path string, object interface{}) {
|
||||||
switch o := object.(type) {
|
switch o := object.(type) {
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
for key, tree := range o.values {
|
for key, tree := range o.values {
|
||||||
validate(t, path+"."+key, tree)
|
validate(t, path+"."+key, tree)
|
||||||
}
|
}
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
for index, tree := range o {
|
for index, tree := range o {
|
||||||
validate(t, path+"."+strconv.Itoa(index), tree)
|
validate(t, path+"."+strconv.Itoa(index), tree)
|
||||||
}
|
}
|
||||||
@@ -37,11 +37,11 @@ func validate(t *testing.T, path string, object interface{}) {
|
|||||||
t.Logf("validation ok %s as %T", path, object)
|
t.Logf("validation ok %s as %T", path, object)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateTree(t *testing.T, tree *TomlTree) {
|
func validateTree(t *testing.T, tree *Tree) {
|
||||||
validate(t, "", tree)
|
validate(t, "", tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeCreateToTree(t *testing.T) {
|
func TestTreeCreateToTree(t *testing.T) {
|
||||||
data := map[string]interface{}{
|
data := map[string]interface{}{
|
||||||
"a_string": "bar",
|
"a_string": "bar",
|
||||||
"an_int": 42,
|
"an_int": 42,
|
||||||
@@ -72,15 +72,15 @@ func TestTomlTreeCreateToTree(t *testing.T) {
|
|||||||
validateTree(t, tree)
|
validateTree(t, tree)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeCreateToTreeInvalidLeafType(t *testing.T) {
|
func TestTreeCreateToTreeInvalidLeafType(t *testing.T) {
|
||||||
_, err := TreeFromMap(map[string]interface{}{"foo": t})
|
_, err := TreeFromMap(map[string]interface{}{"foo": t})
|
||||||
expected := "cannot convert type *testing.T to TomlTree"
|
expected := "cannot convert type *testing.T to Tree"
|
||||||
if err.Error() != expected {
|
if err.Error() != expected {
|
||||||
t.Fatalf("expected error %s, got %s", expected, err.Error())
|
t.Fatalf("expected error %s, got %s", expected, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeCreateToTreeInvalidMapKeyType(t *testing.T) {
|
func TestTreeCreateToTreeInvalidMapKeyType(t *testing.T) {
|
||||||
_, err := TreeFromMap(map[string]interface{}{"foo": map[int]interface{}{2: 1}})
|
_, err := TreeFromMap(map[string]interface{}{"foo": map[int]interface{}{2: 1}})
|
||||||
expected := "map key needs to be a string, not int (int)"
|
expected := "map key needs to be a string, not int (int)"
|
||||||
if err.Error() != expected {
|
if err.Error() != expected {
|
||||||
@@ -88,17 +88,17 @@ func TestTomlTreeCreateToTreeInvalidMapKeyType(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeCreateToTreeInvalidArrayMemberType(t *testing.T) {
|
func TestTreeCreateToTreeInvalidArrayMemberType(t *testing.T) {
|
||||||
_, err := TreeFromMap(map[string]interface{}{"foo": []*testing.T{t}})
|
_, err := TreeFromMap(map[string]interface{}{"foo": []*testing.T{t}})
|
||||||
expected := "cannot convert type *testing.T to TomlTree"
|
expected := "cannot convert type *testing.T to Tree"
|
||||||
if err.Error() != expected {
|
if err.Error() != expected {
|
||||||
t.Fatalf("expected error %s, got %s", expected, err.Error())
|
t.Fatalf("expected error %s, got %s", expected, err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeCreateToTreeInvalidTableGroupType(t *testing.T) {
|
func TestTreeCreateToTreeInvalidTableGroupType(t *testing.T) {
|
||||||
_, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"hello": t}}})
|
_, err := TreeFromMap(map[string]interface{}{"foo": []map[string]interface{}{map[string]interface{}{"hello": t}}})
|
||||||
expected := "cannot convert type *testing.T to TomlTree"
|
expected := "cannot convert type *testing.T to Tree"
|
||||||
if err.Error() != expected {
|
if err.Error() != expected {
|
||||||
t.Fatalf("expected error %s, got %s", expected, err.Error())
|
t.Fatalf("expected error %s, got %s", expected, err.Error())
|
||||||
}
|
}
|
||||||
|
|||||||
+12
-12
@@ -4,11 +4,11 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"reflect"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"reflect"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// encodes a string to a TOML-compliant string value
|
// encodes a string to a TOML-compliant string value
|
||||||
@@ -83,14 +83,14 @@ func tomlValueStringRepresentation(v interface{}) (string, error) {
|
|||||||
return "", fmt.Errorf("unsupported value type %T: %v", v, v)
|
return "", fmt.Errorf("unsupported value type %T: %v", v, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) {
|
func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64) (int64, error) {
|
||||||
simpleValuesKeys := make([]string, 0)
|
simpleValuesKeys := make([]string, 0)
|
||||||
complexValuesKeys := make([]string, 0)
|
complexValuesKeys := make([]string, 0)
|
||||||
|
|
||||||
for k := range t.values {
|
for k := range t.values {
|
||||||
v := t.values[k]
|
v := t.values[k]
|
||||||
switch v.(type) {
|
switch v.(type) {
|
||||||
case *TomlTree, []*TomlTree:
|
case *Tree, []*Tree:
|
||||||
complexValuesKeys = append(complexValuesKeys, k)
|
complexValuesKeys = append(complexValuesKeys, k)
|
||||||
default:
|
default:
|
||||||
simpleValuesKeys = append(simpleValuesKeys, k)
|
simpleValuesKeys = append(simpleValuesKeys, k)
|
||||||
@@ -129,7 +129,7 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
|
|||||||
|
|
||||||
switch node := v.(type) {
|
switch node := v.(type) {
|
||||||
// node has to be of those two types given how keys are sorted above
|
// node has to be of those two types given how keys are sorted above
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
tableName := fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
|
tableName := fmt.Sprintf("\n%s[%s]\n", indent, combinedKey)
|
||||||
writtenBytesCount, err := w.Write([]byte(tableName))
|
writtenBytesCount, err := w.Write([]byte(tableName))
|
||||||
bytesCount += int64(writtenBytesCount)
|
bytesCount += int64(writtenBytesCount)
|
||||||
@@ -140,7 +140,7 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return bytesCount, err
|
return bytesCount, err
|
||||||
}
|
}
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
for _, subTree := range node {
|
for _, subTree := range node {
|
||||||
if len(subTree.values) > 0 {
|
if len(subTree.values) > 0 {
|
||||||
tableArrayName := fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey)
|
tableArrayName := fmt.Sprintf("\n%s[[%s]]\n", indent, combinedKey)
|
||||||
@@ -162,16 +162,16 @@ func (t *TomlTree) writeTo(w io.Writer, indent, keyspace string, bytesCount int6
|
|||||||
return bytesCount, nil
|
return bytesCount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// WriteTo encode the TomlTree as Toml and writes it to the writer w.
|
// WriteTo encode the Tree as Toml and writes it to the writer w.
|
||||||
// Returns the number of bytes written in case of success, or an error if anything happened.
|
// Returns the number of bytes written in case of success, or an error if anything happened.
|
||||||
func (t *TomlTree) WriteTo(w io.Writer) (int64, error) {
|
func (t *Tree) WriteTo(w io.Writer) (int64, error) {
|
||||||
return t.writeTo(w, "", "", 0)
|
return t.writeTo(w, "", "", 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToTomlString generates a human-readable representation of the current tree.
|
// ToTomlString generates a human-readable representation of the current tree.
|
||||||
// Output spans multiple lines, and is suitable for ingest by a TOML parser.
|
// Output spans multiple lines, and is suitable for ingest by a TOML parser.
|
||||||
// If the conversion cannot be performed, ToString returns a non-nil error.
|
// If the conversion cannot be performed, ToString returns a non-nil error.
|
||||||
func (t *TomlTree) ToTomlString() (string, error) {
|
func (t *Tree) ToTomlString() (string, error) {
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
_, err := t.WriteTo(&buf)
|
_, err := t.WriteTo(&buf)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -182,7 +182,7 @@ func (t *TomlTree) ToTomlString() (string, error) {
|
|||||||
|
|
||||||
// String generates a human-readable representation of the current tree.
|
// String generates a human-readable representation of the current tree.
|
||||||
// Alias of ToString. Present to implement the fmt.Stringer interface.
|
// Alias of ToString. Present to implement the fmt.Stringer interface.
|
||||||
func (t *TomlTree) String() string {
|
func (t *Tree) String() string {
|
||||||
result, _ := t.ToTomlString()
|
result, _ := t.ToTomlString()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
@@ -196,18 +196,18 @@ func (t *TomlTree) String() string {
|
|||||||
// * time.Time
|
// * time.Time
|
||||||
// * map[string]interface{} (where interface{} is any of this list)
|
// * map[string]interface{} (where interface{} is any of this list)
|
||||||
// * []interface{} (where interface{} is any of this list)
|
// * []interface{} (where interface{} is any of this list)
|
||||||
func (t *TomlTree) ToMap() map[string]interface{} {
|
func (t *Tree) ToMap() map[string]interface{} {
|
||||||
result := map[string]interface{}{}
|
result := map[string]interface{}{}
|
||||||
|
|
||||||
for k, v := range t.values {
|
for k, v := range t.values {
|
||||||
switch node := v.(type) {
|
switch node := v.(type) {
|
||||||
case []*TomlTree:
|
case []*Tree:
|
||||||
var array []interface{}
|
var array []interface{}
|
||||||
for _, item := range node {
|
for _, item := range node {
|
||||||
array = append(array, item.ToMap())
|
array = append(array, item.ToMap())
|
||||||
}
|
}
|
||||||
result[k] = array
|
result[k] = array
|
||||||
case *TomlTree:
|
case *Tree:
|
||||||
result[k] = node.ToMap()
|
result[k] = node.ToMap()
|
||||||
case *tomlValue:
|
case *tomlValue:
|
||||||
result[k] = node.value
|
result[k] = node.value
|
||||||
|
|||||||
+16
-16
@@ -40,7 +40,7 @@ func assertErrorString(t *testing.T, expected string, err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToTomlString(t *testing.T) {
|
func TestTreeWriteToTomlString(t *testing.T) {
|
||||||
toml, err := Load(`name = { first = "Tom", last = "Preston-Werner" }
|
toml, err := Load(`name = { first = "Tom", last = "Preston-Werner" }
|
||||||
points = { x = 1, y = 2 }`)
|
points = { x = 1, y = 2 }`)
|
||||||
|
|
||||||
@@ -63,7 +63,7 @@ points = { x = 1, y = 2 }`)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToTomlStringSimple(t *testing.T) {
|
func TestTreeWriteToTomlStringSimple(t *testing.T) {
|
||||||
tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n")
|
tree, err := Load("[foo]\n\n[[foo.bar]]\na = 42\n\n[[foo.bar]]\na = 69\n")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Test failed to parse: %v", err)
|
t.Errorf("Test failed to parse: %v", err)
|
||||||
@@ -79,7 +79,7 @@ func TestTomlTreeWriteToTomlStringSimple(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToTomlStringKeysOrders(t *testing.T) {
|
func TestTreeWriteToTomlStringKeysOrders(t *testing.T) {
|
||||||
for i := 0; i < 100; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
tree, _ := Load(`
|
tree, _ := Load(`
|
||||||
foobar = true
|
foobar = true
|
||||||
@@ -119,7 +119,7 @@ func testMaps(t *testing.T, actual, expected map[string]interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToMapSimple(t *testing.T) {
|
func TestTreeWriteToMapSimple(t *testing.T) {
|
||||||
tree, _ := Load("a = 42\nb = 17")
|
tree, _ := Load("a = 42\nb = 17")
|
||||||
|
|
||||||
expected := map[string]interface{}{
|
expected := map[string]interface{}{
|
||||||
@@ -130,32 +130,32 @@ func TestTomlTreeWriteToMapSimple(t *testing.T) {
|
|||||||
testMaps(t, tree.ToMap(), expected)
|
testMaps(t, tree.ToMap(), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToInvalidTreeSimpleValue(t *testing.T) {
|
func TestTreeWriteToInvalidTreeSimpleValue(t *testing.T) {
|
||||||
tree := TomlTree{values: map[string]interface{}{"foo": int8(1)}}
|
tree := Tree{values: map[string]interface{}{"foo": int8(1)}}
|
||||||
_, err := tree.ToTomlString()
|
_, err := tree.ToTomlString()
|
||||||
assertErrorString(t, "invalid value type at foo: int8", err)
|
assertErrorString(t, "invalid value type at foo: int8", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToInvalidTreeTomlValue(t *testing.T) {
|
func TestTreeWriteToInvalidTreeTomlValue(t *testing.T) {
|
||||||
tree := TomlTree{values: map[string]interface{}{"foo": &tomlValue{int8(1), Position{}}}}
|
tree := Tree{values: map[string]interface{}{"foo": &tomlValue{int8(1), Position{}}}}
|
||||||
_, err := tree.ToTomlString()
|
_, err := tree.ToTomlString()
|
||||||
assertErrorString(t, "unsupported value type int8: 1", err)
|
assertErrorString(t, "unsupported value type int8: 1", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToInvalidTreeTomlValueArray(t *testing.T) {
|
func TestTreeWriteToInvalidTreeTomlValueArray(t *testing.T) {
|
||||||
tree := TomlTree{values: map[string]interface{}{"foo": &tomlValue{[]interface{}{int8(1)}, Position{}}}}
|
tree := Tree{values: map[string]interface{}{"foo": &tomlValue{[]interface{}{int8(1)}, Position{}}}}
|
||||||
_, err := tree.ToTomlString()
|
_, err := tree.ToTomlString()
|
||||||
assertErrorString(t, "unsupported value type int8: 1", err)
|
assertErrorString(t, "unsupported value type int8: 1", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToFailingWriterInSimpleValue(t *testing.T) {
|
func TestTreeWriteToFailingWriterInSimpleValue(t *testing.T) {
|
||||||
toml, _ := Load(`a = 2`)
|
toml, _ := Load(`a = 2`)
|
||||||
writer := failingWriter{failAt: 0, written: 0}
|
writer := failingWriter{failAt: 0, written: 0}
|
||||||
_, err := toml.WriteTo(writer)
|
_, err := toml.WriteTo(writer)
|
||||||
assertErrorString(t, "failingWriter failed after writting 0 bytes", err)
|
assertErrorString(t, "failingWriter failed after writting 0 bytes", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToFailingWriterInTable(t *testing.T) {
|
func TestTreeWriteToFailingWriterInTable(t *testing.T) {
|
||||||
toml, _ := Load(`
|
toml, _ := Load(`
|
||||||
[b]
|
[b]
|
||||||
a = 2`)
|
a = 2`)
|
||||||
@@ -168,7 +168,7 @@ a = 2`)
|
|||||||
assertErrorString(t, "failingWriter failed after writting 13 bytes", err)
|
assertErrorString(t, "failingWriter failed after writting 13 bytes", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToFailingWriterInArray(t *testing.T) {
|
func TestTreeWriteToFailingWriterInArray(t *testing.T) {
|
||||||
toml, _ := Load(`
|
toml, _ := Load(`
|
||||||
[[b]]
|
[[b]]
|
||||||
a = 2`)
|
a = 2`)
|
||||||
@@ -181,7 +181,7 @@ a = 2`)
|
|||||||
assertErrorString(t, "failingWriter failed after writting 15 bytes", err)
|
assertErrorString(t, "failingWriter failed after writting 15 bytes", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToMapExampleFile(t *testing.T) {
|
func TestTreeWriteToMapExampleFile(t *testing.T) {
|
||||||
tree, _ := LoadFile("example.toml")
|
tree, _ := LoadFile("example.toml")
|
||||||
expected := map[string]interface{}{
|
expected := map[string]interface{}{
|
||||||
"title": "TOML Example",
|
"title": "TOML Example",
|
||||||
@@ -217,7 +217,7 @@ func TestTomlTreeWriteToMapExampleFile(t *testing.T) {
|
|||||||
testMaps(t, tree.ToMap(), expected)
|
testMaps(t, tree.ToMap(), expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) {
|
func TestTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) {
|
||||||
tree, _ := Load(`
|
tree, _ := Load(`
|
||||||
[[menu.main]]
|
[[menu.main]]
|
||||||
a = "menu 1"
|
a = "menu 1"
|
||||||
@@ -238,7 +238,7 @@ func TestTomlTreeWriteToMapWithTablesInMultipleChunks(t *testing.T) {
|
|||||||
testMaps(t, treeMap, expected)
|
testMaps(t, treeMap, expected)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTomlTreeWriteToMapWithArrayOfInlineTables(t *testing.T) {
|
func TestTreeWriteToMapWithArrayOfInlineTables(t *testing.T) {
|
||||||
tree, _ := Load(`
|
tree, _ := Load(`
|
||||||
[params]
|
[params]
|
||||||
language_tabs = [
|
language_tabs = [
|
||||||
|
|||||||
Reference in New Issue
Block a user