utils.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. package raymond
  2. import (
  3. "path"
  4. "reflect"
  5. )
  6. // indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
  7. // We indirect through pointers and empty interfaces (only) because
  8. // non-empty interfaces have methods we might need.
  9. //
  10. // NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go
  11. func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
  12. for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
  13. if v.IsNil() {
  14. return v, true
  15. }
  16. if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
  17. break
  18. }
  19. }
  20. return v, false
  21. }
  22. // IsTrue returns true if obj is a truthy value.
  23. func IsTrue(obj interface{}) bool {
  24. thruth, ok := isTrueValue(reflect.ValueOf(obj))
  25. if !ok {
  26. return false
  27. }
  28. return thruth
  29. }
  30. // isTrueValue reports whether the value is 'true', in the sense of not the zero of its type,
  31. // and whether the value has a meaningful truth value
  32. //
  33. // NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go
  34. func isTrueValue(val reflect.Value) (truth, ok bool) {
  35. if !val.IsValid() {
  36. // Something like var x interface{}, never set. It's a form of nil.
  37. return false, true
  38. }
  39. switch val.Kind() {
  40. case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
  41. truth = val.Len() > 0
  42. case reflect.Bool:
  43. truth = val.Bool()
  44. case reflect.Complex64, reflect.Complex128:
  45. truth = val.Complex() != 0
  46. case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface:
  47. truth = !val.IsNil()
  48. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  49. truth = val.Int() != 0
  50. case reflect.Float32, reflect.Float64:
  51. truth = val.Float() != 0
  52. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  53. truth = val.Uint() != 0
  54. case reflect.Struct:
  55. truth = true // Struct values are always true.
  56. default:
  57. return
  58. }
  59. return truth, true
  60. }
  61. // canBeNil reports whether an untyped nil can be assigned to the type. See reflect.Zero.
  62. //
  63. // NOTE: borrowed from https://github.com/golang/go/tree/master/src/text/template/exec.go
  64. func canBeNil(typ reflect.Type) bool {
  65. switch typ.Kind() {
  66. case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
  67. return true
  68. }
  69. return false
  70. }
  71. // fileBase returns base file name
  72. //
  73. // example: /foo/bar/baz.png => baz
  74. func fileBase(filePath string) string {
  75. fileName := path.Base(filePath)
  76. fileExt := path.Ext(filePath)
  77. return fileName[:len(fileName)-len(fileExt)]
  78. }