...

Source file src/github.com/google/go-github/v55/github/strings.go

Documentation: github.com/google/go-github/v55/github

     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  }
    97  

View as plain text