github.com/google/go-github/v49@v49.1.0/github/strings.go (about) 1 // Copyright 2013 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "bytes" 10 "fmt" 11 "io" 12 13 "reflect" 14 ) 15 16 var timestampType = reflect.TypeOf(Timestamp{}) 17 18 // Stringify attempts to create a reasonable string representation of types in 19 // the GitHub library. It does things like resolve pointers to their values 20 // and omits struct fields with nil values. 21 func Stringify(message interface{}) string { 22 var buf bytes.Buffer 23 v := reflect.ValueOf(message) 24 stringifyValue(&buf, v) 25 return buf.String() 26 } 27 28 // stringifyValue was heavily inspired by the goprotobuf library. 29 30 func stringifyValue(w io.Writer, val reflect.Value) { 31 if val.Kind() == reflect.Ptr && val.IsNil() { 32 w.Write([]byte("<nil>")) 33 return 34 } 35 36 v := reflect.Indirect(val) 37 38 switch v.Kind() { 39 case reflect.String: 40 fmt.Fprintf(w, `"%s"`, v) 41 case reflect.Slice: 42 w.Write([]byte{'['}) 43 for i := 0; i < v.Len(); i++ { 44 if i > 0 { 45 w.Write([]byte{' '}) 46 } 47 48 stringifyValue(w, v.Index(i)) 49 } 50 51 w.Write([]byte{']'}) 52 return 53 case reflect.Struct: 54 if v.Type().Name() != "" { 55 w.Write([]byte(v.Type().String())) 56 } 57 58 // special handling of Timestamp values 59 if v.Type() == timestampType { 60 fmt.Fprintf(w, "{%s}", v.Interface()) 61 return 62 } 63 64 w.Write([]byte{'{'}) 65 66 var sep bool 67 for i := 0; i < v.NumField(); i++ { 68 fv := v.Field(i) 69 if fv.Kind() == reflect.Ptr && fv.IsNil() { 70 continue 71 } 72 if fv.Kind() == reflect.Slice && fv.IsNil() { 73 continue 74 } 75 if fv.Kind() == reflect.Map && fv.IsNil() { 76 continue 77 } 78 79 if sep { 80 w.Write([]byte(", ")) 81 } else { 82 sep = true 83 } 84 85 w.Write([]byte(v.Type().Field(i).Name)) 86 w.Write([]byte{':'}) 87 stringifyValue(w, fv) 88 } 89 90 w.Write([]byte{'}'}) 91 default: 92 if v.CanInterface() { 93 fmt.Fprint(w, v.Interface()) 94 } 95 } 96 }