defaults.go 3.6 KB

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