strings.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. //
  2. // Copyright 2017, Sander van Harmelen
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. package gitlab
  17. import (
  18. "bytes"
  19. "fmt"
  20. "reflect"
  21. )
  22. // Stringify attempts to create a reasonable string representation of types in
  23. // the GitHub library. It does things like resolve pointers to their values
  24. // and omits struct fields with nil values.
  25. func Stringify(message interface{}) string {
  26. var buf bytes.Buffer
  27. v := reflect.ValueOf(message)
  28. stringifyValue(&buf, v)
  29. return buf.String()
  30. }
  31. // stringifyValue was heavily inspired by the goprotobuf library.
  32. func stringifyValue(buf *bytes.Buffer, val reflect.Value) {
  33. if val.Kind() == reflect.Ptr && val.IsNil() {
  34. buf.WriteString("<nil>")
  35. return
  36. }
  37. v := reflect.Indirect(val)
  38. switch v.Kind() {
  39. case reflect.String:
  40. fmt.Fprintf(buf, `"%s"`, v)
  41. case reflect.Slice:
  42. buf.WriteByte('[')
  43. for i := 0; i < v.Len(); i++ {
  44. if i > 0 {
  45. buf.WriteByte(' ')
  46. }
  47. stringifyValue(buf, v.Index(i))
  48. }
  49. buf.WriteByte(']')
  50. return
  51. case reflect.Struct:
  52. if v.Type().Name() != "" {
  53. buf.WriteString(v.Type().String())
  54. }
  55. buf.WriteByte('{')
  56. var sep bool
  57. for i := 0; i < v.NumField(); i++ {
  58. fv := v.Field(i)
  59. if fv.Kind() == reflect.Ptr && fv.IsNil() {
  60. continue
  61. }
  62. if fv.Kind() == reflect.Slice && fv.IsNil() {
  63. continue
  64. }
  65. if sep {
  66. buf.WriteString(", ")
  67. } else {
  68. sep = true
  69. }
  70. buf.WriteString(v.Type().Field(i).Name)
  71. buf.WriteByte(':')
  72. stringifyValue(buf, fv)
  73. }
  74. buf.WriteByte('}')
  75. default:
  76. if v.CanInterface() {
  77. fmt.Fprint(buf, v.Interface())
  78. }
  79. }
  80. }