defaults.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. package sprig
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "math/rand"
  6. "reflect"
  7. "strings"
  8. "time"
  9. )
  10. func init() {
  11. rand.Seed(time.Now().UnixNano())
  12. }
  13. // dfault checks whether `given` is set, and returns default if not set.
  14. //
  15. // This returns `d` if `given` appears not to be set, and `given` otherwise.
  16. //
  17. // For numeric types 0 is unset.
  18. // For strings, maps, arrays, and slices, len() = 0 is considered unset.
  19. // For bool, false is unset.
  20. // Structs are never considered unset.
  21. //
  22. // For everything else, including pointers, a nil value is unset.
  23. func dfault(d interface{}, given ...interface{}) interface{} {
  24. if empty(given) || empty(given[0]) {
  25. return d
  26. }
  27. return given[0]
  28. }
  29. // empty returns true if the given value has the zero value for its type.
  30. func empty(given interface{}) bool {
  31. g := reflect.ValueOf(given)
  32. if !g.IsValid() {
  33. return true
  34. }
  35. // Basically adapted from text/template.isTrue
  36. switch g.Kind() {
  37. default:
  38. return g.IsNil()
  39. case reflect.Array, reflect.Slice, reflect.Map, reflect.String:
  40. return g.Len() == 0
  41. case reflect.Bool:
  42. return !g.Bool()
  43. case reflect.Complex64, reflect.Complex128:
  44. return g.Complex() == 0
  45. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  46. return g.Int() == 0
  47. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  48. return g.Uint() == 0
  49. case reflect.Float32, reflect.Float64:
  50. return g.Float() == 0
  51. case reflect.Struct:
  52. return false
  53. }
  54. }
  55. // coalesce returns the first non-empty value.
  56. func coalesce(v ...interface{}) interface{} {
  57. for _, val := range v {
  58. if !empty(val) {
  59. return val
  60. }
  61. }
  62. return nil
  63. }
  64. // all returns true if empty(x) is false for all values x in the list.
  65. // If the list is empty, return true.
  66. func all(v ...interface{}) bool {
  67. for _, val := range v {
  68. if empty(val) {
  69. return false
  70. }
  71. }
  72. return true
  73. }
  74. // any returns true if empty(x) is false for any x in the list.
  75. // If the list is empty, return false.
  76. func any(v ...interface{}) bool {
  77. for _, val := range v {
  78. if !empty(val) {
  79. return true
  80. }
  81. }
  82. return false
  83. }
  84. // fromJson decodes JSON into a structured value, ignoring errors.
  85. func fromJson(v string) interface{} {
  86. output, _ := mustFromJson(v)
  87. return output
  88. }
  89. // mustFromJson decodes JSON into a structured value, returning errors.
  90. func mustFromJson(v string) (interface{}, error) {
  91. var output interface{}
  92. err := json.Unmarshal([]byte(v), &output)
  93. return output, err
  94. }
  95. // toJson encodes an item into a JSON string
  96. func toJson(v interface{}) string {
  97. output, _ := json.Marshal(v)
  98. return string(output)
  99. }
  100. func mustToJson(v interface{}) (string, error) {
  101. output, err := json.Marshal(v)
  102. if err != nil {
  103. return "", err
  104. }
  105. return string(output), nil
  106. }
  107. // toPrettyJson encodes an item into a pretty (indented) JSON string
  108. func toPrettyJson(v interface{}) string {
  109. output, _ := json.MarshalIndent(v, "", " ")
  110. return string(output)
  111. }
  112. func mustToPrettyJson(v interface{}) (string, error) {
  113. output, err := json.MarshalIndent(v, "", " ")
  114. if err != nil {
  115. return "", err
  116. }
  117. return string(output), nil
  118. }
  119. // toRawJson encodes an item into a JSON string with no escaping of HTML characters.
  120. func toRawJson(v interface{}) string {
  121. output, err := mustToRawJson(v)
  122. if err != nil {
  123. panic(err)
  124. }
  125. return string(output)
  126. }
  127. // mustToRawJson encodes an item into a JSON string with no escaping of HTML characters.
  128. func mustToRawJson(v interface{}) (string, error) {
  129. buf := new(bytes.Buffer)
  130. enc := json.NewEncoder(buf)
  131. enc.SetEscapeHTML(false)
  132. err := enc.Encode(&v)
  133. if err != nil {
  134. return "", err
  135. }
  136. return strings.TrimSuffix(buf.String(), "\n"), nil
  137. }
  138. // ternary returns the first value if the last value is true, otherwise returns the second value.
  139. func ternary(vt interface{}, vf interface{}, v bool) interface{} {
  140. if v {
  141. return vt
  142. }
  143. return vf
  144. }