| | |
| | |
| | |
| |
|
| | package main |
| |
|
| | import ( |
| | "fmt" |
| | "reflect" |
| | "strconv" |
| | ) |
| |
|
| | func pprints(v any) string { |
| | var pp pprinter |
| | pp.val(reflect.ValueOf(v), 0) |
| | return string(pp.buf) |
| | } |
| |
|
| | type pprinter struct { |
| | buf []byte |
| | } |
| |
|
| | func (p *pprinter) indent(by int) { |
| | for range by { |
| | p.buf = append(p.buf, '\t') |
| | } |
| | } |
| |
|
| | func (p *pprinter) val(v reflect.Value, indent int) { |
| | switch v.Kind() { |
| | default: |
| | p.buf = fmt.Appendf(p.buf, "unsupported kind %v", v.Kind()) |
| |
|
| | case reflect.Bool: |
| | p.buf = strconv.AppendBool(p.buf, v.Bool()) |
| |
|
| | case reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64: |
| | p.buf = strconv.AppendInt(p.buf, v.Int(), 10) |
| |
|
| | case reflect.String: |
| | p.buf = strconv.AppendQuote(p.buf, v.String()) |
| |
|
| | case reflect.Pointer: |
| | if v.IsNil() { |
| | p.buf = append(p.buf, "nil"...) |
| | } else { |
| | p.buf = append(p.buf, "&"...) |
| | p.val(v.Elem(), indent) |
| | } |
| |
|
| | case reflect.Slice, reflect.Array: |
| | p.buf = append(p.buf, "[\n"...) |
| | for i := range v.Len() { |
| | p.indent(indent + 1) |
| | p.val(v.Index(i), indent+1) |
| | p.buf = append(p.buf, ",\n"...) |
| | } |
| | p.indent(indent) |
| | p.buf = append(p.buf, ']') |
| |
|
| | case reflect.Struct: |
| | vt := v.Type() |
| | p.buf = append(append(p.buf, vt.String()...), "{\n"...) |
| | for f := range v.NumField() { |
| | p.indent(indent + 1) |
| | p.buf = append(append(p.buf, vt.Field(f).Name...), ": "...) |
| | p.val(v.Field(f), indent+1) |
| | p.buf = append(p.buf, ",\n"...) |
| | } |
| | p.indent(indent) |
| | p.buf = append(p.buf, '}') |
| | } |
| | } |
| |
|