diff options
Diffstat (limited to 'pkg/util/fmt.go')
-rw-r--r-- | pkg/util/fmt.go | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/pkg/util/fmt.go b/pkg/util/fmt.go new file mode 100644 index 0000000..c0ff596 --- /dev/null +++ b/pkg/util/fmt.go @@ -0,0 +1,67 @@ +package util + +import ( + "fmt" + "strings" +) + +// FmtStateString returns the fmt.Printf string that produced a given +// fmt.State and verb. +func FmtStateString(st fmt.State, verb rune) string { + var ret strings.Builder + ret.WriteByte('%') + for _, flag := range []int{'-', '+', '#', ' ', '0'} { + if st.Flag(flag) { + ret.WriteByte(byte(flag)) + } + } + if width, ok := st.Width(); ok { + fmt.Fprintf(&ret, "%d", width) + } + if prec, ok := st.Precision(); ok { + if prec == 0 { + ret.WriteByte('.') + } else { + fmt.Fprintf(&ret, ".%d", prec) + } + } + ret.WriteRune(verb) + return ret.String() +} + +// FormatByteArrayStringer is function for helping to implement +// fmt.Formatter for []byte or [n]byte types that have a custom string +// representation. Use it like: +// +// type MyType [16]byte +// +// func (val MyType) String() string { +// … +// } +// +// func (val MyType) Format(f fmt.State, verb rune) { +// util.FormatByteArrayStringer(val, val[:], f, verb) +// } +func FormatByteArrayStringer( + obj interface { + fmt.Stringer + fmt.Formatter + }, + objBytes []byte, + f fmt.State, verb rune) { + switch verb { + case 'v': + if !f.Flag('#') { + FormatByteArrayStringer(obj, objBytes, f, 's') // as a string + } else { + byteStr := fmt.Sprintf("%#v", objBytes) + objType := fmt.Sprintf("%T", obj) + objStr := objType + strings.TrimPrefix(byteStr, "[]byte") + fmt.Fprintf(f, FmtStateString(f, 's'), objStr) + } + case 's', 'q': // string + fmt.Fprintf(f, FmtStateString(f, verb), obj.String()) + default: + fmt.Fprintf(f, FmtStateString(f, verb), objBytes) + } +} |