| // Copyright 2025 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| 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, '}') | |
| } | |
| } |