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