From 2a468493f92a17e626a3b3a48d87ccbc72d3848b Mon Sep 17 00:00:00 2001 From: binwiederhier Date: Sun, 13 Jul 2025 12:45:00 +0200 Subject: [PATCH] any --- util/sprig/date.go | 14 +++--- util/sprig/date_test.go | 34 ++++++------- util/sprig/defaults.go | 33 ++++++------- util/sprig/defaults_test.go | 16 +++--- util/sprig/dict.go | 39 +++++++-------- util/sprig/example_test.go | 2 +- util/sprig/functions.go | 74 +++++++-------------------- util/sprig/functions_test.go | 4 +- util/sprig/list.go | 96 ++++++++++++++++++------------------ util/sprig/numeric.go | 22 ++++----- util/sprig/numeric_test.go | 2 +- util/sprig/reflect.go | 10 ++-- util/sprig/strings.go | 18 +++---- util/sprig/strings_test.go | 16 +++--- util/sprig/url.go | 8 +-- util/sprig/url_test.go | 2 +- 16 files changed, 174 insertions(+), 216 deletions(-) diff --git a/util/sprig/date.go b/util/sprig/date.go index ed022dda..3fed04e9 100644 --- a/util/sprig/date.go +++ b/util/sprig/date.go @@ -10,19 +10,19 @@ import ( // Date can be a `time.Time` or an `int, int32, int64`. // In the later case, it is treated as seconds since UNIX // epoch. -func date(fmt string, date interface{}) string { +func date(fmt string, date any) string { return dateInZone(fmt, date, "Local") } -func htmlDate(date interface{}) string { +func htmlDate(date any) string { return dateInZone("2006-01-02", date, "Local") } -func htmlDateInZone(date interface{}, zone string) string { +func htmlDateInZone(date any, zone string) string { return dateInZone("2006-01-02", date, zone) } -func dateInZone(fmt string, date interface{}, zone string) string { +func dateInZone(fmt string, date any, zone string) string { var t time.Time switch date := date.(type) { default: @@ -63,7 +63,7 @@ func mustDateModify(fmt string, date time.Time) (time.Time, error) { return date.Add(d), nil } -func dateAgo(date interface{}) string { +func dateAgo(date any) string { var t time.Time switch date := date.(type) { @@ -81,7 +81,7 @@ func dateAgo(date interface{}) string { return duration.String() } -func duration(sec interface{}) string { +func duration(sec any) string { var n int64 switch value := sec.(type) { default: @@ -94,7 +94,7 @@ func duration(sec interface{}) string { return (time.Duration(n) * time.Second).String() } -func durationRound(duration interface{}) string { +func durationRound(duration any) string { var d time.Duration switch duration := duration.(type) { default: diff --git a/util/sprig/date_test.go b/util/sprig/date_test.go index be7ec9d9..3ebfa2be 100644 --- a/util/sprig/date_test.go +++ b/util/sprig/date_test.go @@ -15,15 +15,15 @@ func TestHtmlDate(t *testing.T) { func TestAgo(t *testing.T) { tpl := "{{ ago .Time }}" - if err := runtv(tpl, "2m5s", map[string]interface{}{"Time": time.Now().Add(-125 * time.Second)}); err != nil { + if err := runtv(tpl, "2m5s", map[string]any{"Time": time.Now().Add(-125 * time.Second)}); err != nil { t.Error(err) } - if err := runtv(tpl, "2h34m17s", map[string]interface{}{"Time": time.Now().Add(-(2*3600 + 34*60 + 17) * time.Second)}); err != nil { + if err := runtv(tpl, "2h34m17s", map[string]any{"Time": time.Now().Add(-(2*3600 + 34*60 + 17) * time.Second)}); err != nil { t.Error(err) } - if err := runtv(tpl, "-5s", map[string]interface{}{"Time": time.Now().Add(5 * time.Second)}); err != nil { + if err := runtv(tpl, "-5s", map[string]any{"Time": time.Now().Add(5 * time.Second)}); err != nil { t.Error(err) } } @@ -42,7 +42,7 @@ func TestUnixEpoch(t *testing.T) { } tpl := `{{unixEpoch .Time}}` - if err = runtv(tpl, "1560458379", map[string]interface{}{"Time": tm}); err != nil { + if err = runtv(tpl, "1560458379", map[string]any{"Time": tm}); err != nil { t.Error(err) } } @@ -55,66 +55,66 @@ func TestDateInZone(t *testing.T) { tpl := `{{ date_in_zone "02 Jan 06 15:04 -0700" .Time "UTC" }}` // Test time.Time input - if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": tm}); err != nil { + if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": tm}); err != nil { t.Error(err) } // Test pointer to time.Time input - if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": &tm}); err != nil { + if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": &tm}); err != nil { t.Error(err) } // Test no time input. This should be close enough to time.Now() we can test loc, _ := time.LoadLocation("UTC") - if err = runtv(tpl, time.Now().In(loc).Format("02 Jan 06 15:04 -0700"), map[string]interface{}{"Time": ""}); err != nil { + if err = runtv(tpl, time.Now().In(loc).Format("02 Jan 06 15:04 -0700"), map[string]any{"Time": ""}); err != nil { t.Error(err) } // Test unix timestamp as int64 - if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": int64(1560458379)}); err != nil { + if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": int64(1560458379)}); err != nil { t.Error(err) } // Test unix timestamp as int32 - if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": int32(1560458379)}); err != nil { + if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": int32(1560458379)}); err != nil { t.Error(err) } // Test unix timestamp as int - if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": int(1560458379)}); err != nil { + if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": int(1560458379)}); err != nil { t.Error(err) } // Test case of invalid timezone tpl = `{{ date_in_zone "02 Jan 06 15:04 -0700" .Time "foobar" }}` - if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]interface{}{"Time": tm}); err != nil { + if err = runtv(tpl, "13 Jun 19 20:39 +0000", map[string]any{"Time": tm}); err != nil { t.Error(err) } } func TestDuration(t *testing.T) { tpl := "{{ duration .Secs }}" - if err := runtv(tpl, "1m1s", map[string]interface{}{"Secs": "61"}); err != nil { + if err := runtv(tpl, "1m1s", map[string]any{"Secs": "61"}); err != nil { t.Error(err) } - if err := runtv(tpl, "1h0m0s", map[string]interface{}{"Secs": "3600"}); err != nil { + if err := runtv(tpl, "1h0m0s", map[string]any{"Secs": "3600"}); err != nil { t.Error(err) } // 1d2h3m4s but go is opinionated - if err := runtv(tpl, "26h3m4s", map[string]interface{}{"Secs": "93784"}); err != nil { + if err := runtv(tpl, "26h3m4s", map[string]any{"Secs": "93784"}); err != nil { t.Error(err) } } func TestDurationRound(t *testing.T) { tpl := "{{ durationRound .Time }}" - if err := runtv(tpl, "2h", map[string]interface{}{"Time": "2h5s"}); err != nil { + if err := runtv(tpl, "2h", map[string]any{"Time": "2h5s"}); err != nil { t.Error(err) } - if err := runtv(tpl, "1d", map[string]interface{}{"Time": "24h5s"}); err != nil { + if err := runtv(tpl, "1d", map[string]any{"Time": "24h5s"}); err != nil { t.Error(err) } - if err := runtv(tpl, "3mo", map[string]interface{}{"Time": "2400h5s"}); err != nil { + if err := runtv(tpl, "3mo", map[string]any{"Time": "2400h5s"}); err != nil { t.Error(err) } } diff --git a/util/sprig/defaults.go b/util/sprig/defaults.go index 6a828a2a..7dcf7450 100644 --- a/util/sprig/defaults.go +++ b/util/sprig/defaults.go @@ -17,7 +17,7 @@ import ( // Structs are never considered unset. // // For everything else, including pointers, a nil value is unset. -func dfault(d interface{}, given ...interface{}) interface{} { +func dfault(d any, given ...any) any { if empty(given) || empty(given[0]) { return d @@ -26,7 +26,7 @@ func dfault(d interface{}, given ...interface{}) interface{} { } // empty returns true if the given value has the zero value for its type. -func empty(given interface{}) bool { +func empty(given any) bool { g := reflect.ValueOf(given) if !g.IsValid() { return true @@ -54,7 +54,7 @@ func empty(given interface{}) bool { } // coalesce returns the first non-empty value. -func coalesce(v ...interface{}) interface{} { +func coalesce(v ...any) any { for _, val := range v { if !empty(val) { return val @@ -65,7 +65,7 @@ func coalesce(v ...interface{}) interface{} { // all returns true if empty(x) is false for all values x in the list. // If the list is empty, return true. -func all(v ...interface{}) bool { +func all(v ...any) bool { for _, val := range v { if empty(val) { return false @@ -74,9 +74,9 @@ func all(v ...interface{}) bool { return true } -// any returns true if empty(x) is false for any x in the list. +// anyNonEmpty returns true if empty(x) is false for anyNonEmpty x in the list. // If the list is empty, return false. -func any(v ...interface{}) bool { +func anyNonEmpty(v ...any) bool { for _, val := range v { if !empty(val) { return true @@ -86,25 +86,25 @@ func any(v ...interface{}) bool { } // fromJSON decodes JSON into a structured value, ignoring errors. -func fromJSON(v string) interface{} { +func fromJSON(v string) any { output, _ := mustFromJSON(v) return output } // mustFromJSON decodes JSON into a structured value, returning errors. -func mustFromJSON(v string) (interface{}, error) { - var output interface{} +func mustFromJSON(v string) (any, error) { + var output any err := json.Unmarshal([]byte(v), &output) return output, err } // toJSON encodes an item into a JSON string -func toJSON(v interface{}) string { +func toJSON(v any) string { output, _ := json.Marshal(v) return string(output) } -func mustToJSON(v interface{}) (string, error) { +func mustToJSON(v any) (string, error) { output, err := json.Marshal(v) if err != nil { return "", err @@ -113,12 +113,12 @@ func mustToJSON(v interface{}) (string, error) { } // toPrettyJSON encodes an item into a pretty (indented) JSON string -func toPrettyJSON(v interface{}) string { +func toPrettyJSON(v any) string { output, _ := json.MarshalIndent(v, "", " ") return string(output) } -func mustToPrettyJSON(v interface{}) (string, error) { +func mustToPrettyJSON(v any) (string, error) { output, err := json.MarshalIndent(v, "", " ") if err != nil { return "", err @@ -127,7 +127,7 @@ func mustToPrettyJSON(v interface{}) (string, error) { } // toRawJSON encodes an item into a JSON string with no escaping of HTML characters. -func toRawJSON(v interface{}) string { +func toRawJSON(v any) string { output, err := mustToRawJSON(v) if err != nil { panic(err) @@ -136,7 +136,7 @@ func toRawJSON(v interface{}) string { } // mustToRawJSON encodes an item into a JSON string with no escaping of HTML characters. -func mustToRawJSON(v interface{}) (string, error) { +func mustToRawJSON(v any) (string, error) { buf := new(bytes.Buffer) enc := json.NewEncoder(buf) enc.SetEscapeHTML(false) @@ -148,10 +148,9 @@ func mustToRawJSON(v interface{}) (string, error) { } // ternary returns the first value if the last value is true, otherwise returns the second value. -func ternary(vt interface{}, vf interface{}, v bool) interface{} { +func ternary(vt any, vf any, v bool) any { if v { return vt } - return vf } diff --git a/util/sprig/defaults_test.go b/util/sprig/defaults_test.go index eb7e35b4..f67c9cd9 100644 --- a/util/sprig/defaults_test.go +++ b/util/sprig/defaults_test.go @@ -53,7 +53,7 @@ func TestEmpty(t *testing.T) { t.Error(err) } - dict := map[string]interface{}{"top": map[string]interface{}{}} + dict := map[string]any{"top": map[string]any{}} tpl = `{{if empty .top.NoSuchThing}}1{{else}}0{{end}}` if err := runtv(tpl, "1", dict); err != nil { t.Error(err) @@ -77,7 +77,7 @@ func TestCoalesce(t *testing.T) { assert.NoError(t, runt(tpl, expect)) } - dict := map[string]interface{}{"top": map[string]interface{}{}} + dict := map[string]any{"top": map[string]any{}} tpl := `{{ coalesce .top.NoSuchThing .bottom .bottom.dollar "airplane"}}` if err := runtv(tpl, "airplane", dict); err != nil { t.Error(err) @@ -97,7 +97,7 @@ func TestAll(t *testing.T) { assert.NoError(t, runt(tpl, expect)) } - dict := map[string]interface{}{"top": map[string]interface{}{}} + dict := map[string]any{"top": map[string]any{}} tpl := `{{ all .top.NoSuchThing .bottom .bottom.dollar "airplane"}}` if err := runtv(tpl, "false", dict); err != nil { t.Error(err) @@ -117,7 +117,7 @@ func TestAny(t *testing.T) { assert.NoError(t, runt(tpl, expect)) } - dict := map[string]interface{}{"top": map[string]interface{}{}} + dict := map[string]any{"top": map[string]any{}} tpl := `{{ any .top.NoSuchThing .bottom .bottom.dollar "airplane"}}` if err := runtv(tpl, "true", dict); err != nil { t.Error(err) @@ -125,7 +125,7 @@ func TestAny(t *testing.T) { } func TestFromJSON(t *testing.T) { - dict := map[string]interface{}{"Input": `{"foo": 55}`} + dict := map[string]any{"Input": `{"foo": 55}`} tpl := `{{.Input | fromJSON}}` expected := `map[foo:55]` @@ -141,7 +141,7 @@ func TestFromJSON(t *testing.T) { } func TestToJSON(t *testing.T) { - dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42}} + dict := map[string]any{"Top": map[string]any{"bool": true, "string": "test", "number": 42}} tpl := `{{.Top | toJSON}}` expected := `{"bool":true,"number":42,"string":"test"}` @@ -151,7 +151,7 @@ func TestToJSON(t *testing.T) { } func TestToPrettyJSON(t *testing.T) { - dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42}} + dict := map[string]any{"Top": map[string]any{"bool": true, "string": "test", "number": 42}} tpl := `{{.Top | toPrettyJSON}}` expected := `{ "bool": true, @@ -164,7 +164,7 @@ func TestToPrettyJSON(t *testing.T) { } func TestToRawJSON(t *testing.T) { - dict := map[string]interface{}{"Top": map[string]interface{}{"bool": true, "string": "test", "number": 42, "html": ""}} + dict := map[string]any{"Top": map[string]any{"bool": true, "string": "test", "number": 42, "html": ""}} tpl := `{{.Top | toRawJSON}}` expected := `{"bool":true,"html":"","number":42,"string":"test"}` diff --git a/util/sprig/dict.go b/util/sprig/dict.go index fd2dd711..97182a97 100644 --- a/util/sprig/dict.go +++ b/util/sprig/dict.go @@ -1,29 +1,29 @@ package sprig -func get(d map[string]interface{}, key string) interface{} { +func get(d map[string]any, key string) any { if val, ok := d[key]; ok { return val } return "" } -func set(d map[string]interface{}, key string, value interface{}) map[string]interface{} { +func set(d map[string]any, key string, value any) map[string]any { d[key] = value return d } -func unset(d map[string]interface{}, key string) map[string]interface{} { +func unset(d map[string]any, key string) map[string]any { delete(d, key) return d } -func hasKey(d map[string]interface{}, key string) bool { +func hasKey(d map[string]any, key string) bool { _, ok := d[key] return ok } -func pluck(key string, d ...map[string]interface{}) []interface{} { - res := []interface{}{} +func pluck(key string, d ...map[string]any) []any { + var res []any for _, dict := range d { if val, ok := dict[key]; ok { res = append(res, val) @@ -32,7 +32,7 @@ func pluck(key string, d ...map[string]interface{}) []interface{} { return res } -func keys(dicts ...map[string]interface{}) []string { +func keys(dicts ...map[string]any) []string { k := []string{} for _, dict := range dicts { for key := range dict { @@ -42,8 +42,8 @@ func keys(dicts ...map[string]interface{}) []string { return k } -func pick(dict map[string]interface{}, keys ...string) map[string]interface{} { - res := map[string]interface{}{} +func pick(dict map[string]any, keys ...string) map[string]any { + res := map[string]any{} for _, k := range keys { if v, ok := dict[k]; ok { res[k] = v @@ -52,8 +52,8 @@ func pick(dict map[string]interface{}, keys ...string) map[string]interface{} { return res } -func omit(dict map[string]interface{}, keys ...string) map[string]interface{} { - res := map[string]interface{}{} +func omit(dict map[string]any, keys ...string) map[string]any { + res := map[string]any{} omit := make(map[string]bool, len(keys)) for _, k := range keys { @@ -68,8 +68,8 @@ func omit(dict map[string]interface{}, keys ...string) map[string]interface{} { return res } -func dict(v ...interface{}) map[string]interface{} { - dict := map[string]interface{}{} +func dict(v ...any) map[string]any { + dict := map[string]any{} lenv := len(v) for i := 0; i < lenv; i += 2 { key := strval(v[i]) @@ -82,20 +82,19 @@ func dict(v ...interface{}) map[string]interface{} { return dict } -func values(dict map[string]interface{}) []interface{} { - values := []interface{}{} +func values(dict map[string]any) []any { + var values []any for _, value := range dict { values = append(values, value) } - return values } -func dig(ps ...interface{}) (interface{}, error) { +func dig(ps ...any) (any, error) { if len(ps) < 3 { panic("dig needs at least three arguments") } - dict := ps[len(ps)-1].(map[string]interface{}) + dict := ps[len(ps)-1].(map[string]any) def := ps[len(ps)-2] ks := make([]string, len(ps)-2) for i := 0; i < len(ks); i++ { @@ -105,7 +104,7 @@ func dig(ps ...interface{}) (interface{}, error) { return digFromDict(dict, def, ks) } -func digFromDict(dict map[string]interface{}, d interface{}, ks []string) (interface{}, error) { +func digFromDict(dict map[string]any, d any, ks []string) (any, error) { k, ns := ks[0], ks[1:] step, has := dict[k] if !has { @@ -114,5 +113,5 @@ func digFromDict(dict map[string]interface{}, d interface{}, ks []string) (inter if len(ns) == 0 { return step, nil } - return digFromDict(step.(map[string]interface{}), d, ns) + return digFromDict(step.(map[string]any), d, ns) } diff --git a/util/sprig/example_test.go b/util/sprig/example_test.go index 2d7696bf..2f1b74c8 100644 --- a/util/sprig/example_test.go +++ b/util/sprig/example_test.go @@ -8,7 +8,7 @@ import ( func Example() { // Set up variables and template. - vars := map[string]interface{}{"Name": " John Jacob Jingleheimer Schmidt "} + vars := map[string]any{"Name": " John Jacob Jingleheimer Schmidt "} tpl := `Hello {{.Name | trim | lower}}` // Get the Sprig function map. diff --git a/util/sprig/functions.go b/util/sprig/functions.go index 3ea46924..68ef516d 100644 --- a/util/sprig/functions.go +++ b/util/sprig/functions.go @@ -24,68 +24,26 @@ func FuncMap() template.FuncMap { return HTMLFuncMap() } -// HermeticTxtFuncMap returns a 'text/template'.FuncMap with only repeatable functions. -func HermeticTxtFuncMap() ttemplate.FuncMap { - r := TxtFuncMap() - for _, name := range nonhermeticFunctions { - delete(r, name) - } - return r -} - -// HermeticHTMLFuncMap returns an 'html/template'.Funcmap with only repeatable functions. -func HermeticHTMLFuncMap() template.FuncMap { - r := HTMLFuncMap() - for _, name := range nonhermeticFunctions { - delete(r, name) - } - return r -} - // TxtFuncMap returns a 'text/template'.FuncMap func TxtFuncMap() ttemplate.FuncMap { - return ttemplate.FuncMap(GenericFuncMap()) + return GenericFuncMap() } // HTMLFuncMap returns an 'html/template'.Funcmap func HTMLFuncMap() template.FuncMap { - return template.FuncMap(GenericFuncMap()) + return GenericFuncMap() } -// GenericFuncMap returns a copy of the basic function map as a map[string]interface{}. -func GenericFuncMap() map[string]interface{} { - gfm := make(map[string]interface{}, len(genericMap)) +// GenericFuncMap returns a copy of the basic function map as a map[string]any. +func GenericFuncMap() map[string]any { + gfm := make(map[string]any, len(genericMap)) for k, v := range genericMap { gfm[k] = v } return gfm } -// These functions are not guaranteed to evaluate to the same result for given input, because they -// refer to the environment or global state. -var nonhermeticFunctions = []string{ - // Date functions - "date", - "date_in_zone", - "date_modify", - "now", - "htmlDate", - "htmlDateInZone", - "dateInZone", - "dateModify", - - // Strings - "randAlphaNum", - "randAlpha", - "randAscii", - "randNumeric", - "randBytes", - "uuidv4", -} - -var genericMap = map[string]interface{}{ - "hello": func() string { return "Hello!" }, - +var genericMap = map[string]any{ // Date functions "ago": dateAgo, "date": date, @@ -157,18 +115,18 @@ var genericMap = map[string]interface{}{ "untilStep": untilStep, // VERY basic arithmetic. - "add1": func(i interface{}) int64 { return toInt64(i) + 1 }, - "add": func(i ...interface{}) int64 { + "add1": func(i any) int64 { return toInt64(i) + 1 }, + "add": func(i ...any) int64 { var a int64 = 0 for _, b := range i { a += toInt64(b) } return a }, - "sub": func(a, b interface{}) int64 { return toInt64(a) - toInt64(b) }, - "div": func(a, b interface{}) int64 { return toInt64(a) / toInt64(b) }, - "mod": func(a, b interface{}) int64 { return toInt64(a) % toInt64(b) }, - "mul": func(a interface{}, v ...interface{}) int64 { + "sub": func(a, b any) int64 { return toInt64(a) - toInt64(b) }, + "div": func(a, b any) int64 { return toInt64(a) / toInt64(b) }, + "mod": func(a, b any) int64 { return toInt64(a) % toInt64(b) }, + "mul": func(a any, v ...any) int64 { val := toInt64(a) for _, b := range v { val = val * toInt64(b) @@ -195,7 +153,7 @@ var genericMap = map[string]interface{}{ "empty": empty, "coalesce": coalesce, "all": all, - "any": any, + "any": anyNonEmpty, "compact": compact, "mustCompact": mustCompact, "fromJSON": fromJSON, @@ -250,8 +208,10 @@ var genericMap = map[string]interface{}{ "omit": omit, "values": values, - "append": push, "push": push, - "mustAppend": mustPush, "mustPush": mustPush, + "append": push, + "push": push, + "mustAppend": mustPush, + "mustPush": mustPush, "prepend": prepend, "mustPrepend": mustPrepend, "first": first, diff --git a/util/sprig/functions_test.go b/util/sprig/functions_test.go index b7bc01f4..e5989b98 100644 --- a/util/sprig/functions_test.go +++ b/util/sprig/functions_test.go @@ -43,7 +43,7 @@ func runt(tpl, expect string) error { // runtv takes a template, and expected return, and values for substitution. // // It runs the template and verifies that the output is an exact match. -func runtv(tpl, expect string, vars interface{}) error { +func runtv(tpl, expect string, vars any) error { fmap := TxtFuncMap() t := template.Must(template.New("test").Funcs(fmap).Parse(tpl)) var b bytes.Buffer @@ -58,7 +58,7 @@ func runtv(tpl, expect string, vars interface{}) error { } // runRaw runs a template with the given variables and returns the result. -func runRaw(tpl string, vars interface{}) (string, error) { +func runRaw(tpl string, vars any) (string, error) { fmap := TxtFuncMap() t := template.Must(template.New("test").Funcs(fmap).Parse(tpl)) var b bytes.Buffer diff --git a/util/sprig/list.go b/util/sprig/list.go index f4e95dda..138ecfa5 100644 --- a/util/sprig/list.go +++ b/util/sprig/list.go @@ -8,14 +8,14 @@ import ( ) // Reflection is used in these functions so that slices and arrays of strings, -// ints, and other types not implementing []interface{} can be worked with. +// ints, and other types not implementing []any can be worked with. // For example, this is useful if you need to work on the output of regexs. -func list(v ...interface{}) []interface{} { +func list(v ...any) []any { return v } -func push(list interface{}, v interface{}) []interface{} { +func push(list any, v any) []any { l, err := mustPush(list, v) if err != nil { panic(err) @@ -24,14 +24,14 @@ func push(list interface{}, v interface{}) []interface{} { return l } -func mustPush(list interface{}, v interface{}) ([]interface{}, error) { +func mustPush(list any, v any) ([]any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: l2 := reflect.ValueOf(list) l := l2.Len() - nl := make([]interface{}, l) + nl := make([]any, l) for i := 0; i < l; i++ { nl[i] = l2.Index(i).Interface() } @@ -43,7 +43,7 @@ func mustPush(list interface{}, v interface{}) ([]interface{}, error) { } } -func prepend(list interface{}, v interface{}) []interface{} { +func prepend(list any, v any) []any { l, err := mustPrepend(list, v) if err != nil { panic(err) @@ -52,8 +52,8 @@ func prepend(list interface{}, v interface{}) []interface{} { return l } -func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) { - //return append([]interface{}{v}, list...) +func mustPrepend(list any, v any) ([]any, error) { + //return append([]any{v}, list...) tp := reflect.TypeOf(list).Kind() switch tp { @@ -61,19 +61,19 @@ func mustPrepend(list interface{}, v interface{}) ([]interface{}, error) { l2 := reflect.ValueOf(list) l := l2.Len() - nl := make([]interface{}, l) + nl := make([]any, l) for i := 0; i < l; i++ { nl[i] = l2.Index(i).Interface() } - return append([]interface{}{v}, nl...), nil + return append([]any{v}, nl...), nil default: return nil, fmt.Errorf("cannot prepend on type %s", tp) } } -func chunk(size int, list interface{}) [][]interface{} { +func chunk(size int, list any) [][]any { l, err := mustChunk(size, list) if err != nil { panic(err) @@ -82,7 +82,7 @@ func chunk(size int, list interface{}) [][]interface{} { return l } -func mustChunk(size int, list interface{}) ([][]interface{}, error) { +func mustChunk(size int, list any) ([][]any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: @@ -91,7 +91,7 @@ func mustChunk(size int, list interface{}) ([][]interface{}, error) { l := l2.Len() cs := int(math.Floor(float64(l-1)/float64(size)) + 1) - nl := make([][]interface{}, cs) + nl := make([][]any, cs) for i := 0; i < cs; i++ { clen := size @@ -102,7 +102,7 @@ func mustChunk(size int, list interface{}) ([][]interface{}, error) { } } - nl[i] = make([]interface{}, clen) + nl[i] = make([]any, clen) for j := 0; j < clen; j++ { ix := i*size + j @@ -117,7 +117,7 @@ func mustChunk(size int, list interface{}) ([][]interface{}, error) { } } -func last(list interface{}) interface{} { +func last(list any) any { l, err := mustLast(list) if err != nil { panic(err) @@ -126,7 +126,7 @@ func last(list interface{}) interface{} { return l } -func mustLast(list interface{}) (interface{}, error) { +func mustLast(list any) (any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: @@ -143,7 +143,7 @@ func mustLast(list interface{}) (interface{}, error) { } } -func first(list interface{}) interface{} { +func first(list any) any { l, err := mustFirst(list) if err != nil { panic(err) @@ -152,7 +152,7 @@ func first(list interface{}) interface{} { return l } -func mustFirst(list interface{}) (interface{}, error) { +func mustFirst(list any) (any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: @@ -169,7 +169,7 @@ func mustFirst(list interface{}) (interface{}, error) { } } -func rest(list interface{}) []interface{} { +func rest(list any) []any { l, err := mustRest(list) if err != nil { panic(err) @@ -178,7 +178,7 @@ func rest(list interface{}) []interface{} { return l } -func mustRest(list interface{}) ([]interface{}, error) { +func mustRest(list any) ([]any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: @@ -189,7 +189,7 @@ func mustRest(list interface{}) ([]interface{}, error) { return nil, nil } - nl := make([]interface{}, l-1) + nl := make([]any, l-1) for i := 1; i < l; i++ { nl[i-1] = l2.Index(i).Interface() } @@ -200,7 +200,7 @@ func mustRest(list interface{}) ([]interface{}, error) { } } -func initial(list interface{}) []interface{} { +func initial(list any) []any { l, err := mustInitial(list) if err != nil { panic(err) @@ -209,7 +209,7 @@ func initial(list interface{}) []interface{} { return l } -func mustInitial(list interface{}) ([]interface{}, error) { +func mustInitial(list any) ([]any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: @@ -220,7 +220,7 @@ func mustInitial(list interface{}) ([]interface{}, error) { return nil, nil } - nl := make([]interface{}, l-1) + nl := make([]any, l-1) for i := 0; i < l-1; i++ { nl[i] = l2.Index(i).Interface() } @@ -231,7 +231,7 @@ func mustInitial(list interface{}) ([]interface{}, error) { } } -func sortAlpha(list interface{}) []string { +func sortAlpha(list any) []string { k := reflect.Indirect(reflect.ValueOf(list)).Kind() switch k { case reflect.Slice, reflect.Array: @@ -243,7 +243,7 @@ func sortAlpha(list interface{}) []string { return []string{strval(list)} } -func reverse(v interface{}) []interface{} { +func reverse(v any) []any { l, err := mustReverse(v) if err != nil { panic(err) @@ -252,7 +252,7 @@ func reverse(v interface{}) []interface{} { return l } -func mustReverse(v interface{}) ([]interface{}, error) { +func mustReverse(v any) ([]any, error) { tp := reflect.TypeOf(v).Kind() switch tp { case reflect.Slice, reflect.Array: @@ -260,7 +260,7 @@ func mustReverse(v interface{}) ([]interface{}, error) { l := l2.Len() // We do not sort in place because the incoming array should not be altered. - nl := make([]interface{}, l) + nl := make([]any, l) for i := 0; i < l; i++ { nl[l-i-1] = l2.Index(i).Interface() } @@ -271,7 +271,7 @@ func mustReverse(v interface{}) ([]interface{}, error) { } } -func compact(list interface{}) []interface{} { +func compact(list any) []any { l, err := mustCompact(list) if err != nil { panic(err) @@ -280,15 +280,15 @@ func compact(list interface{}) []interface{} { return l } -func mustCompact(list interface{}) ([]interface{}, error) { +func mustCompact(list any) ([]any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: l2 := reflect.ValueOf(list) l := l2.Len() - nl := []interface{}{} - var item interface{} + nl := []any{} + var item any for i := 0; i < l; i++ { item = l2.Index(i).Interface() if !empty(item) { @@ -302,7 +302,7 @@ func mustCompact(list interface{}) ([]interface{}, error) { } } -func uniq(list interface{}) []interface{} { +func uniq(list any) []any { l, err := mustUniq(list) if err != nil { panic(err) @@ -311,15 +311,15 @@ func uniq(list interface{}) []interface{} { return l } -func mustUniq(list interface{}) ([]interface{}, error) { +func mustUniq(list any) ([]any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: l2 := reflect.ValueOf(list) l := l2.Len() - dest := []interface{}{} - var item interface{} + dest := []any{} + var item any for i := 0; i < l; i++ { item = l2.Index(i).Interface() if !inList(dest, item) { @@ -333,7 +333,7 @@ func mustUniq(list interface{}) ([]interface{}, error) { } } -func inList(haystack []interface{}, needle interface{}) bool { +func inList(haystack []any, needle any) bool { for _, h := range haystack { if reflect.DeepEqual(needle, h) { return true @@ -342,7 +342,7 @@ func inList(haystack []interface{}, needle interface{}) bool { return false } -func without(list interface{}, omit ...interface{}) []interface{} { +func without(list any, omit ...any) []any { l, err := mustWithout(list, omit...) if err != nil { panic(err) @@ -351,15 +351,15 @@ func without(list interface{}, omit ...interface{}) []interface{} { return l } -func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) { +func mustWithout(list any, omit ...any) ([]any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: l2 := reflect.ValueOf(list) l := l2.Len() - res := []interface{}{} - var item interface{} + res := []any{} + var item any for i := 0; i < l; i++ { item = l2.Index(i).Interface() if !inList(omit, item) { @@ -373,7 +373,7 @@ func mustWithout(list interface{}, omit ...interface{}) ([]interface{}, error) { } } -func has(needle interface{}, haystack interface{}) bool { +func has(needle any, haystack any) bool { l, err := mustHas(needle, haystack) if err != nil { panic(err) @@ -382,7 +382,7 @@ func has(needle interface{}, haystack interface{}) bool { return l } -func mustHas(needle interface{}, haystack interface{}) (bool, error) { +func mustHas(needle any, haystack any) (bool, error) { if haystack == nil { return false, nil } @@ -390,7 +390,7 @@ func mustHas(needle interface{}, haystack interface{}) (bool, error) { switch tp { case reflect.Slice, reflect.Array: l2 := reflect.ValueOf(haystack) - var item interface{} + var item any l := l2.Len() for i := 0; i < l; i++ { item = l2.Index(i).Interface() @@ -410,7 +410,7 @@ func mustHas(needle interface{}, haystack interface{}) (bool, error) { // slice $list 0 3 -> list[0:3] = list[:3] // slice $list 3 5 -> list[3:5] // slice $list 3 -> list[3:5] = list[3:] -func slice(list interface{}, indices ...interface{}) interface{} { +func slice(list any, indices ...any) any { l, err := mustSlice(list, indices...) if err != nil { panic(err) @@ -419,7 +419,7 @@ func slice(list interface{}, indices ...interface{}) interface{} { return l } -func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) { +func mustSlice(list any, indices ...any) (any, error) { tp := reflect.TypeOf(list).Kind() switch tp { case reflect.Slice, reflect.Array: @@ -446,8 +446,8 @@ func mustSlice(list interface{}, indices ...interface{}) (interface{}, error) { } } -func concat(lists ...interface{}) interface{} { - var res []interface{} +func concat(lists ...any) any { + var res []any for _, list := range lists { tp := reflect.TypeOf(list).Kind() switch tp { diff --git a/util/sprig/numeric.go b/util/sprig/numeric.go index 0b23cd21..e41f61f5 100644 --- a/util/sprig/numeric.go +++ b/util/sprig/numeric.go @@ -9,7 +9,7 @@ import ( ) // toFloat64 converts 64-bit floats -func toFloat64(v interface{}) float64 { +func toFloat64(v any) float64 { if str, ok := v.(string); ok { iv, err := strconv.ParseFloat(str, 64) if err != nil { @@ -38,13 +38,13 @@ func toFloat64(v interface{}) float64 { } } -func toInt(v interface{}) int { +func toInt(v any) int { // It's not optimal. But I don't want duplicate toInt64 code. return int(toInt64(v)) } // toInt64 converts integer types to 64-bit integers -func toInt64(v interface{}) int64 { +func toInt64(v any) int64 { if str, ok := v.(string); ok { iv, err := strconv.ParseInt(str, 10, 64) if err != nil { @@ -78,7 +78,7 @@ func toInt64(v interface{}) int64 { } } -func max(a interface{}, i ...interface{}) int64 { +func max(a any, i ...any) int64 { aa := toInt64(a) for _, b := range i { bb := toInt64(b) @@ -89,7 +89,7 @@ func max(a interface{}, i ...interface{}) int64 { return aa } -func maxf(a interface{}, i ...interface{}) float64 { +func maxf(a any, i ...any) float64 { aa := toFloat64(a) for _, b := range i { bb := toFloat64(b) @@ -98,7 +98,7 @@ func maxf(a interface{}, i ...interface{}) float64 { return aa } -func min(a interface{}, i ...interface{}) int64 { +func min(a any, i ...any) int64 { aa := toInt64(a) for _, b := range i { bb := toInt64(b) @@ -109,7 +109,7 @@ func min(a interface{}, i ...interface{}) int64 { return aa } -func minf(a interface{}, i ...interface{}) float64 { +func minf(a any, i ...any) float64 { aa := toFloat64(a) for _, b := range i { bb := toFloat64(b) @@ -148,17 +148,17 @@ func untilStep(start, stop, step int) []int { return v } -func floor(a interface{}) float64 { +func floor(a any) float64 { aa := toFloat64(a) return math.Floor(aa) } -func ceil(a interface{}) float64 { +func ceil(a any) float64 { aa := toFloat64(a) return math.Ceil(aa) } -func round(a interface{}, p int, rOpt ...float64) float64 { +func round(a any, p int, rOpt ...float64) float64 { roundOn := .5 if len(rOpt) > 0 { roundOn = rOpt[0] @@ -179,7 +179,7 @@ func round(a interface{}, p int, rOpt ...float64) float64 { } // converts unix octal to decimal -func toDecimal(v interface{}) int64 { +func toDecimal(v any) int64 { result, err := strconv.ParseInt(fmt.Sprint(v), 8, 64) if err != nil { return 0 diff --git a/util/sprig/numeric_test.go b/util/sprig/numeric_test.go index 573873d8..63310c52 100644 --- a/util/sprig/numeric_test.go +++ b/util/sprig/numeric_test.go @@ -192,7 +192,7 @@ func TestToInt(t *testing.T) { } func TestToDecimal(t *testing.T) { - tests := map[interface{}]int64{ + tests := map[any]int64{ "777": 511, 777: 511, 770: 504, diff --git a/util/sprig/reflect.go b/util/sprig/reflect.go index 8a65c132..5e37f64f 100644 --- a/util/sprig/reflect.go +++ b/util/sprig/reflect.go @@ -6,23 +6,23 @@ import ( ) // typeIs returns true if the src is the type named in target. -func typeIs(target string, src interface{}) bool { +func typeIs(target string, src any) bool { return target == typeOf(src) } -func typeIsLike(target string, src interface{}) bool { +func typeIsLike(target string, src any) bool { t := typeOf(src) return target == t || "*"+target == t } -func typeOf(src interface{}) string { +func typeOf(src any) string { return fmt.Sprintf("%T", src) } -func kindIs(target string, src interface{}) bool { +func kindIs(target string, src any) bool { return target == kindOf(src) } -func kindOf(src interface{}) string { +func kindOf(src any) string { return reflect.ValueOf(src).Kind().String() } diff --git a/util/sprig/strings.go b/util/sprig/strings.go index 3c62d6b6..911aa6f4 100644 --- a/util/sprig/strings.go +++ b/util/sprig/strings.go @@ -33,7 +33,7 @@ func base32decode(v string) string { return string(data) } -func quote(str ...interface{}) string { +func quote(str ...any) string { out := make([]string, 0, len(str)) for _, s := range str { if s != nil { @@ -43,7 +43,7 @@ func quote(str ...interface{}) string { return strings.Join(out, " ") } -func squote(str ...interface{}) string { +func squote(str ...any) string { out := make([]string, 0, len(str)) for _, s := range str { if s != nil { @@ -53,7 +53,7 @@ func squote(str ...interface{}) string { return strings.Join(out, " ") } -func cat(v ...interface{}) string { +func cat(v ...any) string { v = removeNilElements(v) r := strings.TrimSpace(strings.Repeat("%v ", len(v))) return fmt.Sprintf(r, v...) @@ -79,11 +79,11 @@ func plural(one, many string, count int) string { return many } -func strslice(v interface{}) []string { +func strslice(v any) []string { switch v := v.(type) { case []string: return v - case []interface{}: + case []any: b := make([]string, 0, len(v)) for _, s := range v { if s != nil { @@ -114,8 +114,8 @@ func strslice(v interface{}) []string { } } -func removeNilElements(v []interface{}) []interface{} { - newSlice := make([]interface{}, 0, len(v)) +func removeNilElements(v []any) []any { + newSlice := make([]any, 0, len(v)) for _, i := range v { if i != nil { newSlice = append(newSlice, i) @@ -124,7 +124,7 @@ func removeNilElements(v []interface{}) []interface{} { return newSlice } -func strval(v interface{}) string { +func strval(v any) string { switch v := v.(type) { case string: return v @@ -149,7 +149,7 @@ func trunc(c int, s string) string { return s } -func join(sep string, v interface{}) string { +func join(sep string, v any) string { return strings.Join(strslice(v), sep) } diff --git a/util/sprig/strings_test.go b/util/sprig/strings_test.go index 38c96c4e..1e91d9b2 100644 --- a/util/sprig/strings_test.go +++ b/util/sprig/strings_test.go @@ -56,7 +56,7 @@ func TestQuote(t *testing.T) { t.Error(err) } tpl = `{{ .value | quote }}` - values := map[string]interface{}{"value": nil} + values := map[string]any{"value": nil} if err := runtv(tpl, ``, values); err != nil { t.Error(err) } @@ -71,7 +71,7 @@ func TestSquote(t *testing.T) { t.Error(err) } tpl = `{{ .value | squote }}` - values := map[string]interface{}{"value": nil} + values := map[string]any{"value": nil} if err := runtv(tpl, ``, values); err != nil { t.Error(err) } @@ -128,7 +128,7 @@ func TestToStrings(t *testing.T) { tpl := `{{ $s := list 1 2 3 | toStrings }}{{ index $s 1 | kindOf }}` assert.NoError(t, runt(tpl, "string")) tpl = `{{ list 1 .value 2 | toStrings }}` - values := map[string]interface{}{"value": nil} + values := map[string]any{"value": nil} if err := runtv(tpl, `[1 2]`, values); err != nil { t.Error(err) } @@ -137,10 +137,10 @@ func TestToStrings(t *testing.T) { func TestJoin(t *testing.T) { assert.NoError(t, runt(`{{ tuple "a" "b" "c" | join "-" }}`, "a-b-c")) assert.NoError(t, runt(`{{ tuple 1 2 3 | join "-" }}`, "1-2-3")) - assert.NoError(t, runtv(`{{ join "-" .V }}`, "a-b-c", map[string]interface{}{"V": []string{"a", "b", "c"}})) - assert.NoError(t, runtv(`{{ join "-" .V }}`, "abc", map[string]interface{}{"V": "abc"})) - assert.NoError(t, runtv(`{{ join "-" .V }}`, "1-2-3", map[string]interface{}{"V": []int{1, 2, 3}})) - assert.NoError(t, runtv(`{{ join "-" .value }}`, "1-2", map[string]interface{}{"value": []interface{}{"1", nil, "2"}})) + assert.NoError(t, runtv(`{{ join "-" .V }}`, "a-b-c", map[string]any{"V": []string{"a", "b", "c"}})) + assert.NoError(t, runtv(`{{ join "-" .V }}`, "abc", map[string]any{"V": "abc"})) + assert.NoError(t, runtv(`{{ join "-" .V }}`, "1-2-3", map[string]any{"V": []int{1, 2, 3}})) + assert.NoError(t, runtv(`{{ join "-" .value }}`, "1-2", map[string]any{"value": []any{"1", nil, "2"}})) } func TestSortAlpha(t *testing.T) { @@ -194,7 +194,7 @@ func TestCat(t *testing.T) { t.Error(err) } tpl = `{{ .value | cat "a" "b"}}` - values := map[string]interface{}{"value": nil} + values := map[string]any{"value": nil} if err := runtv(tpl, "a b", values); err != nil { t.Error(err) } diff --git a/util/sprig/url.go b/util/sprig/url.go index b8e120e1..00826706 100644 --- a/util/sprig/url.go +++ b/util/sprig/url.go @@ -6,7 +6,7 @@ import ( "reflect" ) -func dictGetOrEmpty(dict map[string]interface{}, key string) string { +func dictGetOrEmpty(dict map[string]any, key string) string { value, ok := dict[key] if !ok { return "" @@ -19,8 +19,8 @@ func dictGetOrEmpty(dict map[string]interface{}, key string) string { } // parses given URL to return dict object -func urlParse(v string) map[string]interface{} { - dict := map[string]interface{}{} +func urlParse(v string) map[string]any { + dict := map[string]any{} parsedURL, err := url.Parse(v) if err != nil { panic(fmt.Sprintf("unable to parse url: %s", err)) @@ -42,7 +42,7 @@ func urlParse(v string) map[string]interface{} { } // join given dict to URL string -func urlJoin(d map[string]interface{}) string { +func urlJoin(d map[string]any) string { resURL := url.URL{ Scheme: dictGetOrEmpty(d, "scheme"), Host: dictGetOrEmpty(d, "host"), diff --git a/util/sprig/url_test.go b/util/sprig/url_test.go index f9c00b17..16d457a7 100644 --- a/util/sprig/url_test.go +++ b/util/sprig/url_test.go @@ -6,7 +6,7 @@ import ( "github.com/stretchr/testify/assert" ) -var urlTests = map[string]map[string]interface{}{ +var urlTests = map[string]map[string]any{ "proto://auth@host:80/path?query#fragment": { "fragment": "fragment", "host": "host:80",