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