diff --git a/cmd/moon/main.go b/cmd/moon/main.go index dab0b02..506d630 100644 --- a/cmd/moon/main.go +++ b/cmd/moon/main.go @@ -64,7 +64,11 @@ func get() { if err := doc.Get(docpath, &v); err != nil { bail(1, "error reading value at path %s: %s", docpath, err) } - fmt.Println(v) + b, err := moon.Encode(v) + if err != nil { + bail(1, "error encoding value: %s", err) + } + os.Stdout.Write(b) } func bail(status int, t string, args ...interface{}) { diff --git a/lib/emit.go b/lib/emit.go index e9191c8..5438e2f 100644 --- a/lib/emit.go +++ b/lib/emit.go @@ -68,6 +68,10 @@ func typeEncoder(t reflect.Type) encodeFn { return encodeStruct case reflect.Slice: return encodeSlice + case reflect.Interface: + return encodeInterface + case reflect.Map: + return encodeMap default: panic(fmt.Errorf("unhandled type: %v kind: %v", t, t.Kind())) } @@ -98,7 +102,7 @@ func encodeFloat(bits int) encodeFn { if math.IsInf(f, 0) || math.IsNaN(f) { panic("that value is bad") // TODO: not this } - b := strconv.AppendFloat(e.scratch[:0], f, 'f', 1, bits) + b := strconv.AppendFloat(e.scratch[:0], f, 'g', -1, bits) e.Write(b) } } @@ -155,3 +159,31 @@ func encodeSlice(e *encoder, v reflect.Value) { } e.WriteByte(']') } + +func encodeInterface(e *encoder, v reflect.Value) { + if v.IsNil() { + e.WriteString("null") + return + } + e.encodeValue(v.Elem()) +} + +func encodeMap(e *encoder, v reflect.Value) { + t := v.Type() + if t.Key().Kind() != reflect.String { + panic(fmt.Errorf("unsupported map key type: %v", t.Key().Kind())) + } + keys := v.MapKeys() + e.WriteByte('{') + for i, key := range keys { + if i > 0 { + e.WriteByte(' ') + } + e.WriteString(key.String()) // TODO: escape this? + e.WriteByte(':') + e.WriteByte(' ') + elem := v.MapIndex(key) + e.encodeValue(elem) + } + e.WriteByte('}') +} diff --git a/lib/emit_test.go b/lib/emit_test.go index 261d020..0d89a6a 100644 --- a/lib/emit_test.go +++ b/lib/emit_test.go @@ -33,6 +33,18 @@ var valueTests = []struct { {[]float32{1.0, 2.2, 3.3}, `[1.0 2.2 3.3]`}, {[]float64{1.0, 2.2, 3.3}, `[1.0 2.2 3.3]`}, {[]string{"one", "two", "three"}, `["one" "two" "three"]`}, + { + map[string]int{"one": 1, "two": 2, "three": 3}, + `{one: 1 two: 2 three: 3}`, + }, + { + map[string]interface{}{ + "one": 1, + "two": 2.0, + "pi": 3.14, + }, + `{one: 1 two: 2.0 pi: 3.14}`, + }, } func TestWriteValues(t *testing.T) {