1package main
2
3import (
4	"encoding/json"
5	"fmt"
6	"io/ioutil"
7	"log"
8	"os"
9	"time"
10
11	"github.com/pelletier/go-toml"
12)
13
14func main() {
15	bytes, err := ioutil.ReadAll(os.Stdin)
16	if err != nil {
17		log.Fatalf("Error during TOML read: %s", err)
18		os.Exit(2)
19	}
20	tree, err := toml.Load(string(bytes))
21	if err != nil {
22		log.Fatalf("Error during TOML load: %s", err)
23		os.Exit(1)
24	}
25
26	typedTree := translate(*tree)
27
28	if err := json.NewEncoder(os.Stdout).Encode(typedTree); err != nil {
29		log.Fatalf("Error encoding JSON: %s", err)
30		os.Exit(3)
31	}
32
33	os.Exit(0)
34}
35
36func translate(tomlData interface{}) interface{} {
37	switch orig := tomlData.(type) {
38	case map[string]interface{}:
39		typed := make(map[string]interface{}, len(orig))
40		for k, v := range orig {
41			typed[k] = translate(v)
42		}
43		return typed
44	case *toml.Tree:
45		return translate(*orig)
46	case toml.Tree:
47		keys := orig.Keys()
48		typed := make(map[string]interface{}, len(keys))
49		for _, k := range keys {
50			typed[k] = translate(orig.GetPath([]string{k}))
51		}
52		return typed
53	case []*toml.Tree:
54		typed := make([]map[string]interface{}, len(orig))
55		for i, v := range orig {
56			typed[i] = translate(v).(map[string]interface{})
57		}
58		return typed
59	case []map[string]interface{}:
60		typed := make([]map[string]interface{}, len(orig))
61		for i, v := range orig {
62			typed[i] = translate(v).(map[string]interface{})
63		}
64		return typed
65	case []interface{}:
66		typed := make([]interface{}, len(orig))
67		for i, v := range orig {
68			typed[i] = translate(v)
69		}
70		return tag("array", typed)
71	case time.Time:
72		return tag("datetime", orig.Format("2006-01-02T15:04:05Z"))
73	case bool:
74		return tag("bool", fmt.Sprintf("%v", orig))
75	case int64:
76		return tag("integer", fmt.Sprintf("%d", orig))
77	case float64:
78		return tag("float", fmt.Sprintf("%v", orig))
79	case string:
80		return tag("string", orig)
81	}
82
83	panic(fmt.Sprintf("Unknown type: %T", tomlData))
84}
85
86func tag(typeName string, data interface{}) map[string]interface{} {
87	return map[string]interface{}{
88		"type":  typeName,
89		"value": data,
90	}
91}
92