utils.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package packngo
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "reflect"
  7. )
  8. var timestampType = reflect.TypeOf(Timestamp{})
  9. // Stringify creates a string representation of the provided message
  10. func Stringify(message interface{}) string {
  11. var buf bytes.Buffer
  12. v := reflect.ValueOf(message)
  13. stringifyValue(&buf, v)
  14. return buf.String()
  15. }
  16. // String allocates a new string value to store v and returns a pointer to it
  17. func String(v string) *string {
  18. p := new(string)
  19. *p = v
  20. return p
  21. }
  22. // Int allocates a new int32 value to store v and returns a pointer to it, but unlike Int32 its argument value is an int.
  23. func Int(v int) *int {
  24. p := new(int)
  25. *p = v
  26. return p
  27. }
  28. // Bool allocates a new bool value to store v and returns a pointer to it.
  29. func Bool(v bool) *bool {
  30. p := new(bool)
  31. *p = v
  32. return p
  33. }
  34. // StreamToString converts a reader to a string
  35. func StreamToString(stream io.Reader) string {
  36. buf := new(bytes.Buffer)
  37. buf.ReadFrom(stream)
  38. return buf.String()
  39. }
  40. // stringifyValue was graciously cargoculted from the goprotubuf library
  41. func stringifyValue(w io.Writer, val reflect.Value) {
  42. if val.Kind() == reflect.Ptr && val.IsNil() {
  43. w.Write([]byte("<nil>"))
  44. return
  45. }
  46. v := reflect.Indirect(val)
  47. switch v.Kind() {
  48. case reflect.String:
  49. fmt.Fprintf(w, `"%s"`, v)
  50. case reflect.Slice:
  51. w.Write([]byte{'['})
  52. for i := 0; i < v.Len(); i++ {
  53. if i > 0 {
  54. w.Write([]byte{' '})
  55. }
  56. stringifyValue(w, v.Index(i))
  57. }
  58. w.Write([]byte{']'})
  59. return
  60. case reflect.Struct:
  61. if v.Type().Name() != "" {
  62. w.Write([]byte(v.Type().String()))
  63. }
  64. // special handling of Timestamp values
  65. if v.Type() == timestampType {
  66. fmt.Fprintf(w, "{%s}", v.Interface())
  67. return
  68. }
  69. w.Write([]byte{'{'})
  70. var sep bool
  71. for i := 0; i < v.NumField(); i++ {
  72. fv := v.Field(i)
  73. if fv.Kind() == reflect.Ptr && fv.IsNil() {
  74. continue
  75. }
  76. if fv.Kind() == reflect.Slice && fv.IsNil() {
  77. continue
  78. }
  79. if sep {
  80. w.Write([]byte(", "))
  81. } else {
  82. sep = true
  83. }
  84. w.Write([]byte(v.Type().Field(i).Name))
  85. w.Write([]byte{':'})
  86. stringifyValue(w, fv)
  87. }
  88. w.Write([]byte{'}'})
  89. default:
  90. if v.CanInterface() {
  91. fmt.Fprint(w, v.Interface())
  92. }
  93. }
  94. }