prettify.go 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package awsutil
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "reflect"
  7. "strings"
  8. )
  9. // Prettify returns the string representation of a value.
  10. func Prettify(i interface{}) string {
  11. var buf bytes.Buffer
  12. prettify(reflect.ValueOf(i), 0, &buf)
  13. return buf.String()
  14. }
  15. // prettify will recursively walk value v to build a textual
  16. // representation of the value.
  17. func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
  18. for v.Kind() == reflect.Ptr {
  19. v = v.Elem()
  20. }
  21. switch v.Kind() {
  22. case reflect.Struct:
  23. strtype := v.Type().String()
  24. if strtype == "time.Time" {
  25. fmt.Fprintf(buf, "%s", v.Interface())
  26. break
  27. } else if strings.HasPrefix(strtype, "io.") {
  28. buf.WriteString("<buffer>")
  29. break
  30. }
  31. buf.WriteString("{\n")
  32. names := []string{}
  33. for i := 0; i < v.Type().NumField(); i++ {
  34. name := v.Type().Field(i).Name
  35. f := v.Field(i)
  36. if name[0:1] == strings.ToLower(name[0:1]) {
  37. continue // ignore unexported fields
  38. }
  39. if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() {
  40. continue // ignore unset fields
  41. }
  42. names = append(names, name)
  43. }
  44. for i, n := range names {
  45. val := v.FieldByName(n)
  46. buf.WriteString(strings.Repeat(" ", indent+2))
  47. buf.WriteString(n + ": ")
  48. prettify(val, indent+2, buf)
  49. if i < len(names)-1 {
  50. buf.WriteString(",\n")
  51. }
  52. }
  53. buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
  54. case reflect.Slice:
  55. strtype := v.Type().String()
  56. if strtype == "[]uint8" {
  57. fmt.Fprintf(buf, "<binary> len %d", v.Len())
  58. break
  59. }
  60. nl, id, id2 := "", "", ""
  61. if v.Len() > 3 {
  62. nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
  63. }
  64. buf.WriteString("[" + nl)
  65. for i := 0; i < v.Len(); i++ {
  66. buf.WriteString(id2)
  67. prettify(v.Index(i), indent+2, buf)
  68. if i < v.Len()-1 {
  69. buf.WriteString("," + nl)
  70. }
  71. }
  72. buf.WriteString(nl + id + "]")
  73. case reflect.Map:
  74. buf.WriteString("{\n")
  75. for i, k := range v.MapKeys() {
  76. buf.WriteString(strings.Repeat(" ", indent+2))
  77. buf.WriteString(k.String() + ": ")
  78. prettify(v.MapIndex(k), indent+2, buf)
  79. if i < v.Len()-1 {
  80. buf.WriteString(",\n")
  81. }
  82. }
  83. buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
  84. default:
  85. if !v.IsValid() {
  86. fmt.Fprint(buf, "<invalid value>")
  87. return
  88. }
  89. format := "%v"
  90. switch v.Interface().(type) {
  91. case string:
  92. format = "%q"
  93. case io.ReadSeeker, io.Reader:
  94. format = "buffer(%p)"
  95. }
  96. fmt.Fprintf(buf, format, v.Interface())
  97. }
  98. }