string.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. package raymond
  2. import (
  3. "fmt"
  4. "reflect"
  5. "strconv"
  6. )
  7. // SafeString represents a string that must not be escaped.
  8. //
  9. // A SafeString can be returned by helpers to disable escaping.
  10. type SafeString string
  11. // isSafeString returns true if argument is a SafeString
  12. func isSafeString(value interface{}) bool {
  13. if _, ok := value.(SafeString); ok {
  14. return true
  15. }
  16. return false
  17. }
  18. // Str returns string representation of any basic type value.
  19. func Str(value interface{}) string {
  20. return strValue(reflect.ValueOf(value))
  21. }
  22. // strValue returns string representation of a reflect.Value
  23. func strValue(value reflect.Value) string {
  24. result := ""
  25. ival, ok := printableValue(value)
  26. if !ok {
  27. panic(fmt.Errorf("Can't print value: %q", value))
  28. }
  29. val := reflect.ValueOf(ival)
  30. switch val.Kind() {
  31. case reflect.Array, reflect.Slice:
  32. for i := 0; i < val.Len(); i++ {
  33. result += strValue(val.Index(i))
  34. }
  35. case reflect.Bool:
  36. result = "false"
  37. if val.Bool() {
  38. result = "true"
  39. }
  40. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  41. result = fmt.Sprintf("%d", ival)
  42. case reflect.Float32, reflect.Float64:
  43. result = strconv.FormatFloat(val.Float(), 'f', -1, 64)
  44. case reflect.Invalid:
  45. result = ""
  46. default:
  47. result = fmt.Sprintf("%s", ival)
  48. }
  49. return result
  50. }
  51. // printableValue returns the, possibly indirected, interface value inside v that
  52. // is best for a call to formatted printer.
  53. //
  54. // NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go
  55. func printableValue(v reflect.Value) (interface{}, bool) {
  56. if v.Kind() == reflect.Ptr {
  57. v, _ = indirect(v) // fmt.Fprint handles nil.
  58. }
  59. if !v.IsValid() {
  60. return "", true
  61. }
  62. if !v.Type().Implements(errorType) && !v.Type().Implements(fmtStringerType) {
  63. if v.CanAddr() && (reflect.PtrTo(v.Type()).Implements(errorType) || reflect.PtrTo(v.Type()).Implements(fmtStringerType)) {
  64. v = v.Addr()
  65. } else {
  66. switch v.Kind() {
  67. case reflect.Chan, reflect.Func:
  68. return nil, false
  69. }
  70. }
  71. }
  72. return v.Interface(), true
  73. }