package awsutil import ( "bytes" "fmt" "io" "reflect" "strings" ) // Prettify returns the string representation of a value. func Prettify(i interface{}) string { var buf bytes.Buffer prettify(reflect.ValueOf(i), 0, &buf) return buf.String() } // prettify will recursively walk value v to build a textual // representation of the value. func prettify(v reflect.Value, indent int, buf *bytes.Buffer) { for v.Kind() == reflect.Ptr { v = v.Elem() } switch v.Kind() { case reflect.Struct: strtype := v.Type().String() if strtype == "time.Time" { fmt.Fprintf(buf, "%s", v.Interface()) break } else if strings.HasPrefix(strtype, "io.") { buf.WriteString("") break } buf.WriteString("{\n") names := []string{} for i := 0; i < v.Type().NumField(); i++ { name := v.Type().Field(i).Name f := v.Field(i) if name[0:1] == strings.ToLower(name[0:1]) { continue // ignore unexported fields } if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() { continue // ignore unset fields } names = append(names, name) } for i, n := range names { val := v.FieldByName(n) buf.WriteString(strings.Repeat(" ", indent+2)) buf.WriteString(n + ": ") prettify(val, indent+2, buf) if i < len(names)-1 { buf.WriteString(",\n") } } buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") case reflect.Slice: strtype := v.Type().String() if strtype == "[]uint8" { fmt.Fprintf(buf, " len %d", v.Len()) break } nl, id, id2 := "", "", "" if v.Len() > 3 { nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2) } buf.WriteString("[" + nl) for i := 0; i < v.Len(); i++ { buf.WriteString(id2) prettify(v.Index(i), indent+2, buf) if i < v.Len()-1 { buf.WriteString("," + nl) } } buf.WriteString(nl + id + "]") case reflect.Map: buf.WriteString("{\n") for i, k := range v.MapKeys() { buf.WriteString(strings.Repeat(" ", indent+2)) buf.WriteString(k.String() + ": ") prettify(v.MapIndex(k), indent+2, buf) if i < v.Len()-1 { buf.WriteString(",\n") } } buf.WriteString("\n" + strings.Repeat(" ", indent) + "}") default: if !v.IsValid() { fmt.Fprint(buf, "") return } format := "%v" switch v.Interface().(type) { case string: format = "%q" case io.ReadSeeker, io.Reader: format = "buffer(%p)" } fmt.Fprintf(buf, format, v.Interface()) } }