// Command toml-test-decoder satisfies BurntSushi's toml-test interface for testing // TOML decoders. Namely, it accepts TOML on stdin and outputs JSON on stdout. // See: https://github.com/BurntSushi/toml-test package main import ( "flag" "fmt" "log" "os" "path" "sort" "strings" "time" "git.makaay.nl/mauricem/go-toml/ast" "git.makaay.nl/mauricem/go-toml/parse" ) func init() { log.SetFlags(0) flag.Usage = usage flag.Parse() } func usage() { log.Printf("Usage: %s < toml-file\n", path.Base(os.Args[0])) flag.PrintDefaults() os.Exit(1) } func main() { if flag.NArg() != 0 { flag.Usage() } toml, err := parse.Run(os.Stdin) if err != nil { log.Fatalf("Error decoding TOML: %s", err) } else { sushi := makeSushi(ast.NewValue(ast.TypeTable, toml)) fmt.Println(sushi) } } func makeSushi(value *ast.Value) string { switch value.Type { case ast.TypeString: return renderValue("string", value.Data[0].(string)) case ast.TypeInteger: return renderValue("integer", fmt.Sprintf("%d", value.Data[0].(int64))) case ast.TypeFloat: return renderValue("float", fmt.Sprintf("%v", value.Data[0].(float64))) case ast.TypeBoolean: return renderValue("bool", fmt.Sprintf("%t", value.Data[0].(bool))) case ast.TypeOffsetDateTime: return renderValue("datetime", value.Data[0].(time.Time).Format(time.RFC3339Nano)) case ast.TypeLocalDateTime: return renderValue("local_datetime", value.Data[0].(time.Time).Format("2006-01-02 15:04:05.999999999")) case ast.TypeLocalDate: return renderValue("local_date", value.Data[0].(time.Time).Format("2006-01-02")) case ast.TypeLocalTime: return renderValue("local_time", value.Data[0].(time.Time).Format("15:04:05.999999999")) case ast.TypeArrayOfTables: fallthrough case ast.TypeArray: values := make([]string, len(value.Data)) isArrayOfTables := false for i, value := range value.Data { isArrayOfTables = value.(*ast.Value).Type == ast.TypeTable values[i] = makeSushi(value.(*ast.Value)) } if isArrayOfTables { return fmt.Sprintf("[%s]", strings.Join(values, ", ")) } else { return fmt.Sprintf(`{"type": "array", "value": [%s]}`, strings.Join(values, ", ")) } case ast.TypeTable: pairs := value.Data[0].(ast.Table) keys := make([]string, len(pairs)) i := 0 for k := range pairs { keys[i] = k i++ } sort.Strings(keys) values := make([]string, len(pairs)) for i, k := range keys { values[i] = fmt.Sprintf("%q: %s", k, makeSushi(pairs[k])) } return fmt.Sprintf("{%s}", strings.Join(values, ", ")) default: panic(fmt.Sprintf("Unhandled data type: %s", value.Type)) } } func renderValue(t string, v string) string { return fmt.Sprintf("{%q: %q, %q: %q}", "type", t, "value", v) }