From bfa6b9dcef7592e6dd8225aaa0d0ab5aef5b3f84 Mon Sep 17 00:00:00 2001 From: Dave Henderson Date: Sun, 9 Mar 2025 20:14:46 -0400 Subject: chore(refactoring): Refactor/modernizations (#2345) chore(refactoring): Refactor with modernization refactorings * range over int * replace interface{} with any * replace common map operations with maps.Copy/maps.Clone * simplifying loops with slices.Contains/ContainsFunc * modernize benchmarks with b.Loop * modernize tests with t.Context * use fmt.Appendf * range over strings.SplitSeq * use new stdlib crypto/pbkdf2 package --------- Signed-off-by: Dave Henderson --- aws/ec2info.go | 4 +- aws/ec2info_test.go | 8 +- aws/ec2meta_test.go | 2 +- aws/sts.go | 4 +- aws/testutils.go | 2 +- base64/base64_test.go | 2 +- coll/coll.go | 100 +++---- coll/coll_test.go | 326 ++++++++++----------- coll/index.go | 2 +- coll/index_test.go | 12 +- coll/jq.go | 18 +- coll/jq_test.go | 56 ++-- coll/jsonpath.go | 8 +- coll/jsonpath_test.go | 6 +- config.go | 17 +- context.go | 4 +- context_test.go | 6 +- conv/conv.go | 36 +-- conv/conv_test.go | 68 ++--- conv/evalargs.go | 2 +- crypto/pbkdf2.go | 8 +- docs-src/content/functions/coll.yml | 2 +- docs/content/functions/coll.md | 2 +- funcs.go | 50 ++-- go.mod | 2 +- gomplate_test.go | 2 +- internal/cmd/main_test.go | 7 +- internal/config/types.go | 4 +- internal/conv/conv.go | 12 +- internal/conv/conv_test.go | 22 +- internal/datafs/envfs.go | 2 +- internal/datafs/mergefs.go | 2 +- internal/datafs/mergefs_test.go | 30 +- internal/datafs/reader_test.go | 2 +- internal/datafs/stdinfs_test.go | 4 +- internal/funcs/aws.go | 10 +- internal/funcs/aws_test.go | 6 +- internal/funcs/base64.go | 14 +- internal/funcs/base64_test.go | 6 +- internal/funcs/coll.go | 58 ++-- internal/funcs/coll_test.go | 60 ++-- internal/funcs/conv.go | 42 +-- internal/funcs/conv_test.go | 6 +- internal/funcs/crypto.go | 54 ++-- internal/funcs/crypto_test.go | 4 +- internal/funcs/data.go | 30 +- internal/funcs/data_test.go | 4 +- internal/funcs/datasource.go | 8 +- internal/funcs/datasource_test.go | 14 +- internal/funcs/env.go | 10 +- internal/funcs/env_test.go | 4 +- internal/funcs/file.go | 20 +- internal/funcs/file_test.go | 4 +- internal/funcs/filepath.go | 30 +- internal/funcs/filepath_test.go | 4 +- internal/funcs/gcp.go | 8 +- internal/funcs/gcp_test.go | 4 +- internal/funcs/math.go | 59 ++-- internal/funcs/math_test.go | 89 +++--- internal/funcs/net.go | 42 +-- internal/funcs/net_test.go | 4 +- internal/funcs/path.go | 22 +- internal/funcs/path_test.go | 4 +- internal/funcs/random.go | 22 +- internal/funcs/random_test.go | 6 +- internal/funcs/regexp.go | 20 +- internal/funcs/regexp_test.go | 4 +- internal/funcs/semver.go | 6 +- internal/funcs/sockaddr.go | 8 +- internal/funcs/sockaddr_test.go | 4 +- internal/funcs/strings.go | 70 ++--- internal/funcs/strings_test.go | 28 +- internal/funcs/test.go | 18 +- internal/funcs/test_test.go | 14 +- internal/funcs/time.go | 30 +- internal/funcs/time_test.go | 4 +- internal/funcs/uuid.go | 10 +- internal/funcs/uuid_test.go | 12 +- internal/parsers/parsefuncs.go | 82 +++--- internal/parsers/parsefuncs_test.go | 190 ++++++------ .../tests/integration/datasources_consul_test.go | 4 +- .../integration/datasources_vault_ec2_test.go | 8 +- .../integration/datasources_vault_iam_test.go | 6 +- .../tests/integration/datasources_vault_test.go | 26 +- internal/tests/integration/inputdir_unix_test.go | 4 +- internal/tests/integration/test_ec2_utils_test.go | 8 +- net/net.go | 12 +- net/net_test.go | 4 +- plugins.go | 4 +- plugins_test.go | 3 +- random/random.go | 2 +- random/random_test.go | 6 +- render.go | 11 +- strings/strings.go | 2 +- strings/strings_test.go | 2 +- template.go | 8 +- test/test.go | 2 +- tmpl/tmpl.go | 16 +- version/gen/vgen.go | 2 +- 99 files changed, 1034 insertions(+), 1078 deletions(-) diff --git a/aws/ec2info.go b/aws/ec2info.go index 556d2efc..ba494d2b 100644 --- a/aws/ec2info.go +++ b/aws/ec2info.go @@ -33,7 +33,7 @@ type ClientOptions struct { type Ec2Info struct { describer func() (InstanceDescriber, error) metaClient *Ec2Meta - cache map[string]interface{} + cache map[string]any } // InstanceDescriber - A subset of ec2iface.EC2API that we can use to call EC2.DescribeInstances @@ -137,7 +137,7 @@ func NewEc2Info(options ClientOptions) (info *Ec2Info) { return describerClient, nil }, metaClient: metaClient, - cache: make(map[string]interface{}), + cache: make(map[string]any), } } diff --git a/aws/ec2info_test.go b/aws/ec2info_test.go index 497f50d1..87db85a3 100644 --- a/aws/ec2info_test.go +++ b/aws/ec2info_test.go @@ -32,7 +32,7 @@ func TestTag_MissingKey(t *testing.T) { return client, nil }, metaClient: ec2meta, - cache: make(map[string]interface{}), + cache: make(map[string]any), } assert.Empty(t, must(e.Tag("missing"))) @@ -59,7 +59,7 @@ func TestTag_ValidKey(t *testing.T) { return client, nil }, metaClient: ec2meta, - cache: make(map[string]interface{}), + cache: make(map[string]any), } assert.Equal(t, "bar", must(e.Tag("foo"))) @@ -85,7 +85,7 @@ func TestTags(t *testing.T) { return client, nil }, metaClient: ec2meta, - cache: make(map[string]interface{}), + cache: make(map[string]any), } assert.Equal(t, map[string]string{"foo": "bar", "baz": "qux"}, must(e.Tags())) @@ -101,7 +101,7 @@ func TestTag_NonEC2(t *testing.T) { return client, nil }, metaClient: ec2meta, - cache: make(map[string]interface{}), + cache: make(map[string]any), } assert.Equal(t, "", must(e.Tag("foo"))) diff --git a/aws/ec2meta_test.go b/aws/ec2meta_test.go index 732f97b6..fcc6da67 100644 --- a/aws/ec2meta_test.go +++ b/aws/ec2meta_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/assert" ) -func must(r interface{}, err error) interface{} { +func must(r any, err error) any { if err != nil { panic(err) } diff --git a/aws/sts.go b/aws/sts.go index b7b0b356..3883de42 100644 --- a/aws/sts.go +++ b/aws/sts.go @@ -8,7 +8,7 @@ import ( // STS - type STS struct { identifier func() CallerIdentitifier - cache map[string]interface{} + cache map[string]any } var identifierClient CallerIdentitifier @@ -28,7 +28,7 @@ func NewSTS(_ ClientOptions) *STS { } return identifierClient }, - cache: make(map[string]interface{}), + cache: make(map[string]any), } } diff --git a/aws/testutils.go b/aws/testutils.go index bc57e117..23a83c87 100644 --- a/aws/testutils.go +++ b/aws/testutils.go @@ -26,7 +26,7 @@ func NewDummyEc2Info(metaClient *Ec2Meta) *Ec2Info { i := &Ec2Info{ metaClient: metaClient, describer: func() (InstanceDescriber, error) { return DummyInstanceDescriber{}, nil }, - cache: map[string]interface{}{}, + cache: map[string]any{}, } return i } diff --git a/base64/base64_test.go b/base64/base64_test.go index c661263c..2ecd3210 100644 --- a/base64/base64_test.go +++ b/base64/base64_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" ) -func must(r interface{}, err error) interface{} { +func must(r any, err error) any { if err != nil { return err } diff --git a/coll/coll.go b/coll/coll.go index cbc96023..310e7cf3 100644 --- a/coll/coll.go +++ b/coll/coll.go @@ -1,13 +1,15 @@ // Package coll contains functions to help manipulate and query collections of // data, like slices/arrays and maps. // -// For the functions that return an array, a []interface{} is returned, +// For the functions that return an array, a []any is returned, // regardless of whether or not the input was a different type. package coll import ( "fmt" + "maps" "reflect" + "slices" "sort" "github.com/hairyhenderson/gomplate/v4/conv" @@ -15,12 +17,12 @@ import ( ) // Slice creates a slice from a bunch of arguments -func Slice(args ...interface{}) []interface{} { +func Slice(args ...any) []any { return args } // Has determines whether or not a given object has a property with the given key -func Has(in interface{}, key interface{}) bool { +func Has(in any, key any) bool { av := reflect.ValueOf(in) switch av.Kind() { @@ -29,7 +31,7 @@ func Has(in interface{}, key interface{}) bool { return av.MapIndex(kv).IsValid() case reflect.Slice, reflect.Array: l := av.Len() - for i := 0; i < l; i++ { + for i := range l { v := av.Index(i).Interface() if reflect.DeepEqual(v, key) { return true @@ -45,8 +47,8 @@ func Has(in interface{}, key interface{}) bool { // is provided, the last is used as the key, and an empty string is // set as the value. // All keys are converted to strings, regardless of input type. -func Dict(v ...interface{}) (map[string]interface{}, error) { - dict := map[string]interface{}{} +func Dict(v ...any) (map[string]any, error) { + dict := map[string]any{} lenv := len(v) for i := 0; i < lenv; i += 2 { key := conv.ToString(v[i]) @@ -61,7 +63,7 @@ func Dict(v ...interface{}) (map[string]interface{}, error) { // Keys returns the list of keys in one or more maps. The returned list of keys // is ordered by map, each in sorted key order. -func Keys(in ...map[string]interface{}) ([]string, error) { +func Keys(in ...map[string]any) ([]string, error) { if len(in) == 0 { return nil, fmt.Errorf("need at least one argument") } @@ -73,9 +75,9 @@ func Keys(in ...map[string]interface{}) ([]string, error) { return keys, nil } -func splitMap(m map[string]interface{}) ([]string, []interface{}) { +func splitMap(m map[string]any) ([]string, []any) { keys := make([]string, len(m)) - values := make([]interface{}, len(m)) + values := make([]any, len(m)) i := 0 for k := range m { keys[i] = k @@ -91,11 +93,11 @@ func splitMap(m map[string]interface{}) ([]string, []interface{}) { // Values returns the list of values in one or more maps. The returned list of values // is ordered by map, each in sorted key order. If the Keys function is called with // the same arguments, the key/value mappings will be maintained. -func Values(in ...map[string]interface{}) ([]interface{}, error) { +func Values(in ...map[string]any) ([]any, error) { if len(in) == 0 { return nil, fmt.Errorf("need at least one argument") } - values := []interface{}{} + values := []any{} for _, m := range in { _, v := splitMap(m) values = append(values, v...) @@ -103,8 +105,8 @@ func Values(in ...map[string]interface{}) ([]interface{}, error) { return values, nil } -// Append v to the end of list. No matter what type of input slice or array list is, a new []interface{} is always returned. -func Append(v interface{}, list interface{}) ([]interface{}, error) { +// Append v to the end of list. No matter what type of input slice or array list is, a new []any is always returned. +func Append(v any, list any) ([]any, error) { l, err := iconv.InterfaceSlice(list) if err != nil { return nil, err @@ -113,24 +115,24 @@ func Append(v interface{}, list interface{}) ([]interface{}, error) { return append(l, v), nil } -// Prepend v to the beginning of list. No matter what type of input slice or array list is, a new []interface{} is always returned. -func Prepend(v interface{}, list interface{}) ([]interface{}, error) { +// Prepend v to the beginning of list. No matter what type of input slice or array list is, a new []any is always returned. +func Prepend(v any, list any) ([]any, error) { l, err := iconv.InterfaceSlice(list) if err != nil { return nil, err } - return append([]interface{}{v}, l...), nil + return append([]any{v}, l...), nil } -// Uniq finds the unique values within list. No matter what type of input slice or array list is, a new []interface{} is always returned. -func Uniq(list interface{}) ([]interface{}, error) { +// Uniq finds the unique values within list. No matter what type of input slice or array list is, a new []any is always returned. +func Uniq(list any) ([]any, error) { l, err := iconv.InterfaceSlice(list) if err != nil { return nil, err } - out := []interface{}{} + out := []any{} for _, v := range l { if !Has(out, v) { out = append(out, v) @@ -139,8 +141,8 @@ func Uniq(list interface{}) ([]interface{}, error) { return out, nil } -// Reverse the list. No matter what type of input slice or array list is, a new []interface{} is always returned. -func Reverse(list interface{}) ([]interface{}, error) { +// Reverse the list. No matter what type of input slice or array list is, a new []any is always returned. +func Reverse(list any) ([]any, error) { l, err := iconv.InterfaceSlice(list) if err != nil { return nil, err @@ -155,29 +157,19 @@ func Reverse(list interface{}) ([]interface{}, error) { // Merge source maps (srcs) into dst. Precedence is in left-to-right order, with // the left-most values taking precedence over the right-most. -func Merge(dst map[string]interface{}, srcs ...map[string]interface{}) (map[string]interface{}, error) { +func Merge(dst map[string]any, srcs ...map[string]any) (map[string]any, error) { for _, src := range srcs { dst = mergeValues(src, dst) } return dst, nil } -// returns whether or not a contains v -func contains(v string, a []string) bool { - for _, n := range a { - if n == v { - return true - } - } - return false -} - // Omit returns a new map without any entries that have the // given keys (inverse of Pick). -func Omit(in map[string]interface{}, keys ...string) map[string]interface{} { - out := map[string]interface{}{} +func Omit(in map[string]any, keys ...string) map[string]any { + out := map[string]any{} for k, v := range in { - if !contains(k, keys) { + if !slices.Contains(keys, k) { out[k] = v } } @@ -186,42 +178,34 @@ func Omit(in map[string]interface{}, keys ...string) map[string]interface{} { // Pick returns a new map with any entries that have the // given keys (inverse of Omit). -func Pick(in map[string]interface{}, keys ...string) map[string]interface{} { - out := map[string]interface{}{} +func Pick(in map[string]any, keys ...string) map[string]any { + out := map[string]any{} for k, v := range in { - if contains(k, keys) { + if slices.Contains(keys, k) { out[k] = v } } return out } -func copyMap(m map[string]interface{}) map[string]interface{} { - n := map[string]interface{}{} - for k, v := range m { - n[k] = v - } - return n -} - // Merges a default and override map -func mergeValues(d map[string]interface{}, o map[string]interface{}) map[string]interface{} { - def := copyMap(d) - over := copyMap(o) +func mergeValues(d map[string]any, o map[string]any) map[string]any { + def := maps.Clone(d) + over := maps.Clone(o) for k, v := range over { // If the key doesn't exist already, then just set the key to that value if _, exists := def[k]; !exists { def[k] = v continue } - nextMap, ok := v.(map[string]interface{}) + nextMap, ok := v.(map[string]any) // If it isn't another map, overwrite the value if !ok { def[k] = v continue } // Edge case: If the key exists in the default, but isn't a map - defMap, isMap := def[k].(map[string]interface{}) + defMap, isMap := def[k].(map[string]any) // If the override map has a map for this key, prefer it if !isMap { def[k] = v @@ -238,7 +222,7 @@ func mergeValues(d map[string]interface{}, o map[string]interface{}) map[string] // sort by the values of those entries. // // Does not modify the input list. -func Sort(key string, list interface{}) (out []interface{}, err error) { +func Sort(key string, list any) (out []any, err error) { if list == nil { return nil, nil } @@ -249,7 +233,7 @@ func Sort(key string, list interface{}) (out []interface{}, err error) { } // if the types are all the same, we can sort the slice if sameTypes(ia) { - s := make([]interface{}, len(ia)) + s := make([]any, len(ia)) // make a copy so the original is unmodified copy(s, ia) sort.SliceStable(s, func(i, j int) bool { @@ -261,8 +245,8 @@ func Sort(key string, list interface{}) (out []interface{}, err error) { } // lessThan - compare two values of the same type -func lessThan(key string) func(left, right interface{}) bool { - return func(left, right interface{}) bool { +func lessThan(key string) func(left, right any) bool { + return func(left, right any) bool { val := reflect.Indirect(reflect.ValueOf(left)) rval := reflect.Indirect(reflect.ValueOf(right)) switch val.Kind() { @@ -299,7 +283,7 @@ func lessThan(key string) func(left, right interface{}) bool { } } -func sameTypes(a []interface{}) bool { +func sameTypes(a []any) bool { var t reflect.Type for _, v := range a { if t == nil { @@ -315,7 +299,7 @@ func sameTypes(a []interface{}) bool { // Flatten a nested array or slice to at most 'depth' levels. Use depth of -1 // to completely flatten the input. // Returns a new slice without modifying the input. -func Flatten(list interface{}, depth int) ([]interface{}, error) { +func Flatten(list any, depth int) ([]any, error) { l, err := iconv.InterfaceSlice(list) if err != nil { return nil, err @@ -323,7 +307,7 @@ func Flatten(list interface{}, depth int) ([]interface{}, error) { if depth == 0 { return l, nil } - out := make([]interface{}, 0, len(l)*2) + out := make([]any, 0, len(l)*2) for _, v := range l { s := reflect.ValueOf(v) kind := s.Kind() diff --git a/coll/coll_test.go b/coll/coll_test.go index 4f7da49f..ab2241ee 100644 --- a/coll/coll_test.go +++ b/coll/coll_test.go @@ -16,24 +16,24 @@ func TestSlice(t *testing.T) { } func TestHas(t *testing.T) { - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", - "baz": map[string]interface{}{ + "baz": map[string]any{ "qux": "quux", }, } testdata := []struct { - in interface{} - key interface{} + in any + key any out bool }{ {in, "foo", true}, {in, "bar", false}, {in["baz"], "qux", true}, {[]string{"foo", "bar", "baz"}, "bar", true}, - {[]interface{}{"foo", "bar", "baz"}, "bar", true}, - {[]interface{}{"foo", "bar", "baz"}, 42, false}, + {[]any{"foo", "bar", "baz"}, "bar", true}, + {[]any{"foo", "bar", "baz"}, 42, false}, {[]int{1, 2, 42}, 42, true}, } @@ -44,16 +44,16 @@ func TestHas(t *testing.T) { func TestDict(t *testing.T) { testdata := []struct { - expected map[string]interface{} - args []interface{} + expected map[string]any + args []any }{ - {expected: map[string]interface{}{}}, - {args: []interface{}{}, expected: map[string]interface{}{}}, - {args: []interface{}{"foo"}, expected: map[string]interface{}{"foo": ""}}, - {args: []interface{}{42}, expected: map[string]interface{}{"42": ""}}, - {args: []interface{}{"foo", nil}, expected: map[string]interface{}{"foo": nil}}, - {args: []interface{}{"foo", "bar"}, expected: map[string]interface{}{"foo": "bar"}}, - {args: []interface{}{"foo", "bar", "baz", true}, expected: map[string]interface{}{ + {expected: map[string]any{}}, + {args: []any{}, expected: map[string]any{}}, + {args: []any{"foo"}, expected: map[string]any{"foo": ""}}, + {args: []any{42}, expected: map[string]any{"42": ""}}, + {args: []any{"foo", nil}, expected: map[string]any{"foo": nil}}, + {args: []any{"foo", "bar"}, expected: map[string]any{"foo": "bar"}}, + {args: []any{"foo", "bar", "baz", true}, expected: map[string]any{ "foo": "bar", "baz": true, }}, @@ -69,7 +69,7 @@ func TestKeys(t *testing.T) { _, err := Keys() require.Error(t, err) - in := map[string]interface{}{ + in := map[string]any{ "foo": 1, "bar": 2, } @@ -78,7 +78,7 @@ func TestKeys(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, keys) - in2 := map[string]interface{}{ + in2 := map[string]any{ "baz": 3, "qux": 4, } @@ -87,7 +87,7 @@ func TestKeys(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, keys) - in3 := map[string]interface{}{ + in3 := map[string]any{ "Foo": 5, "Bar": 6, "foo": 7, @@ -103,114 +103,114 @@ func TestValues(t *testing.T) { _, err := Values() require.Error(t, err) - in := map[string]interface{}{ + in := map[string]any{ "foo": 1, "bar": 2, } - expected := []interface{}{2, 1} + expected := []any{2, 1} values, err := Values(in) require.NoError(t, err) assert.EqualValues(t, expected, values) - in2 := map[string]interface{}{ + in2 := map[string]any{ "baz": 3, "qux": 4, } - expected = []interface{}{2, 1, 3, 4} + expected = []any{2, 1, 3, 4} values, err = Values(in, in2) require.NoError(t, err) assert.EqualValues(t, expected, values) - in3 := map[string]interface{}{ + in3 := map[string]any{ "Foo": 5, "Bar": 6, "foo": 7, "bar": 8, } - expected = []interface{}{2, 1, 3, 4, 6, 5, 8, 7} + expected = []any{2, 1, 3, 4, 6, 5, 8, 7} values, err = Values(in, in2, in3) require.NoError(t, err) assert.EqualValues(t, expected, values) } func TestAppend(t *testing.T) { - out, err := Append(42, []interface{}{}) + out, err := Append(42, []any{}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{42}, out) + assert.EqualValues(t, []any{42}, out) - out, err = Append(42, []interface{}{4.9, false, "foo"}) + out, err = Append(42, []any{4.9, false, "foo"}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{4.9, false, "foo", 42}, out) + assert.EqualValues(t, []any{4.9, false, "foo", 42}, out) - // a strange but valid use-cases, since we're converting to an []interface{} + // a strange but valid use-cases, since we're converting to an []any out, err = Append(42, []string{"foo"}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{"foo", 42}, out) + assert.EqualValues(t, []any{"foo", 42}, out) out, err = Append("baz", []string{"foo", "bar"}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{"foo", "bar", "baz"}, out) + assert.EqualValues(t, []any{"foo", "bar", "baz"}, out) } func TestPrepend(t *testing.T) { - out, err := Prepend(42, []interface{}{}) + out, err := Prepend(42, []any{}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{42}, out) + assert.EqualValues(t, []any{42}, out) - out, err = Prepend(42, []interface{}{4.9, false, "foo"}) + out, err = Prepend(42, []any{4.9, false, "foo"}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{42, 4.9, false, "foo"}, out) + assert.EqualValues(t, []any{42, 4.9, false, "foo"}, out) - // a strange but valid use-cases, since we're converting to an []interface{} + // a strange but valid use-cases, since we're converting to an []any out, err = Prepend(42, []string{"foo"}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{42, "foo"}, out) + assert.EqualValues(t, []any{42, "foo"}, out) out, err = Prepend("foo", []string{"bar", "baz"}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{"foo", "bar", "baz"}, out) + assert.EqualValues(t, []any{"foo", "bar", "baz"}, out) } func TestUniq(t *testing.T) { - out, err := Uniq([]interface{}{1, 2, 3, 1, true, false, true, "1", 2}) + out, err := Uniq([]any{1, 2, 3, 1, true, false, true, "1", 2}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{1, 2, 3, true, false, "1"}, out) + assert.EqualValues(t, []any{1, 2, 3, true, false, "1"}, out) out, err = Uniq([]string{"one", "two", "one", "three"}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{"one", "two", "three"}, out) + assert.EqualValues(t, []any{"one", "two", "three"}, out) } func TestReverse(t *testing.T) { - out, err := Reverse([]interface{}{}) + out, err := Reverse([]any{}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{}, out) + assert.EqualValues(t, []any{}, out) - out, err = Reverse([]interface{}{8}) + out, err = Reverse([]any{8}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{8}, out) + assert.EqualValues(t, []any{8}, out) - out, err = Reverse([]interface{}{1, 2, 3, 4}) + out, err = Reverse([]any{1, 2, 3, 4}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{4, 3, 2, 1}, out) + assert.EqualValues(t, []any{4, 3, 2, 1}, out) out, err = Reverse([]int{1, 2, 3, 4}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{4, 3, 2, 1}, out) + assert.EqualValues(t, []any{4, 3, 2, 1}, out) } func TestMerge(t *testing.T) { - dst := map[string]interface{}{} - src := map[string]interface{}{} - expected := map[string]interface{}{} + dst := map[string]any{} + src := map[string]any{} + expected := map[string]any{} out, err := Merge(dst, src) require.NoError(t, err) assert.EqualValues(t, expected, out) - dst = map[string]interface{}{"a": 4, "c": 5} - src = map[string]interface{}{"a": 1, "b": 2, "c": 3} - expected = map[string]interface{}{ + dst = map[string]any{"a": 4, "c": 5} + src = map[string]any{"a": 1, "b": 2, "c": 3} + expected = map[string]any{ "a": dst["a"], "b": src["b"], "c": dst["c"], } @@ -218,10 +218,10 @@ func TestMerge(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, out) - dst = map[string]interface{}{"a": 4, "c": 5} - src = map[string]interface{}{"a": 1, "b": 2, "c": 3} - src2 := map[string]interface{}{"a": 1, "b": 2, "c": 3, "d": 4} - expected = map[string]interface{}{ + dst = map[string]any{"a": 4, "c": 5} + src = map[string]any{"a": 1, "b": 2, "c": 3} + src2 := map[string]any{"a": 1, "b": 2, "c": 3, "d": 4} + expected = map[string]any{ "a": dst["a"], "b": src["b"], "c": dst["c"], "d": src2["d"], } @@ -229,10 +229,10 @@ func TestMerge(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, out) - dst = map[string]interface{}{"a": false, "c": 5} - src = map[string]interface{}{"a": true, "b": 2, "c": 3} - src2 = map[string]interface{}{"a": true, "b": 2, "c": 3, "d": 4} - expected = map[string]interface{}{ + dst = map[string]any{"a": false, "c": 5} + src = map[string]any{"a": true, "b": 2, "c": 3} + src2 = map[string]any{"a": true, "b": 2, "c": 3, "d": 4} + expected = map[string]any{ "a": dst["a"], "b": src["b"], "c": dst["c"], "d": src2["d"], } @@ -240,15 +240,15 @@ func TestMerge(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, out) - dst = map[string]interface{}{"a": true, "c": 5} - src = map[string]interface{}{ + dst = map[string]any{"a": true, "c": 5} + src = map[string]any{ "a": false, - "b": map[string]interface{}{ + "b": map[string]any{ "ca": "foo", }, } - src2 = map[string]interface{}{"a": false, "b": 2, "c": 3, "d": 4} - expected = map[string]interface{}{ + src2 = map[string]any{"a": false, "b": 2, "c": 3, "d": 4} + expected = map[string]any{ "a": dst["a"], "b": src["b"], "c": dst["c"], "d": src2["d"], } @@ -256,22 +256,22 @@ func TestMerge(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, out) - dst = map[string]interface{}{ + dst = map[string]any{ "a": true, - "b": map[string]interface{}{ + "b": map[string]any{ "ca": "foo", "cb": "bar", }, "c": 5, } - src = map[string]interface{}{ + src = map[string]any{ "a": false, - "b": map[string]interface{}{ + "b": map[string]any{ "ca": 8, }, } - expected = map[string]interface{}{ - "a": dst["a"], "b": map[string]interface{}{ + expected = map[string]any{ + "a": dst["a"], "b": map[string]any{ "ca": "foo", "cb": "bar", }, "c": dst["c"], @@ -288,19 +288,19 @@ type coords struct { func TestSameTypes(t *testing.T) { data := []struct { - in []interface{} + in []any out bool }{ - {[]interface{}{}, true}, - {[]interface{}{"a", "b"}, true}, - {[]interface{}{1.0, 3.14}, true}, - {[]interface{}{1, 3}, true}, - {[]interface{}{true, false}, true}, - {[]interface{}{1, 3.0}, false}, - {[]interface{}{"a", nil}, false}, - {[]interface{}{"a", true}, false}, - {[]interface{}{coords{2, 3}, coords{3, 4}}, true}, - {[]interface{}{coords{2, 3}, &coords{3, 4}}, false}, + {[]any{}, true}, + {[]any{"a", "b"}, true}, + {[]any{1.0, 3.14}, true}, + {[]any{1, 3}, true}, + {[]any{true, false}, true}, + {[]any{1, 3.0}, false}, + {[]any{"a", nil}, false}, + {[]any{"a", true}, false}, + {[]any{coords{2, 3}, coords{3, 4}}, true}, + {[]any{coords{2, 3}, &coords{3, 4}}, false}, } for _, d := range data { @@ -310,7 +310,7 @@ func TestSameTypes(t *testing.T) { func TestLessThan(t *testing.T) { data := []struct { - left, right interface{} + left, right any key string out bool }{ @@ -324,17 +324,17 @@ func TestLessThan(t *testing.T) { {left: uint(0xff), right: uint(0x32)}, {left: 1, right: 3, out: true}, {left: true, right: false, out: false}, - {left: map[string]interface{}{"foo": 1}, right: map[string]interface{}{"foo": 2}}, + {left: map[string]any{"foo": 1}, right: map[string]any{"foo": 2}}, { key: "foo", - left: map[string]interface{}{"foo": 1}, - right: map[string]interface{}{"foo": 2}, + left: map[string]any{"foo": 1}, + right: map[string]any{"foo": 2}, out: true, }, { key: "bar", - left: map[string]interface{}{"foo": 1}, - right: map[string]interface{}{"foo": 2}, + left: map[string]any{"foo": 1}, + right: map[string]any{"foo": 2}, }, {key: "X", left: coords{}, right: coords{-1, 2}}, {key: "Y", left: &coords{1, 1}, right: &coords{-1, 2}, out: true}, @@ -356,23 +356,23 @@ func TestSort(t *testing.T) { data := []struct { key string - in interface{} - out []interface{} + in any + out []any }{ { key: "", in: []string{"b", "c", "a", "d"}, - out: []interface{}{"a", "b", "c", "d"}, + out: []any{"a", "b", "c", "d"}, }, { key: "", - in: []interface{}{"b", "c", "a", "d"}, - out: []interface{}{"a", "b", "c", "d"}, + in: []any{"b", "c", "a", "d"}, + out: []any{"a", "b", "c", "d"}, }, { key: "", - in: []interface{}{"c", "a", "b", 3, 1, 2}, - out: []interface{}{"c", "a", "b", 3, 1, 2}, + in: []any{"c", "a", "b", 3, 1, 2}, + out: []any{"c", "a", "b", 3, 1, 2}, }, { key: "", @@ -382,41 +382,41 @@ func TestSort(t *testing.T) { { key: "", - in: []map[string]interface{}{ + in: []map[string]any{ {"name": "Bart", "age": 12}, {"age": 1, "name": "Maggie"}, {"name": "Lisa", "age": 6}, }, - out: []interface{}{ - map[string]interface{}{"name": "Bart", "age": 12}, - map[string]interface{}{"age": 1, "name": "Maggie"}, - map[string]interface{}{"name": "Lisa", "age": 6}, + out: []any{ + map[string]any{"name": "Bart", "age": 12}, + map[string]any{"age": 1, "name": "Maggie"}, + map[string]any{"name": "Lisa", "age": 6}, }, }, { key: "name", - in: []map[string]interface{}{ + in: []map[string]any{ {"name": "Bart", "age": 12}, {"age": 1, "name": "Maggie"}, {"name": "Lisa", "age": 6}, }, - out: []interface{}{ - map[string]interface{}{"name": "Bart", "age": 12}, - map[string]interface{}{"name": "Lisa", "age": 6}, - map[string]interface{}{"age": 1, "name": "Maggie"}, + out: []any{ + map[string]any{"name": "Bart", "age": 12}, + map[string]any{"name": "Lisa", "age": 6}, + map[string]any{"age": 1, "name": "Maggie"}, }, }, { key: "age", - in: []map[string]interface{}{ + in: []map[string]any{ {"name": "Bart", "age": 12}, {"age": 1, "name": "Maggie"}, {"name": "Lisa", "age": 6}, }, - out: []interface{}{ - map[string]interface{}{"age": 1, "name": "Maggie"}, - map[string]interface{}{"name": "Lisa", "age": 6}, - map[string]interface{}{"name": "Bart", "age": 12}, + out: []any{ + map[string]any{"age": 1, "name": "Maggie"}, + map[string]any{"name": "Lisa", "age": 6}, + map[string]any{"name": "Bart", "age": 12}, }, }, { @@ -426,7 +426,7 @@ func TestSort(t *testing.T) { {"x": 13, "y": -8}, {"x": 1, "y": 0}, }, - out: []interface{}{ + out: []any{ map[string]int{"x": 13, "y": -8}, map[string]int{"x": 1, "y": 0}, map[string]int{"x": 54, "y": 6}, @@ -439,7 +439,7 @@ func TestSort(t *testing.T) { {3, 3}, {1, 5}, }, - out: []interface{}{ + out: []any{ coords{1, 5}, coords{2, 4}, coords{3, 3}, @@ -452,7 +452,7 @@ func TestSort(t *testing.T) { {3, 3}, {1, 5}, }, - out: []interface{}{ + out: []any{ &coords{1, 5}, &coords{2, 4}, &coords{3, 3}, @@ -471,70 +471,70 @@ func TestSort(t *testing.T) { func TestFlatten(t *testing.T) { data := []struct { - in interface{} - expected []interface{} + in any + expected []any depth int }{ - {in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{[]string{}, []int{1, 2}, 3}}, + {in: []int{1, 2, 3}, expected: []any{1, 2, 3}}, + {in: [3]int{1, 2, 3}, expected: []any{1, 2, 3}}, + {in: []any{[]string{}, []int{1, 2}, 3}, expected: []any{[]string{}, []int{1, 2}, 3}}, { - in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, - expected: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, + in: []any{[]string{"one"}, [][]int{{1, 2}}, 3}, + expected: []any{[]string{"one"}, [][]int{{1, 2}}, 3}, }, - {depth: 1, in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {depth: 1, in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {depth: 1, in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{1, 2, 3}}, + {depth: 1, in: []int{1, 2, 3}, expected: []any{1, 2, 3}}, + {depth: 1, in: [3]int{1, 2, 3}, expected: []any{1, 2, 3}}, + {depth: 1, in: []any{[]string{}, []int{1, 2}, 3}, expected: []any{1, 2, 3}}, { depth: 1, - in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, - expected: []interface{}{"one", []int{1, 2}, 3}, + in: []any{[]string{"one"}, [][]int{{1, 2}}, 3}, + expected: []any{"one", []int{1, 2}, 3}, }, - {depth: 2, in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {depth: 2, in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {depth: 2, in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{1, 2, 3}}, + {depth: 2, in: []int{1, 2, 3}, expected: []any{1, 2, 3}}, + {depth: 2, in: [3]int{1, 2, 3}, expected: []any{1, 2, 3}}, + {depth: 2, in: []any{[]string{}, []int{1, 2}, 3}, expected: []any{1, 2, 3}}, { depth: 2, - in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, - expected: []interface{}{"one", 1, 2, 3}, + in: []any{[]string{"one"}, [][]int{{1, 2}}, 3}, + expected: []any{"one", 1, 2, 3}, }, { depth: 2, - in: []interface{}{ + in: []any{ []string{"one"}, - []interface{}{ - []interface{}{ + []any{ + []any{ []int{1}, - []interface{}{2, []int{3}}, + []any{2, []int{3}}, }, []int{4, 5}, }, 6, }, - expected: []interface{}{"one", []int{1}, []interface{}{2, []int{3}}, 4, 5, 6}, + expected: []any{"one", []int{1}, []any{2, []int{3}}, 4, 5, 6}, }, - {depth: -1, in: []int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {depth: -1, in: [3]int{1, 2, 3}, expected: []interface{}{1, 2, 3}}, - {depth: -1, in: []interface{}{[]string{}, []int{1, 2}, 3}, expected: []interface{}{1, 2, 3}}, + {depth: -1, in: []int{1, 2, 3}, expected: []any{1, 2, 3}}, + {depth: -1, in: [3]int{1, 2, 3}, expected: []any{1, 2, 3}}, + {depth: -1, in: []any{[]string{}, []int{1, 2}, 3}, expected: []any{1, 2, 3}}, { depth: -1, - in: []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, - expected: []interface{}{"one", 1, 2, 3}, + in: []any{[]string{"one"}, [][]int{{1, 2}}, 3}, + expected: []any{"one", 1, 2, 3}, }, { depth: -1, - in: []interface{}{ + in: []any{ []string{"one"}, - []interface{}{ - []interface{}{ + []any{ + []any{ []int{1}, - []interface{}{2, []int{3}}, + []any{2, []int{3}}, }, []int{4, 5}, }, 6, }, - expected: []interface{}{"one", 1, 2, 3, 4, 5, 6}, + expected: []any{"one", 1, 2, 3, 4, 5, 6}, }, } @@ -549,17 +549,17 @@ func TestFlatten(t *testing.T) { } func BenchmarkFlatten(b *testing.B) { - data := []interface{}{ + data := []any{ []int{1, 2, 3}, [3]int{1, 2, 3}, - []interface{}{[]string{}, []int{1, 2}, 3}, - []interface{}{[]string{"one"}, [][]int{{1, 2}}, 3}, - []interface{}{ + []any{[]string{}, []int{1, 2}, 3}, + []any{[]string{"one"}, [][]int{{1, 2}}, 3}, + []any{ []string{"one"}, - []interface{}{ - []interface{}{ + []any{ + []any{ []int{1}, - []interface{}{2, []int{3}}, + []any{2, []int{3}}, }, []int{4, 5}, }, @@ -569,7 +569,7 @@ func BenchmarkFlatten(b *testing.B) { for depth := -1; depth <= 2; depth++ { for _, d := range data { b.Run(fmt.Sprintf("depth%d %T(%v)", depth, d, d), func(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { Flatten(d, depth) } }) @@ -578,42 +578,42 @@ func BenchmarkFlatten(b *testing.B) { } func TestOmit(t *testing.T) { - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "bar": true, "": "baz", } assert.EqualValues(t, in, Omit(in, "baz")) - expected := map[string]interface{}{ + expected := map[string]any{ "foo": "bar", "bar": true, } assert.EqualValues(t, expected, Omit(in, "")) - expected = map[string]interface{}{ + expected = map[string]any{ "": "baz", } assert.EqualValues(t, expected, Omit(in, "foo", "bar")) - assert.EqualValues(t, map[string]interface{}{}, Omit(in, "foo", "bar", "")) + assert.EqualValues(t, map[string]any{}, Omit(in, "foo", "bar", "")) } func TestPick(t *testing.T) { - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "bar": true, "": "baz", } - expected := map[string]interface{}{} + expected := map[string]any{} assert.EqualValues(t, expected, Pick(in, "baz")) - expected = map[string]interface{}{ + expected = map[string]any{ "": "baz", } assert.EqualValues(t, expected, Pick(in, "")) - expected = map[string]interface{}{ + expected = map[string]any{ "foo": "bar", "bar": true, } diff --git a/coll/index.go b/coll/index.go index ba815320..46402a51 100644 --- a/coll/index.go +++ b/coll/index.go @@ -14,7 +14,7 @@ import ( // will return an error if the key is not found. Note that the argument order is // different from the template function definition found in `funcs/coll.go` to // allow for variadic indexes. -func Index(v interface{}, keys ...interface{}) (interface{}, error) { +func Index(v any, keys ...any) (any, error) { item := reflect.ValueOf(v) item = indirectInterface(item) if !item.IsValid() { diff --git a/coll/index_test.go b/coll/index_test.go index 521e8cef..88993e93 100644 --- a/coll/index_test.go +++ b/coll/index_test.go @@ -8,28 +8,28 @@ import ( ) func TestIndex(t *testing.T) { - out, err := Index(map[string]interface{}{ + out, err := Index(map[string]any{ "foo": "bar", "baz": "qux", }, "foo") require.NoError(t, err) assert.Equal(t, "bar", out) - out, err = Index(map[string]interface{}{ + out, err = Index(map[string]any{ "foo": "bar", "baz": "qux", "quux": "corge", }, "foo", 2) require.NoError(t, err) assert.Equal(t, byte('r'), out) - out, err = Index([]interface{}{"foo", "bar", "baz"}, 2) + out, err = Index([]any{"foo", "bar", "baz"}, 2) require.NoError(t, err) assert.Equal(t, "baz", out) - out, err = Index([]interface{}{"foo", "bar", "baz"}, 2, 2) + out, err = Index([]any{"foo", "bar", "baz"}, 2, 2) require.NoError(t, err) assert.Equal(t, byte('z'), out) // error cases - out, err = Index([]interface{}{"foo", "bar", "baz"}, 0, 1, 2) + out, err = Index([]any{"foo", "bar", "baz"}, 0, 1, 2) require.Error(t, err) assert.Nil(t, out) @@ -41,7 +41,7 @@ func TestIndex(t *testing.T) { require.Error(t, err) assert.Nil(t, out) - out, err = Index(map[interface{}]string{nil: "foo", 2: "bar"}, "baz") + out, err = Index(map[any]string{nil: "foo", 2: "bar"}, "baz") require.Error(t, err) assert.Nil(t, out) diff --git a/coll/jq.go b/coll/jq.go index 16dc8f0e..fa7777ff 100644 --- a/coll/jq.go +++ b/coll/jq.go @@ -10,7 +10,7 @@ import ( ) // JQ - -func JQ(ctx context.Context, jqExpr string, in interface{}) (interface{}, error) { +func JQ(ctx context.Context, jqExpr string, in any) (any, error) { query, err := gojq.Parse(jqExpr) if err != nil { return nil, fmt.Errorf("jq parsing expression %q: %w", jqExpr, err) @@ -23,8 +23,8 @@ func JQ(ctx context.Context, jqExpr string, in interface{}) (interface{}, error) } iter := query.RunWithContext(ctx, in) - var out interface{} - a := []interface{}{} + var out any + a := []any{} for { v, ok := iter.Next() if !ok { @@ -44,12 +44,12 @@ func JQ(ctx context.Context, jqExpr string, in interface{}) (interface{}, error) return out, nil } -// jqConvertType converts the input to a map[string]interface{}, []interface{}, +// jqConvertType converts the input to a map[string]any, []any, // or other supported primitive JSON types. -func jqConvertType(in interface{}) (interface{}, error) { +func jqConvertType(in any) (any, error) { // if it's already a supported type, pass it through switch in.(type) { - case map[string]interface{}, []interface{}, + case map[string]any, []any, string, []byte, nil, bool, int, int8, int16, int32, int64, @@ -67,8 +67,8 @@ func jqConvertType(in interface{}) (interface{}, error) { value = value.Elem() } - mapType := reflect.TypeOf(map[string]interface{}{}) - sliceType := reflect.TypeOf([]interface{}{}) + mapType := reflect.TypeOf(map[string]any{}) + sliceType := reflect.TypeOf([]any{}) // if it can be converted to a map or slice, do that if inType.ConvertibleTo(mapType) { return value.Convert(mapType).Interface(), nil @@ -83,7 +83,7 @@ func jqConvertType(in interface{}) (interface{}, error) { if err != nil { return nil, fmt.Errorf("json marshal struct: %w", err) } - var m map[string]interface{} + var m map[string]any err = json.Unmarshal(b, &m) if err != nil { return nil, fmt.Errorf("json unmarshal struct: %w", err) diff --git a/coll/jq_test.go b/coll/jq_test.go index e4af3847..0d45fdfb 100644 --- a/coll/jq_test.go +++ b/coll/jq_test.go @@ -11,29 +11,29 @@ import ( func TestJQ(t *testing.T) { ctx := context.Background() - in := map[string]interface{}{ - "store": map[string]interface{}{ - "book": []interface{}{ - map[string]interface{}{ + in := map[string]any{ + "store": map[string]any{ + "book": []any{ + map[string]any{ "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95, }, - map[string]interface{}{ + map[string]any{ "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99, }, - map[string]interface{}{ + map[string]any{ "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99, }, - map[string]interface{}{ + map[string]any{ "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", @@ -41,7 +41,7 @@ func TestJQ(t *testing.T) { "price": 22.99, }, }, - "bicycle": map[string]interface{}{ + "bicycle": map[string]any{ "color": "red", "price": 19.95, }, @@ -76,14 +76,14 @@ func TestJQ(t *testing.T) { out, err = JQ(ctx, ".store.book[]|select(.price < 10.0 )", in) require.NoError(t, err) - expected := []interface{}{ - map[string]interface{}{ + expected := []any{ + map[string]any{ "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95, }, - map[string]interface{}{ + map[string]any{ "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", @@ -93,20 +93,20 @@ func TestJQ(t *testing.T) { } assert.EqualValues(t, expected, out) - in = map[string]interface{}{ - "a": map[string]interface{}{ - "aa": map[string]interface{}{ - "foo": map[string]interface{}{ - "aaa": map[string]interface{}{ - "aaaa": map[string]interface{}{ + in = map[string]any{ + "a": map[string]any{ + "aa": map[string]any{ + "foo": map[string]any{ + "aaa": map[string]any{ + "aaaa": map[string]any{ "bar": 1234, }, }, }, }, - "ab": map[string]interface{}{ - "aba": map[string]interface{}{ - "foo": map[string]interface{}{ + "ab": map[string]any{ + "aba": map[string]any{ + "foo": map[string]any{ "abaa": true, "abab": "baz", }, @@ -117,7 +117,7 @@ func TestJQ(t *testing.T) { out, err = JQ(ctx, `tostream|select((.[0]|index("foo")) and (.[0][-1]!="foo") and (.[1])) as $s|($s[0]|index("foo")+1) as $ind|($ind|truncate_stream($s)) as $newstream|$newstream|reduce . as [$p,$v] ({};setpath($p;$v))|add`, in) require.NoError(t, err) assert.Len(t, out, 3) - assert.Contains(t, out, map[string]interface{}{"aaaa": map[string]interface{}{"bar": 1234}}) + assert.Contains(t, out, map[string]any{"aaaa": map[string]any{"bar": 1234}}) assert.Contains(t, out, true) assert.Contains(t, out, "baz") } @@ -130,7 +130,7 @@ func TestJQ_typeConversions(t *testing.T) { } type storeType struct { Bicycle *bicycleType - safe interface{} + safe any } structIn := &storeType{ @@ -151,9 +151,9 @@ func TestJQ_typeConversions(t *testing.T) { _, err = JQ(ctx, ".*", structIn) require.Error(t, err) - // a type with an underlying type of map[string]interface{}, just like + // a type with an underlying type of map[string]any, just like // gomplate.tmplctx - type mapType map[string]interface{} + type mapType map[string]any out, err = JQ(ctx, ".foo", mapType{"foo": "bar"}) require.NoError(t, err) @@ -165,7 +165,7 @@ func TestJQ_typeConversions(t *testing.T) { assert.Equal(t, "bar", out) // underlying slice type - type sliceType []interface{} + type sliceType []any out, err = JQ(ctx, ".[1]", sliceType{"foo", "bar"}) require.NoError(t, err) @@ -216,9 +216,9 @@ func TestJQConvertType_passthroughTypes(t *testing.T) { _, err := jqConvertType(v) require.Error(t, err) - testdata := []interface{}{ - map[string]interface{}{"foo": 1234}, - []interface{}{"foo", "bar", "baz", 1, 2, 3}, + testdata := []any{ + map[string]any{"foo": 1234}, + []any{"foo", "bar", "baz", 1, 2, 3}, "foo", []byte("foo"), json.RawMessage(`{"foo": "bar"}`), diff --git a/coll/jsonpath.go b/coll/jsonpath.go index 78ec5689..210280b6 100644 --- a/coll/jsonpath.go +++ b/coll/jsonpath.go @@ -8,7 +8,7 @@ import ( ) // JSONPath - -func JSONPath(p string, in interface{}) (interface{}, error) { +func JSONPath(p string, in any) (any, error) { jp, err := parsePath(p) if err != nil { return nil, fmt.Errorf("couldn't parse JSONPath %s: %w", p, err) @@ -18,7 +18,7 @@ func JSONPath(p string, in interface{}) (interface{}, error) { return nil, fmt.Errorf("executing JSONPath failed: %w", err) } - var out interface{} + var out any if len(results) == 1 && len(results[0]) == 1 { v := results[0][0] out, err = extractResult(v) @@ -26,7 +26,7 @@ func JSONPath(p string, in interface{}) (interface{}, error) { return nil, err } } else { - a := []interface{}{} + a := []any{} for _, r := range results { for _, v := range r { o, err := extractResult(v) @@ -54,7 +54,7 @@ func parsePath(p string) (*jsonpath.JSONPath, error) { return jp, nil } -func extractResult(v reflect.Value) (interface{}, error) { +func extractResult(v reflect.Value) (any, error) { if v.CanInterface() { return v.Interface(), nil } diff --git a/coll/jsonpath_test.go b/coll/jsonpath_test.go index a8bf02de..147fc2ea 100644 --- a/coll/jsonpath_test.go +++ b/coll/jsonpath_test.go @@ -8,8 +8,8 @@ import ( ) type ( - m = map[string]interface{} - ar = []interface{} + m = map[string]any + ar = []any ) func TestJSONPath(t *testing.T) { @@ -127,7 +127,7 @@ func TestJSONPath(t *testing.T) { } type storeType struct { Bicycle *bicycleType - safe interface{} + safe any } structIn := &storeType{ diff --git a/config.go b/config.go index 21567c40..e35267c9 100644 --- a/config.go +++ b/config.go @@ -3,6 +3,7 @@ package gomplate import ( "fmt" "io" + "maps" "net/http" "os" "slices" @@ -148,7 +149,7 @@ func (c *Config) UnmarshalYAML(value *yaml.Node) error { // TODO: remove when we remove the deprecated array format for templates // // Deprecated: custom unmarshaling will be removed in the next version -func (c Config) MarshalYAML() (interface{}, error) { +func (c Config) MarshalYAML() (any, error) { aux := rawConfig{ DataSources: c.DataSources, Context: c.Context, @@ -196,9 +197,7 @@ func mergeDataSources(left, right DataSource) DataSource { if left.Header == nil { left.Header = right.Header } else { - for k, v := range right.Header { - left.Header[k] = v - } + maps.Copy(left.Header, right.Header) } return left } @@ -325,9 +324,7 @@ func (c *Config) MergeFrom(o *Config) *Config { c.Context = mergeDataSourceMaps(c.Context, o.Context) } if len(o.Plugins) > 0 { - for k, v := range o.Plugins { - c.Plugins[k] = v - } + maps.Copy(c.Plugins, o.Plugins) } return c @@ -393,7 +390,7 @@ func (c Config) validate() (err error) { return err } -func notTogether(names []string, values ...interface{}) error { +func notTogether(names []string, values ...any) error { found := "" for i, value := range values { if isZero(value) { @@ -408,7 +405,7 @@ func notTogether(names []string, values ...interface{}) error { return nil } -func mustTogether(left, right string, lValue, rValue interface{}) error { +func mustTogether(left, right string, lValue, rValue any) error { if !isZero(lValue) && isZero(rValue) { return fmt.Errorf("these options must be set together: '%s', '%s'", left, right) @@ -417,7 +414,7 @@ func mustTogether(left, right string, lValue, rValue interface{}) error { return nil } -func isZero(value interface{}) bool { +func isZero(value any) bool { switch v := value.(type) { case string: return v == "" diff --git a/context.go b/context.go index d84a2967..471e4ef3 100644 --- a/context.go +++ b/context.go @@ -10,7 +10,7 @@ import ( ) // context for templates -type tmplctx map[string]interface{} +type tmplctx map[string]any // Env - Map environment variables for use in a template func (c *tmplctx) Env() map[string]string { @@ -26,7 +26,7 @@ func (c *tmplctx) Env() map[string]string { func createTmplContext( ctx context.Context, aliases []string, sr datafs.DataSourceReader, -) (interface{}, error) { +) (any, error) { tctx := &tmplctx{} for _, a := range aliases { ct, b, err := sr.ReadSource(ctx, a) diff --git a/context_test.go b/context_test.go index a0985be9..72ccc62b 100644 --- a/context_test.go +++ b/context_test.go @@ -53,13 +53,13 @@ func TestCreateContext(t *testing.T) { require.NoError(t, err) assert.IsType(t, &tmplctx{}, c) tctx := c.(*tmplctx) - ds := ((*tctx)["foo"]).(map[string]interface{}) + ds := ((*tctx)["foo"]).(map[string]any) assert.Equal(t, "bar", ds["foo"]) t.Setenv("bar", "bar: baz") c, err = createTmplContext(ctx, []string{"."}, sr) require.NoError(t, err) - assert.IsType(t, map[string]interface{}{}, c) - ds = c.(map[string]interface{}) + assert.IsType(t, map[string]any{}, c) + ds = c.(map[string]any) assert.Equal(t, "baz", ds["bar"]) } diff --git a/conv/conv.go b/conv/conv.go index fd455244..223dd156 100644 --- a/conv/conv.go +++ b/conv/conv.go @@ -29,7 +29,7 @@ func Bool(in string) bool { // Possible non-boolean true values are: 1 or the strings "t", "true", or "yes" // (any capitalizations) // All other values are considered false. -func ToBool(in interface{}) bool { +func ToBool(in any) bool { if b, ok := in.(bool); ok { return b } @@ -60,7 +60,7 @@ func ToBool(in interface{}) bool { } // ToBools - -func ToBools(in ...interface{}) []bool { +func ToBools(in ...any) []bool { out := make([]bool, len(in)) for i, v := range in { out[i] = ToBool(v) @@ -71,7 +71,7 @@ func ToBools(in ...interface{}) []bool { // Slice creates a slice from a bunch of arguments // // Deprecated: use [github.com/hairyhenderson/gomplate/v4/coll.Slice] instead -func Slice(args ...interface{}) []interface{} { +func Slice(args ...any) []any { return args } @@ -80,14 +80,14 @@ func Slice(args ...interface{}) []interface{} { // // This is functionally identical to strings.Join, except that each element is // coerced to a string first -func Join(in interface{}, sep string) (out string, err error) { +func Join(in any, sep string) (out string, err error) { s, ok := in.([]string) if ok { return strings.Join(s, sep), nil } - var a []interface{} - a, ok = in.([]interface{}) + var a []any + a, ok = in.([]any) if !ok { a, err = iconv.InterfaceSlice(in) if err != nil { @@ -107,7 +107,7 @@ func Join(in interface{}, sep string) (out string, err error) { } // Has determines whether or not a given object has a property with the given key -func Has(in interface{}, key interface{}) bool { +func Has(in any, key any) bool { av := reflect.ValueOf(in) switch av.Kind() { @@ -116,7 +116,7 @@ func Has(in interface{}, key interface{}) bool { return av.MapIndex(kv).IsValid() case reflect.Slice, reflect.Array: l := av.Len() - for i := 0; i < l; i++ { + for i := range l { v := av.Index(i).Interface() if reflect.DeepEqual(v, key) { return true @@ -128,7 +128,7 @@ func Has(in interface{}, key interface{}) bool { } // ToString - -func ToString(in interface{}) string { +func ToString(in any) string { if in == nil { return "nil" } @@ -151,7 +151,7 @@ func ToString(in interface{}) string { } // ToStrings - -func ToStrings(in ...interface{}) []string { +func ToStrings(in ...any) []string { out := make([]string, len(in)) for i, v := range in { out[i] = ToString(v) @@ -184,7 +184,7 @@ func MustAtoi(s string) int { } // ToInt64 - convert input to an int64, if convertible. Otherwise, returns 0. -func ToInt64(v interface{}) (int64, error) { +func ToInt64(v any) (int64, error) { if str, ok := v.(string); ok { return strToInt64(str) } @@ -218,7 +218,7 @@ func ToInt64(v interface{}) (int64, error) { } // ToInt - -func ToInt(in interface{}) (int, error) { +func ToInt(in any) (int, error) { i, err := ToInt64(in) if err != nil { return 0, err @@ -236,7 +236,7 @@ func ToInt(in interface{}) (int, error) { } // ToInt64s - -func ToInt64s(in ...interface{}) ([]int64, error) { +func ToInt64s(in ...any) ([]int64, error) { out := make([]int64, len(in)) for i, v := range in { n, err := ToInt64(v) @@ -251,7 +251,7 @@ func ToInt64s(in ...interface{}) ([]int64, error) { } // ToInts - -func ToInts(in ...interface{}) ([]int, error) { +func ToInts(in ...any) ([]int, error) { out := make([]int, len(in)) for i, v := range in { n, err := ToInt(v) @@ -266,7 +266,7 @@ func ToInts(in ...interface{}) ([]int, error) { } // ToFloat64 - convert input to a float64, if convertible. Otherwise, errors. -func ToFloat64(v interface{}) (float64, error) { +func ToFloat64(v any) (float64, error) { if str, ok := v.(string); ok { return strToFloat64(str) } @@ -334,7 +334,7 @@ func strToFloat64(str string) (float64, error) { } // ToFloat64s - -func ToFloat64s(in ...interface{}) ([]float64, error) { +func ToFloat64s(in ...any) ([]float64, error) { out := make([]float64, len(in)) for i, v := range in { f, err := ToFloat64(v) @@ -352,8 +352,8 @@ func ToFloat64s(in ...interface{}) ([]float64, error) { // is provided, the last is used as the key, and an empty string is // set as the value. // All keys are converted to strings, regardless of input type. -func Dict(v ...interface{}) (map[string]interface{}, error) { - dict := map[string]interface{}{} +func Dict(v ...any) (map[string]any, error) { + dict := map[string]any{} lenv := len(v) for i := 0; i < lenv; i += 2 { key := ToString(v[i]) diff --git a/conv/conv_test.go b/conv/conv_test.go index 2ce0659a..5b986e48 100644 --- a/conv/conv_test.go +++ b/conv/conv_test.go @@ -42,22 +42,22 @@ func TestSlice(t *testing.T) { func TestJoin(t *testing.T) { testdata := []struct { - in interface{} + in any sep string out string }{ - {[]interface{}{"foo", "bar"}, ",", "foo,bar"}, - {[]interface{}{"foo", "bar"}, ",\n", "foo,\nbar"}, + {[]any{"foo", "bar"}, ",", "foo,bar"}, + {[]any{"foo", "bar"}, ",\n", "foo,\nbar"}, // Join handles all kinds of scalar types too... - {[]interface{}{42, uint64(18446744073709551615)}, "-", "42-18446744073709551615"}, + {[]any{42, uint64(18446744073709551615)}, "-", "42-18446744073709551615"}, {[]int{42, 100}, ",", "42,100"}, {[]int64{42, 100}, ",", "42,100"}, {[]uint64{42, 100}, ",", "42,100"}, {[]bool{true, false}, ",", "true,false"}, {[]float64{1, 2}, ",", "1,2"}, - {[]interface{}{1, "", true, 3.14, "foo", nil}, ",", "1,,true,3.14,foo,nil"}, + {[]any{1, "", true, 3.14, "foo", nil}, ",", "1,,true,3.14,foo,nil"}, // and best-effort with weird types - {[]interface{}{[]string{"foo"}, "bar"}, ",", "[foo],bar"}, + {[]any{[]string{"foo"}, "bar"}, ",", "[foo],bar"}, } for _, d := range testdata { out, err := Join(d.in, d.sep) @@ -67,24 +67,24 @@ func TestJoin(t *testing.T) { } func TestHas(t *testing.T) { - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", - "baz": map[string]interface{}{ + "baz": map[string]any{ "qux": "quux", }, } testdata := []struct { - in interface{} - key interface{} + in any + key any out bool }{ {in, "foo", true}, {in, "bar", false}, {in["baz"], "qux", true}, {[]string{"foo", "bar", "baz"}, "bar", true}, - {[]interface{}{"foo", "bar", "baz"}, "bar", true}, - {[]interface{}{"foo", "bar", "baz"}, 42, false}, + {[]any{"foo", "bar", "baz"}, "bar", true}, + {[]any{"foo", "bar", "baz"}, 42, false}, {[]int{1, 2, 42}, 42, true}, } @@ -321,13 +321,13 @@ func TestToInts(t *testing.T) { } func TestToFloat64(t *testing.T) { - z := []interface{}{nil, "", "foo"} + z := []any{nil, "", "foo"} for _, n := range z { _, err := ToFloat64(n) require.Error(t, err) } - z = []interface{}{0, 0.0, false, float32(0), "0", int64(0), uint(0), "0x0", "00", "0,000"} + z = []any{0, 0.0, false, float32(0), "0", int64(0), uint(0), "0x0", "00", "0,000"} for _, n := range z { actual, err := ToFloat64(n) require.NoError(t, err) @@ -338,14 +338,14 @@ func TestToFloat64(t *testing.T) { require.NoError(t, err) assert.InEpsilon(t, 1.0, actual, 1e-12) - z = []interface{}{42, 42.0, float32(42), "42", "42.0", uint8(42), "0x2A", "052"} + z = []any{42, 42.0, float32(42), "42", "42.0", uint8(42), "0x2A", "052"} for _, n := range z { actual, err = ToFloat64(n) require.NoError(t, err) assert.InEpsilon(t, 42.0, actual, 1e-12) } - z = []interface{}{1000.34, "1000.34", "1,000.34"} + z = []any{1000.34, "1000.34", "1,000.34"} for _, n := range z { actual, err = ToFloat64(n) require.NoError(t, err) @@ -382,7 +382,7 @@ func TestToString(t *testing.T) { var n *string testdata := []struct { - in interface{} + in any out string }{ {nil, "nil"}, @@ -414,7 +414,7 @@ func TestToString(t *testing.T) { } func TestToBool(t *testing.T) { - trueData := []interface{}{ + trueData := []any{ true, 1, int8(1), @@ -442,7 +442,7 @@ func TestToBool(t *testing.T) { assert.True(t, out) } - falseData := []interface{}{ + falseData := []any{ nil, false, 42, @@ -464,33 +464,33 @@ func TestToBool(t *testing.T) { func TestDict(t *testing.T) { testdata := []struct { - expected map[string]interface{} - args []interface{} + expected map[string]any + args []any }{ - {expected: map[string]interface{}{}}, + {expected: map[string]any{}}, { - args: []interface{}{}, - expected: map[string]interface{}{}, + args: []any{}, + expected: map[string]any{}, }, { - args: []interface{}{"foo"}, - expected: map[string]interface{}{"foo": ""}, + args: []any{"foo"}, + expected: map[string]any{"foo": ""}, }, { - args: []interface{}{42}, - expected: map[string]interface{}{"42": ""}, + args: []any{42}, + expected: map[string]any{"42": ""}, }, { - args: []interface{}{"foo", nil}, - expected: map[string]interface{}{"foo": nil}, + args: []any{"foo", nil}, + expected: map[string]any{"foo": nil}, }, { - args: []interface{}{"foo", "bar"}, - expected: map[string]interface{}{"foo": "bar"}, + args: []any{"foo", "bar"}, + expected: map[string]any{"foo": "bar"}, }, { - args: []interface{}{"foo", "bar", "baz", true}, - expected: map[string]interface{}{ + args: []any{"foo", "bar", "baz", true}, + expected: map[string]any{ "foo": "bar", "baz": true, }, diff --git a/conv/evalargs.go b/conv/evalargs.go index f7df2ec1..306de54f 100644 --- a/conv/evalargs.go +++ b/conv/evalargs.go @@ -13,7 +13,7 @@ var ( // printableValue returns the, possibly indirected, interface value inside v that // is best for a call to formatted printer. -func printableValue(v reflect.Value) (interface{}, bool) { +func printableValue(v reflect.Value) (any, bool) { if v.Kind() == reflect.Ptr { v, _ = indirect(v) // fmt.Fprint handles nil. } diff --git a/crypto/pbkdf2.go b/crypto/pbkdf2.go index 0cc44d7e..f7b9090a 100644 --- a/crypto/pbkdf2.go +++ b/crypto/pbkdf2.go @@ -2,17 +2,16 @@ package crypto import ( "crypto" + "crypto/pbkdf2" "crypto/sha1" //nolint: gosec "crypto/sha256" "crypto/sha512" "fmt" "hash" "sync" - - "golang.org/x/crypto/pbkdf2" ) -var hashFuncs = sync.OnceValue[map[crypto.Hash]func() hash.Hash](func() map[crypto.Hash]func() hash.Hash { +var hashFuncs = sync.OnceValue(func() map[crypto.Hash]func() hash.Hash { h := make(map[crypto.Hash]func() hash.Hash) h[crypto.SHA1] = sha1.New h[crypto.SHA224] = sha256.New224 @@ -53,5 +52,6 @@ func PBKDF2(password, salt []byte, iter, keylen int, hashFunc crypto.Hash) ([]by if !ok { return nil, fmt.Errorf("hashFunc not supported: %v", hashFunc) } - return pbkdf2.Key(password, salt, iter, keylen, h), nil + + return pbkdf2.Key(h, string(password), salt, iter, keylen) } diff --git a/docs-src/content/functions/coll.yml b/docs-src/content/functions/coll.yml index a540598d..2b96ad95 100644 --- a/docs-src/content/functions/coll.yml +++ b/docs-src/content/functions/coll.yml @@ -4,7 +4,7 @@ preamble: | These functions help manipulate and query collections of data, like lists (slices, or arrays) and maps (dictionaries). #### Implementation Note - For the functions that return an array, a Go `[]interface{}` is returned, regardless of whether or not the + For the functions that return an array, a Go `[]any` is returned, regardless of whether or not the input was a different type. funcs: - name: coll.Dict diff --git a/docs/content/functions/coll.md b/docs/content/functions/coll.md index f862a2e9..c7f01119 100644 --- a/docs/content/functions/coll.md +++ b/docs/content/functions/coll.md @@ -8,7 +8,7 @@ menu: These functions help manipulate and query collections of data, like lists (slices, or arrays) and maps (dictionaries). #### Implementation Note -For the functions that return an array, a Go `[]interface{}` is returned, regardless of whether or not the +For the functions that return an array, a Go `[]any` is returned, regardless of whether or not the input was a different type. ## `coll.Dict` diff --git a/funcs.go b/funcs.go index 93025f59..ea460432 100644 --- a/funcs.go +++ b/funcs.go @@ -2,6 +2,7 @@ package gomplate import ( "context" + "maps" "text/template" "github.com/hairyhenderson/gomplate/v4/internal/config" @@ -11,37 +12,30 @@ import ( // CreateFuncs - function mappings are created here func CreateFuncs(ctx context.Context) template.FuncMap { f := template.FuncMap{} - addToMap(f, funcs.CreateDataFuncs(ctx)) - addToMap(f, funcs.CreateAWSFuncs(ctx)) - addToMap(f, funcs.CreateGCPFuncs(ctx)) - addToMap(f, funcs.CreateBase64Funcs(ctx)) - addToMap(f, funcs.CreateNetFuncs(ctx)) - addToMap(f, funcs.CreateReFuncs(ctx)) - addToMap(f, funcs.CreateStringFuncs(ctx)) - addToMap(f, funcs.CreateEnvFuncs(ctx)) - addToMap(f, funcs.CreateConvFuncs(ctx)) - addToMap(f, funcs.CreateTimeFuncs(ctx)) - addToMap(f, funcs.CreateMathFuncs(ctx)) - addToMap(f, funcs.CreateCryptoFuncs(ctx)) - addToMap(f, funcs.CreateFileFuncs(ctx)) - addToMap(f, funcs.CreateFilePathFuncs(ctx)) - addToMap(f, funcs.CreatePathFuncs(ctx)) - addToMap(f, funcs.CreateSockaddrFuncs(ctx)) - addToMap(f, funcs.CreateTestFuncs(ctx)) - addToMap(f, funcs.CreateCollFuncs(ctx)) - addToMap(f, funcs.CreateUUIDFuncs(ctx)) - addToMap(f, funcs.CreateRandomFuncs(ctx)) - addToMap(f, funcs.CreateSemverFuncs(ctx)) + maps.Copy(f, funcs.CreateDataFuncs(ctx)) + maps.Copy(f, funcs.CreateAWSFuncs(ctx)) + maps.Copy(f, funcs.CreateGCPFuncs(ctx)) + maps.Copy(f, funcs.CreateBase64Funcs(ctx)) + maps.Copy(f, funcs.CreateNetFuncs(ctx)) + maps.Copy(f, funcs.CreateReFuncs(ctx)) + maps.Copy(f, funcs.CreateStringFuncs(ctx)) + maps.Copy(f, funcs.CreateEnvFuncs(ctx)) + maps.Copy(f, funcs.CreateConvFuncs(ctx)) + maps.Copy(f, funcs.CreateTimeFuncs(ctx)) + maps.Copy(f, funcs.CreateMathFuncs(ctx)) + maps.Copy(f, funcs.CreateCryptoFuncs(ctx)) + maps.Copy(f, funcs.CreateFileFuncs(ctx)) + maps.Copy(f, funcs.CreateFilePathFuncs(ctx)) + maps.Copy(f, funcs.CreatePathFuncs(ctx)) + maps.Copy(f, funcs.CreateSockaddrFuncs(ctx)) + maps.Copy(f, funcs.CreateTestFuncs(ctx)) + maps.Copy(f, funcs.CreateCollFuncs(ctx)) + maps.Copy(f, funcs.CreateUUIDFuncs(ctx)) + maps.Copy(f, funcs.CreateRandomFuncs(ctx)) + maps.Copy(f, funcs.CreateSemverFuncs(ctx)) return f } -// addToMap - add src's entries to dst -func addToMap(dst, src map[string]interface{}) { - for k, v := range src { - dst[k] = v - } -} - // SetExperimental enables experimental functions and features in the given // context. This must be done before creating functions. The set of experimental // features enabled by this is not fixed and will change over time. diff --git a/go.mod b/go.mod index c72d346a..f89e03d3 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module github.com/hairyhenderson/gomplate/v4 -go 1.23.4 +go 1.24.1 require ( cuelang.org/go v0.12.0 diff --git a/gomplate_test.go b/gomplate_test.go index 5b480dc9..8a4b05d9 100644 --- a/gomplate_test.go +++ b/gomplate_test.go @@ -171,7 +171,7 @@ func TestMappingNamer(t *testing.T) { reg := datafs.NewRegistry() tr := &renderer{ sr: datafs.NewSourceReader(reg), - funcs: map[string]interface{}{ + funcs: map[string]any{ "foo": func() string { return "foo" }, }, } diff --git a/internal/cmd/main_test.go b/internal/cmd/main_test.go index 6225e932..58519d6c 100644 --- a/internal/cmd/main_test.go +++ b/internal/cmd/main_test.go @@ -2,7 +2,6 @@ package cmd import ( "bytes" - "context" "strings" "testing" @@ -42,8 +41,7 @@ func TestOptionalExecArgs(t *testing.T) { } func TestRunMain(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() err := Main(ctx, []string{"-h"}, nil, nil, nil) require.NoError(t, err) @@ -60,8 +58,7 @@ func TestRunMain(t *testing.T) { } func TestPostRunExec(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() out := &bytes.Buffer{} err := postRunExec(ctx, []string{"cat"}, strings.NewReader("hello world"), out, out) diff --git a/internal/config/types.go b/internal/config/types.go index 022363f7..083b1c1e 100644 --- a/internal/config/types.go +++ b/internal/config/types.go @@ -73,7 +73,7 @@ func (t *Templates) unmarshalYAMLArray(value *yaml.Node) error { return nil } -func (t Templates) MarshalYAML() (interface{}, error) { +func (t Templates) MarshalYAML() (any, error) { type rawTemplate struct { Header http.Header `yaml:"header,omitempty,flow"` URL string `yaml:"url"` @@ -133,7 +133,7 @@ func (d *DataSource) UnmarshalYAML(value *yaml.Node) error { // MarshalYAML - satisfy the yaml.Marshaler interface - URLs aren't // well supported, and anyway we need to do some extra parsing -func (d DataSource) MarshalYAML() (interface{}, error) { +func (d DataSource) MarshalYAML() (any, error) { type raw struct { Header http.Header URL string diff --git a/internal/conv/conv.go b/internal/conv/conv.go index 3b2ca7c7..29dca28e 100644 --- a/internal/conv/conv.go +++ b/internal/conv/conv.go @@ -5,11 +5,11 @@ import ( "reflect" ) -// InterfaceSlice converts an array or slice of any type into an []interface{} +// InterfaceSlice converts an array or slice of any type into an []any // for use in functions that expect this. -func InterfaceSlice(slice interface{}) ([]interface{}, error) { - // avoid all this nonsense if this is already a []interface{}... - if s, ok := slice.([]interface{}); ok { +func InterfaceSlice(slice any) ([]any, error) { + // avoid all this nonsense if this is already a []any... + if s, ok := slice.([]any); ok { return s, nil } s := reflect.ValueOf(slice) @@ -17,8 +17,8 @@ func InterfaceSlice(slice interface{}) ([]interface{}, error) { switch kind { case reflect.Slice, reflect.Array: l := s.Len() - ret := make([]interface{}, l) - for i := 0; i < l; i++ { + ret := make([]any, l) + for i := range l { ret[i] = s.Index(i).Interface() } return ret, nil diff --git a/internal/conv/conv_test.go b/internal/conv/conv_test.go index c83c8dd0..f2542383 100644 --- a/internal/conv/conv_test.go +++ b/internal/conv/conv_test.go @@ -9,14 +9,14 @@ import ( func TestInterfaceSlice(t *testing.T) { data := []struct { - in, expected interface{} + in, expected any }{ - {[]int{1, 2, 3}, []interface{}{1, 2, 3}}, - {[3]int{1, 2, 3}, []interface{}{1, 2, 3}}, - {[]string{"foo", "bar", "baz"}, []interface{}{"foo", "bar", "baz"}}, - {[3]string{"foo", "bar", "baz"}, []interface{}{"foo", "bar", "baz"}}, - {[]interface{}{[]string{}, []int{1, 2}, 3}, []interface{}{[]string{}, []int{1, 2}, 3}}, - {[3]interface{}{[]string{}, []int{1, 2}, 3}, []interface{}{[]string{}, []int{1, 2}, 3}}, + {[]int{1, 2, 3}, []any{1, 2, 3}}, + {[3]int{1, 2, 3}, []any{1, 2, 3}}, + {[]string{"foo", "bar", "baz"}, []any{"foo", "bar", "baz"}}, + {[3]string{"foo", "bar", "baz"}, []any{"foo", "bar", "baz"}}, + {[]any{[]string{}, []int{1, 2}, 3}, []any{[]string{}, []int{1, 2}, 3}}, + {[3]any{[]string{}, []int{1, 2}, 3}, []any{[]string{}, []int{1, 2}, 3}}, } for _, d := range data { @@ -30,18 +30,18 @@ func TestInterfaceSlice(t *testing.T) { } func BenchmarkInterfaceSlice(b *testing.B) { - data := []interface{}{ + data := []any{ []int{1, 2, 3}, [3]int{1, 2, 3}, []string{"foo", "bar", "baz", "foo", "bar", "baz", "foo", "bar", "baz", "foo", "bar", "baz"}, [12]string{"foo", "bar", "baz", "foo", "bar", "baz", "foo", "bar", "baz", "foo", "bar", "baz"}, - []interface{}{[]string{}, []int{1, 2}, 3}, - [3]interface{}{[]string{}, []int{1, 2}, 3}, + []any{[]string{}, []int{1, 2}, 3}, + [3]any{[]string{}, []int{1, 2}, 3}, } for _, d := range data { b.Run(fmt.Sprintf("%T(%v)", d, d), func(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { InterfaceSlice(d) } }) diff --git a/internal/datafs/envfs.go b/internal/datafs/envfs.go index 0a8d82c4..6418fcd9 100644 --- a/internal/datafs/envfs.go +++ b/internal/datafs/envfs.go @@ -194,7 +194,7 @@ func (fi staticFileInfo) Mode() fs.FileMode { return fi.mode } func (fi *staticFileInfo) ModTime() time.Time { return fi.modTime } func (fi staticFileInfo) Name() string { return fi.name } func (fi staticFileInfo) Size() int64 { return fi.size } -func (fi staticFileInfo) Sys() interface{} { return nil } +func (fi staticFileInfo) Sys() any { return nil } func (fi *staticFileInfo) Info() (fs.FileInfo, error) { return fi, nil } func (fi staticFileInfo) Type() fs.FileMode { return fi.Mode().Type() } diff --git a/internal/datafs/mergefs.go b/internal/datafs/mergefs.go index 1559b5fb..4c10fb1d 100644 --- a/internal/datafs/mergefs.go +++ b/internal/datafs/mergefs.go @@ -264,7 +264,7 @@ func (f *mergeFile) readSubFile(sf subFile) (map[string]any, error) { return sfData, nil } -func mergeData(data []map[string]interface{}) ([]byte, error) { +func mergeData(data []map[string]any) ([]byte, error) { dst := data[0] data = data[1:] diff --git a/internal/datafs/mergefs_test.go b/internal/datafs/mergefs_test.go index 012c5a95..d03c63d5 100644 --- a/internal/datafs/mergefs_test.go +++ b/internal/datafs/mergefs_test.go @@ -97,59 +97,59 @@ func wdForTest(t *testing.T) string { } func TestMergeData(t *testing.T) { - def := map[string]interface{}{ + def := map[string]any{ "f": true, "t": false, "z": "def", } - out, err := mergeData([]map[string]interface{}{def}) + out, err := mergeData([]map[string]any{def}) require.NoError(t, err) assert.Equal(t, "f: true\nt: false\nz: def\n", string(out)) - over := map[string]interface{}{ + over := map[string]any{ "f": false, "t": true, "z": "over", } - out, err = mergeData([]map[string]interface{}{over, def}) + out, err = mergeData([]map[string]any{over, def}) require.NoError(t, err) assert.Equal(t, "f: false\nt: true\nz: over\n", string(out)) - over = map[string]interface{}{ + over = map[string]any{ "f": false, "t": true, "z": "over", - "m": map[string]interface{}{ + "m": map[string]any{ "a": "aaa", }, } - out, err = mergeData([]map[string]interface{}{over, def}) + out, err = mergeData([]map[string]any{over, def}) require.NoError(t, err) assert.Equal(t, "f: false\nm:\n a: aaa\nt: true\nz: over\n", string(out)) - uber := map[string]interface{}{ + uber := map[string]any{ "z": "über", } - out, err = mergeData([]map[string]interface{}{uber, over, def}) + out, err = mergeData([]map[string]any{uber, over, def}) require.NoError(t, err) assert.Equal(t, "f: false\nm:\n a: aaa\nt: true\nz: über\n", string(out)) - uber = map[string]interface{}{ + uber = map[string]any{ "m": "notamap", - "z": map[string]interface{}{ + "z": map[string]any{ "b": "bbb", }, } - out, err = mergeData([]map[string]interface{}{uber, over, def}) + out, err = mergeData([]map[string]any{uber, over, def}) require.NoError(t, err) assert.Equal(t, "f: false\nm: notamap\nt: true\nz:\n b: bbb\n", string(out)) - uber = map[string]interface{}{ - "m": map[string]interface{}{ + uber = map[string]any{ + "m": map[string]any{ "b": "bbb", }, } - out, err = mergeData([]map[string]interface{}{uber, over, def}) + out, err = mergeData([]map[string]any{uber, over, def}) require.NoError(t, err) assert.Equal(t, "f: false\nm:\n a: aaa\n b: bbb\nt: true\nz: over\n", string(out)) } diff --git a/internal/datafs/reader_test.go b/internal/datafs/reader_test.go index 740cfa53..dbb37edc 100644 --- a/internal/datafs/reader_test.go +++ b/internal/datafs/reader_test.go @@ -127,7 +127,7 @@ func BenchmarkResolveURL(b *testing.B) { for _, a := range args { b.Run(fmt.Sprintf("base=%s_rel=%s", &a.url, a.rel), func(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { _, _ = resolveURL(a.url, a.rel) } }) diff --git a/internal/datafs/stdinfs_test.go b/internal/datafs/stdinfs_test.go index 8b0e0598..ba14483f 100644 --- a/internal/datafs/stdinfs_test.go +++ b/internal/datafs/stdinfs_test.go @@ -104,7 +104,7 @@ func TestStdinFS(t *testing.T) { ctx := ContextWithStdin(context.Background(), bytes.NewReader(content)) fsys = fsimpl.WithContextFS(ctx, fsys) - for i := 0; i < 3; i++ { + for i := range 3 { f, err := fsys.Open("foo") require.NoError(t, err) @@ -118,7 +118,7 @@ func TestStdinFS(t *testing.T) { ctx := ContextWithStdin(context.Background(), bytes.NewReader(content)) fsys = fsimpl.WithContextFS(ctx, fsys) - for i := 0; i < 3; i++ { + for i := range 3 { b, err := fs.ReadFile(fsys, "foo") require.NoError(t, err) require.Equal(t, content, b, "read %d failed", i) diff --git a/internal/funcs/aws.go b/internal/funcs/aws.go index 01e225ca..891e1a3b 100644 --- a/internal/funcs/aws.go +++ b/internal/funcs/aws.go @@ -9,15 +9,15 @@ import ( ) // CreateAWSFuncs - -func CreateAWSFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateAWSFuncs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &Funcs{ ctx: ctx, awsopts: aws.GetClientOptions(), } - f["aws"] = func() interface{} { return ns } + f["aws"] = func() any { return ns } // global aliases - for backwards compatibility f["ec2meta"] = ns.EC2Meta @@ -74,13 +74,13 @@ func (a *Funcs) EC2Tags() (map[string]string, error) { } // KMSEncrypt - -func (a *Funcs) KMSEncrypt(keyID, plaintext interface{}) (string, error) { +func (a *Funcs) KMSEncrypt(keyID, plaintext any) (string, error) { a.kmsInit.Do(a.initKMS) return a.kms.Encrypt(conv.ToString(keyID), conv.ToString(plaintext)) } // KMSDecrypt - -func (a *Funcs) KMSDecrypt(ciphertext interface{}) (string, error) { +func (a *Funcs) KMSDecrypt(ciphertext any) (string, error) { a.kmsInit.Do(a.initKMS) return a.kms.Decrypt(conv.ToString(ciphertext)) } diff --git a/internal/funcs/aws_test.go b/internal/funcs/aws_test.go index 2a1efc5d..396d7826 100644 --- a/internal/funcs/aws_test.go +++ b/internal/funcs/aws_test.go @@ -12,14 +12,14 @@ import ( func TestCreateAWSFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateAWSFuncs(ctx) - actual := fmap["aws"].(func() interface{}) + actual := fmap["aws"].(func() any) assert.Equal(t, ctx, actual().(*Funcs).ctx) }) @@ -38,7 +38,7 @@ func TestAWSFuncs(t *testing.T) { assert.Equal(t, "unknown", must(af.EC2Region())) } -func must(r interface{}, err error) interface{} { +func must(r any, err error) any { if err != nil { panic(err) } diff --git a/internal/funcs/base64.go b/internal/funcs/base64.go index ba79a1d1..b7c86657 100644 --- a/internal/funcs/base64.go +++ b/internal/funcs/base64.go @@ -8,11 +8,11 @@ import ( ) // CreateBase64Funcs - -func CreateBase64Funcs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateBase64Funcs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &Base64Funcs{ctx} - f["base64"] = func() interface{} { return ns } + f["base64"] = func() any { return ns } return f } @@ -23,19 +23,19 @@ type Base64Funcs struct { } // Encode - -func (Base64Funcs) Encode(in interface{}) (string, error) { +func (Base64Funcs) Encode(in any) (string, error) { b := toBytes(in) return base64.Encode(b) } // Decode - -func (Base64Funcs) Decode(in interface{}) (string, error) { +func (Base64Funcs) Decode(in any) (string, error) { out, err := base64.Decode(conv.ToString(in)) return string(out), err } // DecodeBytes - -func (Base64Funcs) DecodeBytes(in interface{}) ([]byte, error) { +func (Base64Funcs) DecodeBytes(in any) ([]byte, error) { out, err := base64.Decode(conv.ToString(in)) return out, err } @@ -44,7 +44,7 @@ type byter interface { Bytes() []byte } -func toBytes(in interface{}) []byte { +func toBytes(in any) []byte { if in == nil { return []byte{} } diff --git a/internal/funcs/base64_test.go b/internal/funcs/base64_test.go index f0cca886..425a1218 100644 --- a/internal/funcs/base64_test.go +++ b/internal/funcs/base64_test.go @@ -13,14 +13,14 @@ import ( func TestCreateBase64Funcs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateBase64Funcs(ctx) - actual := fmap["base64"].(func() interface{}) + actual := fmap["base64"].(func() any) assert.Equal(t, ctx, actual().(*Base64Funcs).ctx) }) @@ -63,7 +63,7 @@ func TestToBytes(t *testing.T) { } func BenchmarkToBytes(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { b.StopTimer() buf := &bytes.Buffer{} buf.WriteString("hi") diff --git a/internal/funcs/coll.go b/internal/funcs/coll.go index 0f87239d..c32c2ba6 100644 --- a/internal/funcs/coll.go +++ b/internal/funcs/coll.go @@ -13,11 +13,11 @@ import ( ) // CreateCollFuncs - -func CreateCollFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateCollFuncs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &CollFuncs{ctx} - f["coll"] = func() interface{} { return ns } + f["coll"] = func() any { return ns } f["has"] = ns.Has f["slice"] = ns.deprecatedSlice @@ -44,13 +44,13 @@ type CollFuncs struct { } // Slice - -func (CollFuncs) Slice(args ...interface{}) []interface{} { +func (CollFuncs) Slice(args ...any) []any { return coll.Slice(args...) } // deprecatedSlice - // Deprecated: use coll.Slice instead -func (f *CollFuncs) deprecatedSlice(args ...interface{}) []interface{} { +func (f *CollFuncs) deprecatedSlice(args ...any) []any { deprecated.WarnDeprecated(f.ctx, "the 'slice' alias for coll.Slice is deprecated - use coll.Slice instead") return coll.Slice(args...) } @@ -61,7 +61,7 @@ func (CollFuncs) GoSlice(item reflect.Value, indexes ...reflect.Value) (reflect. } // Has - -func (CollFuncs) Has(in interface{}, key string) bool { +func (CollFuncs) Has(in any, key string) bool { return coll.Has(in, key) } @@ -70,7 +70,7 @@ func (CollFuncs) Has(in interface{}, key string) bool { // the arguments are ordered differently for pipeline compatibility. Also, this // function is more strict, and will return an error when the value doesn't // contain the given key. -func (CollFuncs) Index(args ...interface{}) (interface{}, error) { +func (CollFuncs) Index(args ...any) (any, error) { if len(args) < 2 { return nil, fmt.Errorf("wrong number of args: wanted at least 2, got %d", len(args)) } @@ -82,50 +82,50 @@ func (CollFuncs) Index(args ...interface{}) (interface{}, error) { } // Dict - -func (CollFuncs) Dict(in ...interface{}) (map[string]interface{}, error) { +func (CollFuncs) Dict(in ...any) (map[string]any, error) { return coll.Dict(in...) } // Keys - -func (CollFuncs) Keys(in ...map[string]interface{}) ([]string, error) { +func (CollFuncs) Keys(in ...map[string]any) ([]string, error) { return coll.Keys(in...) } // Values - -func (CollFuncs) Values(in ...map[string]interface{}) ([]interface{}, error) { +func (CollFuncs) Values(in ...map[string]any) ([]any, error) { return coll.Values(in...) } // Append - -func (CollFuncs) Append(v interface{}, list interface{}) ([]interface{}, error) { +func (CollFuncs) Append(v any, list any) ([]any, error) { return coll.Append(v, list) } // Prepend - -func (CollFuncs) Prepend(v interface{}, list interface{}) ([]interface{}, error) { +func (CollFuncs) Prepend(v any, list any) ([]any, error) { return coll.Prepend(v, list) } // Uniq - -func (CollFuncs) Uniq(in interface{}) ([]interface{}, error) { +func (CollFuncs) Uniq(in any) ([]any, error) { return coll.Uniq(in) } // Reverse - -func (CollFuncs) Reverse(in interface{}) ([]interface{}, error) { +func (CollFuncs) Reverse(in any) ([]any, error) { return coll.Reverse(in) } // Merge - -func (CollFuncs) Merge(dst map[string]interface{}, src ...map[string]interface{}) (map[string]interface{}, error) { +func (CollFuncs) Merge(dst map[string]any, src ...map[string]any) (map[string]any, error) { return coll.Merge(dst, src...) } // Sort - -func (CollFuncs) Sort(args ...interface{}) ([]interface{}, error) { +func (CollFuncs) Sort(args ...any) ([]any, error) { var ( key string - list interface{} + list any ) if len(args) == 0 || len(args) > 2 { return nil, fmt.Errorf("wrong number of args: wanted 1 or 2, got %d", len(args)) @@ -141,17 +141,17 @@ func (CollFuncs) Sort(args ...interface{}) ([]interface{}, error) { } // JSONPath - -func (CollFuncs) JSONPath(p string, in interface{}) (interface{}, error) { +func (CollFuncs) JSONPath(p string, in any) (any, error) { return coll.JSONPath(p, in) } // JQ - -func (f *CollFuncs) JQ(jqExpr string, in interface{}) (interface{}, error) { +func (f *CollFuncs) JQ(jqExpr string, in any) (any, error) { return coll.JQ(f.ctx, jqExpr, in) } // Flatten - -func (CollFuncs) Flatten(args ...interface{}) ([]interface{}, error) { +func (CollFuncs) Flatten(args ...any) ([]any, error) { if len(args) == 0 || len(args) > 2 { return nil, fmt.Errorf("wrong number of args: wanted 1 or 2, got %d", len(args)) } @@ -172,22 +172,22 @@ func (CollFuncs) Flatten(args ...interface{}) ([]interface{}, error) { return coll.Flatten(list, depth) } -func pickOmitArgs(args ...interface{}) (map[string]interface{}, []string, error) { +func pickOmitArgs(args ...any) (map[string]any, []string, error) { if len(args) <= 1 { return nil, nil, fmt.Errorf("wrong number of args: wanted 2 or more, got %d", len(args)) } - m, ok := args[len(args)-1].(map[string]interface{}) + m, ok := args[len(args)-1].(map[string]any) if !ok { - return nil, nil, fmt.Errorf("wrong map type: must be map[string]interface{}, got %T", args[len(args)-1]) + return nil, nil, fmt.Errorf("wrong map type: must be map[string]any, got %T", args[len(args)-1]) } // special-case - if there's only one key and it's a slice, expand it if len(args) == 2 { if reflect.TypeOf(args[0]).Kind() == reflect.Slice { sl := reflect.ValueOf(args[0]) - expandedArgs := make([]interface{}, sl.Len()+1) - for i := 0; i < sl.Len(); i++ { + expandedArgs := make([]any, sl.Len()+1) + for i := range sl.Len() { expandedArgs[i] = sl.Index(i).Interface() } expandedArgs[len(expandedArgs)-1] = m @@ -207,7 +207,7 @@ func pickOmitArgs(args ...interface{}) (map[string]interface{}, []string, error) } // Pick - -func (CollFuncs) Pick(args ...interface{}) (map[string]interface{}, error) { +func (CollFuncs) Pick(args ...any) (map[string]any, error) { m, keys, err := pickOmitArgs(args...) if err != nil { return nil, err @@ -216,7 +216,7 @@ func (CollFuncs) Pick(args ...interface{}) (map[string]interface{}, error) { } // Omit - -func (CollFuncs) Omit(args ...interface{}) (map[string]interface{}, error) { +func (CollFuncs) Omit(args ...any) (map[string]any, error) { m, keys, err := pickOmitArgs(args...) if err != nil { return nil, err @@ -225,14 +225,14 @@ func (CollFuncs) Omit(args ...interface{}) (map[string]interface{}, error) { } // Set - -func (CollFuncs) Set(key string, value interface{}, m map[string]interface{}) (map[string]interface{}, error) { +func (CollFuncs) Set(key string, value any, m map[string]any) (map[string]any, error) { m[key] = value return m, nil } // Unset - -func (CollFuncs) Unset(key string, m map[string]interface{}) (map[string]interface{}, error) { +func (CollFuncs) Unset(key string, m map[string]any) (map[string]any, error) { delete(m, key) return m, nil diff --git a/internal/funcs/coll_test.go b/internal/funcs/coll_test.go index b075d078..86e53e65 100644 --- a/internal/funcs/coll_test.go +++ b/internal/funcs/coll_test.go @@ -13,14 +13,14 @@ import ( func TestCreateCollFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateCollFuncs(ctx) - actual := fmap["coll"].(func() interface{}) + actual := fmap["coll"].(func() any) assert.Equal(t, ctx, actual().(*CollFuncs).ctx) }) @@ -38,13 +38,13 @@ func TestFlatten(t *testing.T) { _, err = c.Flatten(42) require.Error(t, err) - out, err := c.Flatten([]interface{}{1, []interface{}{[]int{2}, 3}}) + out, err := c.Flatten([]any{1, []any{[]int{2}, 3}}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{1, 2, 3}, out) + assert.EqualValues(t, []any{1, 2, 3}, out) - out, err = c.Flatten(1, []interface{}{1, []interface{}{[]int{2}, 3}}) + out, err = c.Flatten(1, []any{1, []any{[]int{2}, 3}}) require.NoError(t, err) - assert.EqualValues(t, []interface{}{1, []int{2}, 3}, out) + assert.EqualValues(t, []any{1, []int{2}, 3}, out) } func TestPick(t *testing.T) { @@ -64,19 +64,19 @@ func TestPick(t *testing.T) { _, err = c.Pick("foo", "bar") require.Error(t, err) - _, err = c.Pick(map[string]interface{}{}, "foo", "bar", map[string]interface{}{}) + _, err = c.Pick(map[string]any{}, "foo", "bar", map[string]any{}) require.Error(t, err) - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "bar": true, "": "baz", } out, err := c.Pick("baz", in) require.NoError(t, err) - assert.EqualValues(t, map[string]interface{}{}, out) + assert.EqualValues(t, map[string]any{}, out) - expected := map[string]interface{}{ + expected := map[string]any{ "foo": "bar", "bar": true, } @@ -84,7 +84,7 @@ func TestPick(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, out) - expected = map[string]interface{}{ + expected = map[string]any{ "": "baz", } out, err = c.Pick("", in) @@ -98,14 +98,14 @@ func TestPick(t *testing.T) { t.Run("supports slice key", func(t *testing.T) { t.Parallel() - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "bar": true, "": "baz", } out, err := c.Pick([]string{"foo", "bar"}, in) require.NoError(t, err) - assert.EqualValues(t, map[string]interface{}{"foo": "bar", "bar": true}, out) + assert.EqualValues(t, map[string]any{"foo": "bar", "bar": true}, out) }) } @@ -126,10 +126,10 @@ func TestOmit(t *testing.T) { _, err = c.Omit("foo", "bar") require.Error(t, err) - _, err = c.Omit(map[string]interface{}{}, "foo", "bar", map[string]interface{}{}) + _, err = c.Omit(map[string]any{}, "foo", "bar", map[string]any{}) require.Error(t, err) - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "bar": true, "": "baz", @@ -138,7 +138,7 @@ func TestOmit(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, in, out) - expected := map[string]interface{}{ + expected := map[string]any{ "foo": "bar", "bar": true, } @@ -146,7 +146,7 @@ func TestOmit(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, out) - expected = map[string]interface{}{ + expected = map[string]any{ "": "baz", } out, err = c.Omit("foo", "bar", in) @@ -155,32 +155,32 @@ func TestOmit(t *testing.T) { out, err = c.Omit("foo", "bar", "", in) require.NoError(t, err) - assert.EqualValues(t, map[string]interface{}{}, out) + assert.EqualValues(t, map[string]any{}, out) t.Run("supports slice of strings", func(t *testing.T) { t.Parallel() - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "bar": true, "": "baz", } out, err := c.Omit([]string{"foo", "bar"}, in) require.NoError(t, err) - assert.EqualValues(t, map[string]interface{}{"": "baz"}, out) + assert.EqualValues(t, map[string]any{"": "baz"}, out) }) - t.Run("supports slice of interface{}", func(t *testing.T) { + t.Run("supports slice of any", func(t *testing.T) { t.Parallel() - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "bar": true, "": "baz", } - out, err := c.Omit([]interface{}{"foo", "bar"}, in) + out, err := c.Omit([]any{"foo", "bar"}, in) require.NoError(t, err) - assert.EqualValues(t, map[string]interface{}{"": "baz"}, out) + assert.EqualValues(t, map[string]any{"": "baz"}, out) }) } @@ -198,8 +198,8 @@ func TestGoSlice(t *testing.T) { require.Error(t, err) // invalid index type - in = reflect.ValueOf([]interface{}{1}) - _, err = c.GoSlice(in, reflect.ValueOf([]interface{}{[]int{2}})) + in = reflect.ValueOf([]any{1}) + _, err = c.GoSlice(in, reflect.ValueOf([]any{[]int{2}})) require.Error(t, err) // valid slice, no slicing @@ -222,15 +222,15 @@ func TestCollFuncs_Set(t *testing.T) { c := &CollFuncs{} - m := map[string]interface{}{"foo": "bar"} + m := map[string]any{"foo": "bar"} out, err := c.Set("foo", "baz", m) require.NoError(t, err) - assert.EqualValues(t, map[string]interface{}{"foo": "baz"}, out) + assert.EqualValues(t, map[string]any{"foo": "baz"}, out) // m was modified so foo is now baz out, err = c.Set("bar", "baz", m) require.NoError(t, err) - assert.EqualValues(t, map[string]interface{}{"foo": "baz", "bar": "baz"}, out) + assert.EqualValues(t, map[string]any{"foo": "baz", "bar": "baz"}, out) } func TestCollFuncs_Unset(t *testing.T) { @@ -238,7 +238,7 @@ func TestCollFuncs_Unset(t *testing.T) { c := &CollFuncs{} - m := map[string]interface{}{"foo": "bar"} + m := map[string]any{"foo": "bar"} out, err := c.Unset("foo", m) require.NoError(t, err) assert.Empty(t, out) diff --git a/internal/funcs/conv.go b/internal/funcs/conv.go index 67fd3b9f..5d6ba8f7 100644 --- a/internal/funcs/conv.go +++ b/internal/funcs/conv.go @@ -11,11 +11,11 @@ import ( ) // CreateConvFuncs - -func CreateConvFuncs(ctx context.Context) map[string]interface{} { +func CreateConvFuncs(ctx context.Context) map[string]any { ns := &ConvFuncs{ctx} - f := map[string]interface{}{} - f["conv"] = func() interface{} { return ns } + f := map[string]any{} + f["conv"] = func() any { return ns } f["urlParse"] = ns.URL f["bool"] = ns.Bool @@ -32,93 +32,93 @@ type ConvFuncs struct { // Bool - // // Deprecated: use [ToBool] instead -func (f *ConvFuncs) Bool(s interface{}) bool { +func (f *ConvFuncs) Bool(s any) bool { deprecated.WarnDeprecated(f.ctx, "conv.Bool is deprecated - use conv.ToBool instead") return conv.Bool(conv.ToString(s)) } // ToBool - -func (ConvFuncs) ToBool(in interface{}) bool { +func (ConvFuncs) ToBool(in any) bool { return conv.ToBool(in) } // ToBools - -func (ConvFuncs) ToBools(in ...interface{}) []bool { +func (ConvFuncs) ToBools(in ...any) []bool { return conv.ToBools(in...) } // Join - -func (ConvFuncs) Join(in interface{}, sep string) (string, error) { +func (ConvFuncs) Join(in any, sep string) (string, error) { return conv.Join(in, sep) } // ParseInt - -func (ConvFuncs) ParseInt(s interface{}, base, bitSize int) (int64, error) { +func (ConvFuncs) ParseInt(s any, base, bitSize int) (int64, error) { return strconv.ParseInt(conv.ToString(s), base, bitSize) } // ParseFloat - -func (ConvFuncs) ParseFloat(s interface{}, bitSize int) (float64, error) { +func (ConvFuncs) ParseFloat(s any, bitSize int) (float64, error) { return strconv.ParseFloat(conv.ToString(s), bitSize) } // ParseUint - -func (ConvFuncs) ParseUint(s interface{}, base, bitSize int) (uint64, error) { +func (ConvFuncs) ParseUint(s any, base, bitSize int) (uint64, error) { return strconv.ParseUint(conv.ToString(s), base, bitSize) } // Atoi - -func (ConvFuncs) Atoi(s interface{}) (int, error) { +func (ConvFuncs) Atoi(s any) (int, error) { return strconv.Atoi(conv.ToString(s)) } // URL - -func (ConvFuncs) URL(s interface{}) (*url.URL, error) { +func (ConvFuncs) URL(s any) (*url.URL, error) { return url.Parse(conv.ToString(s)) } // ToInt64 - -func (ConvFuncs) ToInt64(in interface{}) (int64, error) { +func (ConvFuncs) ToInt64(in any) (int64, error) { return conv.ToInt64(in) } // ToInt - -func (ConvFuncs) ToInt(in interface{}) (int, error) { +func (ConvFuncs) ToInt(in any) (int, error) { return conv.ToInt(in) } // ToInt64s - -func (ConvFuncs) ToInt64s(in ...interface{}) ([]int64, error) { +func (ConvFuncs) ToInt64s(in ...any) ([]int64, error) { return conv.ToInt64s(in...) } // ToInts - -func (ConvFuncs) ToInts(in ...interface{}) ([]int, error) { +func (ConvFuncs) ToInts(in ...any) ([]int, error) { return conv.ToInts(in...) } // ToFloat64 - -func (ConvFuncs) ToFloat64(in interface{}) (float64, error) { +func (ConvFuncs) ToFloat64(in any) (float64, error) { return conv.ToFloat64(in) } // ToFloat64s - -func (ConvFuncs) ToFloat64s(in ...interface{}) ([]float64, error) { +func (ConvFuncs) ToFloat64s(in ...any) ([]float64, error) { return conv.ToFloat64s(in...) } // ToString - -func (ConvFuncs) ToString(in interface{}) string { +func (ConvFuncs) ToString(in any) string { return conv.ToString(in) } // ToStrings - -func (ConvFuncs) ToStrings(in ...interface{}) []string { +func (ConvFuncs) ToStrings(in ...any) []string { return conv.ToStrings(in...) } // Default - -func (ConvFuncs) Default(def, in interface{}) interface{} { +func (ConvFuncs) Default(def, in any) any { if truth, ok := template.IsTrue(in); truth && ok { return in } diff --git a/internal/funcs/conv_test.go b/internal/funcs/conv_test.go index 51bbba8b..2fd23eaa 100644 --- a/internal/funcs/conv_test.go +++ b/internal/funcs/conv_test.go @@ -12,14 +12,14 @@ import ( func TestCreateConvFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateConvFuncs(ctx) - actual := fmap["conv"].(func() interface{}) + actual := fmap["conv"].(func() any) assert.Equal(t, ctx, actual().(*ConvFuncs).ctx) }) @@ -33,7 +33,7 @@ func TestDefault(t *testing.T) { c := &ConvFuncs{} def := "DEFAULT" data := []struct { - val interface{} + val any empty bool }{ {0, true}, diff --git a/internal/funcs/crypto.go b/internal/funcs/crypto.go index 8807d518..63387c1c 100644 --- a/internal/funcs/crypto.go +++ b/internal/funcs/crypto.go @@ -20,12 +20,12 @@ import ( ) // CreateCryptoFuncs - -func CreateCryptoFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateCryptoFuncs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &CryptoFuncs{ctx} - f["crypto"] = func() interface{} { return ns } + f["crypto"] = func() any { return ns } return f } @@ -37,7 +37,7 @@ type CryptoFuncs struct { // PBKDF2 - Run the Password-Based Key Derivation Function #2 as defined in // RFC 2898 (PKCS #5 v2.0). This function outputs the binary result in hex // format. -func (CryptoFuncs) PBKDF2(password, salt, iter, keylen interface{}, hashFunc ...string) (k string, err error) { +func (CryptoFuncs) PBKDF2(password, salt, iter, keylen any, hashFunc ...string) (k string, err error) { var h gcrypto.Hash if len(hashFunc) == 0 { h = gcrypto.SHA1 @@ -65,36 +65,36 @@ func (CryptoFuncs) PBKDF2(password, salt, iter, keylen interface{}, hashFunc ... } // WPAPSK - Convert an ASCII passphrase to WPA PSK for a given SSID -func (f CryptoFuncs) WPAPSK(ssid, password interface{}) (string, error) { +func (f CryptoFuncs) WPAPSK(ssid, password any) (string, error) { return f.PBKDF2(password, ssid, 4096, 32) } // SHA1 - Note: SHA-1 is cryptographically broken and should not be used for secure applications. -func (f CryptoFuncs) SHA1(input interface{}) string { +func (f CryptoFuncs) SHA1(input any) string { out, _ := f.SHA1Bytes(input) return fmt.Sprintf("%02x", out) } // SHA224 - -func (f CryptoFuncs) SHA224(input interface{}) string { +func (f CryptoFuncs) SHA224(input any) string { out, _ := f.SHA224Bytes(input) return fmt.Sprintf("%02x", out) } // SHA256 - -func (f CryptoFuncs) SHA256(input interface{}) string { +func (f CryptoFuncs) SHA256(input any) string { out, _ := f.SHA256Bytes(input) return fmt.Sprintf("%02x", out) } // SHA384 - -func (f CryptoFuncs) SHA384(input interface{}) string { +func (f CryptoFuncs) SHA384(input any) string { out, _ := f.SHA384Bytes(input) return fmt.Sprintf("%02x", out) } // SHA512 - -func (f CryptoFuncs) SHA512(input interface{}) string { +func (f CryptoFuncs) SHA512(input any) string { out, _ := f.SHA512Bytes(input) return fmt.Sprintf("%02x", out) } @@ -102,7 +102,7 @@ func (f CryptoFuncs) SHA512(input interface{}) string { // SHA512_224 - // //nolint:revive,stylecheck -func (f CryptoFuncs) SHA512_224(input interface{}) string { +func (f CryptoFuncs) SHA512_224(input any) string { out, _ := f.SHA512_224Bytes(input) return fmt.Sprintf("%02x", out) } @@ -110,13 +110,13 @@ func (f CryptoFuncs) SHA512_224(input interface{}) string { // SHA512_256 - // //nolint:revive,stylecheck -func (f CryptoFuncs) SHA512_256(input interface{}) string { +func (f CryptoFuncs) SHA512_256(input any) string { out, _ := f.SHA512_256Bytes(input) return fmt.Sprintf("%02x", out) } // SHA1 - Note: SHA-1 is cryptographically broken and should not be used for secure applications. -func (CryptoFuncs) SHA1Bytes(input interface{}) ([]byte, error) { +func (CryptoFuncs) SHA1Bytes(input any) ([]byte, error) { //nolint:gosec b := sha1.Sum(toBytes(input)) out := make([]byte, len(b)) @@ -125,7 +125,7 @@ func (CryptoFuncs) SHA1Bytes(input interface{}) ([]byte, error) { } // SHA224 - -func (CryptoFuncs) SHA224Bytes(input interface{}) ([]byte, error) { +func (CryptoFuncs) SHA224Bytes(input any) ([]byte, error) { b := sha256.Sum224(toBytes(input)) out := make([]byte, len(b)) copy(out, b[:]) @@ -133,7 +133,7 @@ func (CryptoFuncs) SHA224Bytes(input interface{}) ([]byte, error) { } // SHA256 - -func (CryptoFuncs) SHA256Bytes(input interface{}) ([]byte, error) { +func (CryptoFuncs) SHA256Bytes(input any) ([]byte, error) { b := sha256.Sum256(toBytes(input)) out := make([]byte, len(b)) copy(out, b[:]) @@ -141,7 +141,7 @@ func (CryptoFuncs) SHA256Bytes(input interface{}) ([]byte, error) { } // SHA384 - -func (CryptoFuncs) SHA384Bytes(input interface{}) ([]byte, error) { +func (CryptoFuncs) SHA384Bytes(input any) ([]byte, error) { b := sha512.Sum384(toBytes(input)) out := make([]byte, len(b)) copy(out, b[:]) @@ -149,7 +149,7 @@ func (CryptoFuncs) SHA384Bytes(input interface{}) ([]byte, error) { } // SHA512 - -func (CryptoFuncs) SHA512Bytes(input interface{}) ([]byte, error) { +func (CryptoFuncs) SHA512Bytes(input any) ([]byte, error) { b := sha512.Sum512(toBytes(input)) out := make([]byte, len(b)) copy(out, b[:]) @@ -157,7 +157,7 @@ func (CryptoFuncs) SHA512Bytes(input interface{}) ([]byte, error) { } // SHA512_224 - -func (CryptoFuncs) SHA512_224Bytes(input interface{}) ([]byte, error) { +func (CryptoFuncs) SHA512_224Bytes(input any) ([]byte, error) { b := sha512.Sum512_224(toBytes(input)) out := make([]byte, len(b)) copy(out, b[:]) @@ -165,7 +165,7 @@ func (CryptoFuncs) SHA512_224Bytes(input interface{}) ([]byte, error) { } // SHA512_256 - -func (CryptoFuncs) SHA512_256Bytes(input interface{}) ([]byte, error) { +func (CryptoFuncs) SHA512_256Bytes(input any) ([]byte, error) { b := sha512.Sum512_256(toBytes(input)) out := make([]byte, len(b)) copy(out, b[:]) @@ -173,7 +173,7 @@ func (CryptoFuncs) SHA512_256Bytes(input interface{}) ([]byte, error) { } // Bcrypt - -func (CryptoFuncs) Bcrypt(args ...interface{}) (string, error) { +func (CryptoFuncs) Bcrypt(args ...any) (string, error) { input := "" var err error @@ -199,7 +199,7 @@ func (CryptoFuncs) Bcrypt(args ...interface{}) (string, error) { // RSAEncrypt - // Experimental! -func (f *CryptoFuncs) RSAEncrypt(key string, in interface{}) ([]byte, error) { +func (f *CryptoFuncs) RSAEncrypt(key string, in any) ([]byte, error) { if err := checkExperimental(f.ctx); err != nil { return nil, err } @@ -229,7 +229,7 @@ func (f *CryptoFuncs) RSADecryptBytes(key string, in []byte) ([]byte, error) { // RSAGenerateKey - // Experimental! -func (f *CryptoFuncs) RSAGenerateKey(args ...interface{}) (string, error) { +func (f *CryptoFuncs) RSAGenerateKey(args ...any) (string, error) { err := checkExperimental(f.ctx) if err != nil { return "", err @@ -261,7 +261,7 @@ func (f *CryptoFuncs) RSADerivePublicKey(privateKey string) (string, error) { // ECDSAGenerateKey - // Experimental! -func (f *CryptoFuncs) ECDSAGenerateKey(args ...interface{}) (string, error) { +func (f *CryptoFuncs) ECDSAGenerateKey(args ...any) (string, error) { if err := checkExperimental(f.ctx); err != nil { return "", err } @@ -343,7 +343,7 @@ func (f *CryptoFuncs) Ed25519DerivePublicKey(privateKey string) (string, error) // EncryptAES - // Experimental! -func (f *CryptoFuncs) EncryptAES(key string, args ...interface{}) ([]byte, error) { +func (f *CryptoFuncs) EncryptAES(key string, args ...any) ([]byte, error) { if err := checkExperimental(f.ctx); err != nil { return nil, err } @@ -358,7 +358,7 @@ func (f *CryptoFuncs) EncryptAES(key string, args ...interface{}) ([]byte, error // DecryptAES - // Experimental! -func (f *CryptoFuncs) DecryptAES(key string, args ...interface{}) (string, error) { +func (f *CryptoFuncs) DecryptAES(key string, args ...any) (string, error) { if err := checkExperimental(f.ctx); err != nil { return "", err } @@ -369,7 +369,7 @@ func (f *CryptoFuncs) DecryptAES(key string, args ...interface{}) (string, error // DecryptAESBytes - // Experimental! -func (f *CryptoFuncs) DecryptAESBytes(key string, args ...interface{}) ([]byte, error) { +func (f *CryptoFuncs) DecryptAESBytes(key string, args ...any) ([]byte, error) { if err := checkExperimental(f.ctx); err != nil { return nil, err } @@ -382,7 +382,7 @@ func (f *CryptoFuncs) DecryptAESBytes(key string, args ...interface{}) ([]byte, return crypto.DecryptAESCBC(k, msg) } -func parseAESArgs(key string, args ...interface{}) ([]byte, []byte, error) { +func parseAESArgs(key string, args ...any) ([]byte, []byte, error) { keyBits := 256 // default to AES-256-CBC var msg []byte diff --git a/internal/funcs/crypto_test.go b/internal/funcs/crypto_test.go index e2b15415..75e7c6df 100644 --- a/internal/funcs/crypto_test.go +++ b/internal/funcs/crypto_test.go @@ -13,14 +13,14 @@ import ( ) func TestCreateCryptoFuncs(t *testing.T) { - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateCryptoFuncs(ctx) - actual := fmap["crypto"].(func() interface{}) + actual := fmap["crypto"].(func() any) assert.Equal(t, ctx, actual().(*CryptoFuncs).ctx) }) diff --git a/internal/funcs/data.go b/internal/funcs/data.go index 085dbc54..1666f689 100644 --- a/internal/funcs/data.go +++ b/internal/funcs/data.go @@ -8,12 +8,12 @@ import ( ) // CreateDataFuncs - -func CreateDataFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateDataFuncs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &DataFuncs{ctx} - f["data"] = func() interface{} { return ns } + f["data"] = func() any { return ns } f["json"] = ns.JSON f["jsonArray"] = ns.JSONArray @@ -39,27 +39,27 @@ type DataFuncs struct { } // JSON - -func (f *DataFuncs) JSON(in interface{}) (map[string]interface{}, error) { +func (f *DataFuncs) JSON(in any) (map[string]any, error) { return parsers.JSON(conv.ToString(in)) } // JSONArray - -func (f *DataFuncs) JSONArray(in interface{}) ([]interface{}, error) { +func (f *DataFuncs) JSONArray(in any) ([]any, error) { return parsers.JSONArray(conv.ToString(in)) } // YAML - -func (f *DataFuncs) YAML(in interface{}) (map[string]interface{}, error) { +func (f *DataFuncs) YAML(in any) (map[string]any, error) { return parsers.YAML(conv.ToString(in)) } // YAMLArray - -func (f *DataFuncs) YAMLArray(in interface{}) ([]interface{}, error) { +func (f *DataFuncs) YAMLArray(in any) ([]any, error) { return parsers.YAMLArray(conv.ToString(in)) } // TOML - -func (f *DataFuncs) TOML(in interface{}) (interface{}, error) { +func (f *DataFuncs) TOML(in any) (any, error) { return parsers.TOML(conv.ToString(in)) } @@ -79,36 +79,36 @@ func (f *DataFuncs) CSVByColumn(args ...string) (cols map[string][]string, err e } // CUE - -func (f *DataFuncs) CUE(in interface{}) (interface{}, error) { +func (f *DataFuncs) CUE(in any) (any, error) { return parsers.CUE(conv.ToString(in)) } // ToCSV - -func (f *DataFuncs) ToCSV(args ...interface{}) (string, error) { +func (f *DataFuncs) ToCSV(args ...any) (string, error) { return parsers.ToCSV(args...) } // ToCUE - -func (f *DataFuncs) ToCUE(in interface{}) (string, error) { +func (f *DataFuncs) ToCUE(in any) (string, error) { return parsers.ToCUE(in) } // ToJSON - -func (f *DataFuncs) ToJSON(in interface{}) (string, error) { +func (f *DataFuncs) ToJSON(in any) (string, error) { return parsers.ToJSON(in) } // ToJSONPretty - -func (f *DataFuncs) ToJSONPretty(indent string, in interface{}) (string, error) { +func (f *DataFuncs) ToJSONPretty(indent string, in any) (string, error) { return parsers.ToJSONPretty(indent, in) } // ToYAML - -func (f *DataFuncs) ToYAML(in interface{}) (string, error) { +func (f *DataFuncs) ToYAML(in any) (string, error) { return parsers.ToYAML(in) } // ToTOML - -func (f *DataFuncs) ToTOML(in interface{}) (string, error) { +func (f *DataFuncs) ToTOML(in any) (string, error) { return parsers.ToTOML(in) } diff --git a/internal/funcs/data_test.go b/internal/funcs/data_test.go index b01530b6..d7dccedf 100644 --- a/internal/funcs/data_test.go +++ b/internal/funcs/data_test.go @@ -11,14 +11,14 @@ import ( func TestCreateDataFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateDataFuncs(ctx) - actual := fmap["data"].(func() interface{}) + actual := fmap["data"].(func() any) assert.Equal(t, ctx, actual().(*DataFuncs).ctx) }) diff --git a/internal/funcs/datasource.go b/internal/funcs/datasource.go index 6c4badf8..e1232231 100644 --- a/internal/funcs/datasource.go +++ b/internal/funcs/datasource.go @@ -12,16 +12,16 @@ import ( ) // CreateDataSourceFuncs - -func CreateDataSourceFuncs(ctx context.Context, sr datafs.DataSourceReader) map[string]interface{} { +func CreateDataSourceFuncs(ctx context.Context, sr datafs.DataSourceReader) map[string]any { ns := &dataSourceFuncs{ ctx: ctx, sr: sr, } - f := map[string]interface{}{} + f := map[string]any{} // undocumented but available - f["_datasource"] = func() interface{} { return ns } + f["_datasource"] = func() any { return ns } f["datasource"] = ns.Datasource f["ds"] = ns.Datasource @@ -52,7 +52,7 @@ func (d *dataSourceFuncs) Include(alias string, args ...string) (string, error) } // Datasource - Reads from the named datasource, and returns the parsed datafs. -func (d *dataSourceFuncs) Datasource(alias string, args ...string) (interface{}, error) { +func (d *dataSourceFuncs) Datasource(alias string, args ...string) (any, error) { ct, b, err := d.sr.ReadSource(d.ctx, alias, args...) if err != nil { return nil, err diff --git a/internal/funcs/datasource_test.go b/internal/funcs/datasource_test.go index 3c5f5f7f..18050009 100644 --- a/internal/funcs/datasource_test.go +++ b/internal/funcs/datasource_test.go @@ -19,14 +19,14 @@ import ( func TestCreateDataSourceFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateDataSourceFuncs(ctx, nil) - actual := fmap["_datasource"].(func() interface{}) + actual := fmap["_datasource"].(func() any) assert.Equal(t, ctx, actual().(*dataSourceFuncs).ctx) }) @@ -57,7 +57,7 @@ func TestDatasource(t *testing.T) { return d } - test := func(ext, mime string, contents []byte, expected interface{}) { + test := func(ext, mime string, contents []byte, expected any) { data := setup(ext, contents) actual, err := data.Datasource("foo", "?type="+mime) @@ -67,17 +67,17 @@ func TestDatasource(t *testing.T) { testObj := func(ext, mime string, contents []byte) { test(ext, mime, contents, - map[string]interface{}{ - "hello": map[string]interface{}{"cruel": "world"}, + map[string]any{ + "hello": map[string]any{"cruel": "world"}, }) } testObj("json", iohelpers.JSONMimetype, []byte(`{"hello":{"cruel":"world"}}`)) testObj("yml", iohelpers.YAMLMimetype, []byte("hello:\n cruel: world\n")) test("json", iohelpers.JSONMimetype, []byte(`[1, "two", true]`), - []interface{}{1, "two", true}) + []any{1, "two", true}) test("yaml", iohelpers.YAMLMimetype, []byte("---\n- 1\n- two\n- true\n"), - []interface{}{1, "two", true}) + []any{1, "two", true}) d := setup("", nil) actual, err := d.Datasource("foo") diff --git a/internal/funcs/env.go b/internal/funcs/env.go index 61ed9be4..5ec5a17a 100644 --- a/internal/funcs/env.go +++ b/internal/funcs/env.go @@ -8,11 +8,11 @@ import ( ) // CreateEnvFuncs - -func CreateEnvFuncs(ctx context.Context) map[string]interface{} { +func CreateEnvFuncs(ctx context.Context) map[string]any { ns := &EnvFuncs{ctx} - return map[string]interface{}{ - "env": func() interface{} { return ns }, + return map[string]any{ + "env": func() any { return ns }, "getenv": ns.Getenv, } } @@ -23,11 +23,11 @@ type EnvFuncs struct { } // Getenv - -func (EnvFuncs) Getenv(key interface{}, def ...string) string { +func (EnvFuncs) Getenv(key any, def ...string) string { return env.Getenv(conv.ToString(key), def...) } // ExpandEnv - -func (EnvFuncs) ExpandEnv(s interface{}) string { +func (EnvFuncs) ExpandEnv(s any) string { return env.ExpandEnv(conv.ToString(s)) } diff --git a/internal/funcs/env_test.go b/internal/funcs/env_test.go index a6ee43ac..b34d9769 100644 --- a/internal/funcs/env_test.go +++ b/internal/funcs/env_test.go @@ -12,14 +12,14 @@ import ( func TestCreateEnvFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateEnvFuncs(ctx) - actual := fmap["env"].(func() interface{}) + actual := fmap["env"].(func() any) assert.Equal(t, ctx, actual().(*EnvFuncs).ctx) }) diff --git a/internal/funcs/file.go b/internal/funcs/file.go index 16012cf1..508cf6ce 100644 --- a/internal/funcs/file.go +++ b/internal/funcs/file.go @@ -12,7 +12,7 @@ import ( ) // CreateFileFuncs - -func CreateFileFuncs(ctx context.Context) map[string]interface{} { +func CreateFileFuncs(ctx context.Context) map[string]any { fsys, err := datafs.FSysForPath(ctx, "/") if err != nil { fsys = datafs.WrapWdFS(osfs.NewFS()) @@ -23,8 +23,8 @@ func CreateFileFuncs(ctx context.Context) map[string]interface{} { fs: fsys, } - return map[string]interface{}{ - "file": func() interface{} { return ns }, + return map[string]any{ + "file": func() any { return ns }, } } @@ -35,30 +35,30 @@ type FileFuncs struct { } // Read - -func (f *FileFuncs) Read(path interface{}) (string, error) { +func (f *FileFuncs) Read(path any) (string, error) { b, err := fs.ReadFile(f.fs, conv.ToString(path)) return string(b), err } // Stat - -func (f *FileFuncs) Stat(path interface{}) (fs.FileInfo, error) { +func (f *FileFuncs) Stat(path any) (fs.FileInfo, error) { return fs.Stat(f.fs, conv.ToString(path)) } // Exists - -func (f *FileFuncs) Exists(path interface{}) bool { +func (f *FileFuncs) Exists(path any) bool { _, err := f.Stat(conv.ToString(path)) return err == nil } // IsDir - -func (f *FileFuncs) IsDir(path interface{}) bool { +func (f *FileFuncs) IsDir(path any) bool { i, err := f.Stat(conv.ToString(path)) return err == nil && i.IsDir() } // ReadDir - -func (f *FileFuncs) ReadDir(path interface{}) ([]string, error) { +func (f *FileFuncs) ReadDir(path any) ([]string, error) { des, err := fs.ReadDir(f.fs, conv.ToString(path)) if err != nil { return nil, err @@ -73,7 +73,7 @@ func (f *FileFuncs) ReadDir(path interface{}) ([]string, error) { } // Walk - -func (f *FileFuncs) Walk(path interface{}) ([]string, error) { +func (f *FileFuncs) Walk(path any) ([]string, error) { files := make([]string, 0) err := fs.WalkDir(f.fs, conv.ToString(path), func(subpath string, _ fs.DirEntry, err error) error { if err != nil { @@ -92,7 +92,7 @@ func (f *FileFuncs) Walk(path interface{}) ([]string, error) { } // Write - -func (f *FileFuncs) Write(path interface{}, data interface{}) (s string, err error) { +func (f *FileFuncs) Write(path any, data any) (s string, err error) { type byteser interface{ Bytes() []byte } var content []byte diff --git a/internal/funcs/file_test.go b/internal/funcs/file_test.go index 0c2babda..e64836ba 100644 --- a/internal/funcs/file_test.go +++ b/internal/funcs/file_test.go @@ -21,14 +21,14 @@ import ( func TestCreateFileFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateFileFuncs(ctx) - actual := fmap["file"].(func() interface{}) + actual := fmap["file"].(func() any) assert.Equal(t, ctx, actual().(*FileFuncs).ctx) }) diff --git a/internal/funcs/filepath.go b/internal/funcs/filepath.go index ffbd5699..5594a0fa 100644 --- a/internal/funcs/filepath.go +++ b/internal/funcs/filepath.go @@ -8,11 +8,11 @@ import ( ) // CreateFilePathFuncs - -func CreateFilePathFuncs(ctx context.Context) map[string]interface{} { +func CreateFilePathFuncs(ctx context.Context) map[string]any { ns := &FilePathFuncs{ctx} - return map[string]interface{}{ - "filepath": func() interface{} { return ns }, + return map[string]any{ + "filepath": func() any { return ns }, } } @@ -22,63 +22,63 @@ type FilePathFuncs struct { } // Base - -func (f *FilePathFuncs) Base(in interface{}) string { +func (f *FilePathFuncs) Base(in any) string { return filepath.Base(conv.ToString(in)) } // Clean - -func (f *FilePathFuncs) Clean(in interface{}) string { +func (f *FilePathFuncs) Clean(in any) string { return filepath.Clean(conv.ToString(in)) } // Dir - -func (f *FilePathFuncs) Dir(in interface{}) string { +func (f *FilePathFuncs) Dir(in any) string { return filepath.Dir(conv.ToString(in)) } // Ext - -func (f *FilePathFuncs) Ext(in interface{}) string { +func (f *FilePathFuncs) Ext(in any) string { return filepath.Ext(conv.ToString(in)) } // FromSlash - -func (f *FilePathFuncs) FromSlash(in interface{}) string { +func (f *FilePathFuncs) FromSlash(in any) string { return filepath.FromSlash(conv.ToString(in)) } // IsAbs - -func (f *FilePathFuncs) IsAbs(in interface{}) bool { +func (f *FilePathFuncs) IsAbs(in any) bool { return filepath.IsAbs(conv.ToString(in)) } // Join - -func (f *FilePathFuncs) Join(elem ...interface{}) string { +func (f *FilePathFuncs) Join(elem ...any) string { s := conv.ToStrings(elem...) return filepath.Join(s...) } // Match - -func (f *FilePathFuncs) Match(pattern, name interface{}) (matched bool, err error) { +func (f *FilePathFuncs) Match(pattern, name any) (matched bool, err error) { return filepath.Match(conv.ToString(pattern), conv.ToString(name)) } // Rel - -func (f *FilePathFuncs) Rel(basepath, targpath interface{}) (string, error) { +func (f *FilePathFuncs) Rel(basepath, targpath any) (string, error) { return filepath.Rel(conv.ToString(basepath), conv.ToString(targpath)) } // Split - -func (f *FilePathFuncs) Split(in interface{}) []string { +func (f *FilePathFuncs) Split(in any) []string { dir, file := filepath.Split(conv.ToString(in)) return []string{dir, file} } // ToSlash - -func (f *FilePathFuncs) ToSlash(in interface{}) string { +func (f *FilePathFuncs) ToSlash(in any) string { return filepath.ToSlash(conv.ToString(in)) } // VolumeName - -func (f *FilePathFuncs) VolumeName(in interface{}) string { +func (f *FilePathFuncs) VolumeName(in any) string { return filepath.VolumeName(conv.ToString(in)) } diff --git a/internal/funcs/filepath_test.go b/internal/funcs/filepath_test.go index 0c4bbe80..2662c2c6 100644 --- a/internal/funcs/filepath_test.go +++ b/internal/funcs/filepath_test.go @@ -11,14 +11,14 @@ import ( func TestCreateFilePathFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateFilePathFuncs(ctx) - actual := fmap["filepath"].(func() interface{}) + actual := fmap["filepath"].(func() any) assert.Equal(t, ctx, actual().(*FilePathFuncs).ctx) }) diff --git a/internal/funcs/gcp.go b/internal/funcs/gcp.go index b87bd54b..d4278296 100644 --- a/internal/funcs/gcp.go +++ b/internal/funcs/gcp.go @@ -8,13 +8,13 @@ import ( ) // CreateGCPFuncs - -func CreateGCPFuncs(ctx context.Context) map[string]interface{} { +func CreateGCPFuncs(ctx context.Context) map[string]any { ns := &GcpFuncs{ ctx: ctx, gcpopts: gcp.GetClientOptions(), } - return map[string]interface{}{ - "gcp": func() interface{} { return ns }, + return map[string]any{ + "gcp": func() any { return ns }, } } @@ -28,7 +28,7 @@ type GcpFuncs struct { // Meta - func (a *GcpFuncs) Meta(key string, def ...string) (string, error) { - a.meta = sync.OnceValue[*gcp.MetaClient](func() *gcp.MetaClient { + a.meta = sync.OnceValue(func() *gcp.MetaClient { return gcp.NewMetaClient(a.ctx, a.gcpopts) })() diff --git a/internal/funcs/gcp_test.go b/internal/funcs/gcp_test.go index 91ab54fb..ce9fff42 100644 --- a/internal/funcs/gcp_test.go +++ b/internal/funcs/gcp_test.go @@ -11,14 +11,14 @@ import ( func TestCreateGCPFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateGCPFuncs(ctx) - actual := fmap["gcp"].(func() interface{}) + actual := fmap["gcp"].(func() any) assert.Equal(t, ctx, actual().(*GcpFuncs).ctx) }) diff --git a/internal/funcs/math.go b/internal/funcs/math.go index 694586a7..fbdbab5b 100644 --- a/internal/funcs/math.go +++ b/internal/funcs/math.go @@ -4,6 +4,7 @@ import ( "context" "fmt" gmath "math" + "slices" "strconv" "github.com/hairyhenderson/gomplate/v4/conv" @@ -12,11 +13,11 @@ import ( ) // CreateMathFuncs - -func CreateMathFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateMathFuncs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &MathFuncs{ctx} - f["math"] = func() interface{} { return ns } + f["math"] = func() any { return ns } f["add"] = ns.Add f["sub"] = ns.Sub @@ -34,7 +35,7 @@ type MathFuncs struct { } // IsInt - -func (f MathFuncs) IsInt(n interface{}) bool { +func (f MathFuncs) IsInt(n any) bool { switch i := n.(type) { case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64: return true @@ -46,7 +47,7 @@ func (f MathFuncs) IsInt(n interface{}) bool { } // IsFloat - -func (f MathFuncs) IsFloat(n interface{}) bool { +func (f MathFuncs) IsFloat(n any) bool { switch i := n.(type) { case float32, float64: return true @@ -63,23 +64,13 @@ func (f MathFuncs) IsFloat(n interface{}) bool { return false } -func (f MathFuncs) containsFloat(n ...interface{}) bool { - c := false - for _, v := range n { - if f.IsFloat(v) { - return true - } - } - return c -} - // IsNum - -func (f MathFuncs) IsNum(n interface{}) bool { +func (f MathFuncs) IsNum(n any) bool { return f.IsInt(n) || f.IsFloat(n) } // Abs - -func (f MathFuncs) Abs(n interface{}) (interface{}, error) { +func (f MathFuncs) Abs(n any) (any, error) { fn, err := conv.ToFloat64(n) if err != nil { return nil, fmt.Errorf("expected a number: %w", err) @@ -94,8 +85,8 @@ func (f MathFuncs) Abs(n interface{}) (interface{}, error) { } // Add - -func (f MathFuncs) Add(n ...interface{}) (interface{}, error) { - if f.containsFloat(n...) { +func (f MathFuncs) Add(n ...any) (any, error) { + if slices.ContainsFunc(n, f.IsFloat) { nums, err := conv.ToFloat64s(n...) if err != nil { return nil, fmt.Errorf("expected number inputs: %w", err) @@ -123,8 +114,8 @@ func (f MathFuncs) Add(n ...interface{}) (interface{}, error) { } // Mul - -func (f MathFuncs) Mul(n ...interface{}) (interface{}, error) { - if f.containsFloat(n...) { +func (f MathFuncs) Mul(n ...any) (any, error) { + if slices.ContainsFunc(n, f.IsFloat) { nums, err := conv.ToFloat64s(n...) if err != nil { return nil, fmt.Errorf("expected number inputs: %w", err) @@ -152,8 +143,8 @@ func (f MathFuncs) Mul(n ...interface{}) (interface{}, error) { } // Sub - -func (f MathFuncs) Sub(a, b interface{}) (interface{}, error) { - if f.containsFloat(a, b) { +func (f MathFuncs) Sub(a, b any) (any, error) { + if slices.ContainsFunc([]any{a, b}, f.IsFloat) { fa, err := conv.ToFloat64(a) if err != nil { return nil, fmt.Errorf("expected a number: %w", err) @@ -181,7 +172,7 @@ func (f MathFuncs) Sub(a, b interface{}) (interface{}, error) { } // Div - -func (f MathFuncs) Div(a, b interface{}) (interface{}, error) { +func (f MathFuncs) Div(a, b any) (any, error) { divisor, err := conv.ToFloat64(a) if err != nil { return nil, fmt.Errorf("expected a number: %w", err) @@ -200,7 +191,7 @@ func (f MathFuncs) Div(a, b interface{}) (interface{}, error) { } // Rem - -func (f MathFuncs) Rem(a, b interface{}) (interface{}, error) { +func (f MathFuncs) Rem(a, b any) (any, error) { ia, err := conv.ToInt64(a) if err != nil { return nil, fmt.Errorf("expected a number: %w", err) @@ -215,7 +206,7 @@ func (f MathFuncs) Rem(a, b interface{}) (interface{}, error) { } // Pow - -func (f MathFuncs) Pow(a, b interface{}) (interface{}, error) { +func (f MathFuncs) Pow(a, b any) (any, error) { fa, err := conv.ToFloat64(a) if err != nil { return nil, fmt.Errorf("expected a number: %w", err) @@ -236,7 +227,7 @@ func (f MathFuncs) Pow(a, b interface{}) (interface{}, error) { // Seq - return a sequence from `start` to `end`, in steps of `step` // start and step are optional, and default to 1. -func (f MathFuncs) Seq(n ...interface{}) ([]int64, error) { +func (f MathFuncs) Seq(n ...any) ([]int64, error) { start := int64(1) end := int64(0) step := int64(1) @@ -282,8 +273,8 @@ func (f MathFuncs) Seq(n ...interface{}) ([]int64, error) { } // Max - -func (f MathFuncs) Max(a interface{}, b ...interface{}) (interface{}, error) { - if f.IsFloat(a) || f.containsFloat(b...) { +func (f MathFuncs) Max(a any, b ...any) (any, error) { + if f.IsFloat(a) || slices.ContainsFunc(b, f.IsFloat) { m, err := conv.ToFloat64(a) if err != nil { return nil, fmt.Errorf("expected a number: %w", err) @@ -321,8 +312,8 @@ func (f MathFuncs) Max(a interface{}, b ...interface{}) (interface{}, error) { } // Min - -func (f MathFuncs) Min(a interface{}, b ...interface{}) (interface{}, error) { - if f.IsFloat(a) || f.containsFloat(b...) { +func (f MathFuncs) Min(a any, b ...any) (any, error) { + if f.IsFloat(a) || slices.ContainsFunc(b, f.IsFloat) { m, err := conv.ToFloat64(a) if err != nil { return nil, fmt.Errorf("expected a number: %w", err) @@ -358,7 +349,7 @@ func (f MathFuncs) Min(a interface{}, b ...interface{}) (interface{}, error) { } // Ceil - -func (f MathFuncs) Ceil(n interface{}) (interface{}, error) { +func (f MathFuncs) Ceil(n any) (any, error) { in, err := conv.ToFloat64(n) if err != nil { return nil, fmt.Errorf("n must be a number: %w", err) @@ -368,7 +359,7 @@ func (f MathFuncs) Ceil(n interface{}) (interface{}, error) { } // Floor - -func (f MathFuncs) Floor(n interface{}) (interface{}, error) { +func (f MathFuncs) Floor(n any) (any, error) { in, err := conv.ToFloat64(n) if err != nil { return nil, fmt.Errorf("n must be a number: %w", err) @@ -378,7 +369,7 @@ func (f MathFuncs) Floor(n interface{}) (interface{}, error) { } // Round - -func (f MathFuncs) Round(n interface{}) (interface{}, error) { +func (f MathFuncs) Round(n any) (any, error) { in, err := conv.ToFloat64(n) if err != nil { return nil, fmt.Errorf("n must be a number: %w", err) diff --git a/internal/funcs/math_test.go b/internal/funcs/math_test.go index d55f973a..717db2b6 100644 --- a/internal/funcs/math_test.go +++ b/internal/funcs/math_test.go @@ -4,6 +4,7 @@ import ( "context" "fmt" gmath "math" + "slices" "strconv" "testing" @@ -14,14 +15,14 @@ import ( func TestCreateMathFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateMathFuncs(ctx) - actual := fmap["math"].(func() interface{}) + actual := fmap["math"].(func() any) assert.Equal(t, ctx, actual().(*MathFuncs).ctx) }) @@ -106,7 +107,7 @@ func TestSub(t *testing.T) { assert.InEpsilon(t, -5.3, actual, 1e-12) } -func mustDiv(a, b interface{}) interface{} { +func mustDiv(a, b any) any { m := MathFuncs{} r, err := m.Div(a, b) if err != nil { @@ -155,7 +156,7 @@ func TestPow(t *testing.T) { assert.InEpsilon(t, 2.25, actual, 1e-12) } -func mustSeq(t *testing.T, n ...interface{}) []int64 { +func mustSeq(t *testing.T, n ...any) []int64 { m := MathFuncs{} s, err := m.Seq(n...) if err != nil { @@ -181,7 +182,7 @@ func TestIsIntFloatNum(t *testing.T) { t.Parallel() tests := []struct { - in interface{} + in any isInt bool isFloat bool }{ @@ -232,14 +233,14 @@ func TestIsIntFloatNum(t *testing.T) { } func BenchmarkIsFloat(b *testing.B) { - data := []interface{}{ + data := []any{ 0, 1, -1, uint(42), uint8(255), uint16(42), uint32(42), uint64(42), int(42), int8(127), int16(42), int32(42), int64(42), float32(18.3), float64(18.3), 1.5, -18.6, "42", "052", "0xff", "-42", "-0", "3.14", "-3.14", "0.00", "NaN", "-Inf", "+Inf", "", "foo", nil, true, } m := MathFuncs{} for _, n := range data { b.Run(fmt.Sprintf("%T(%v)", n, n), func(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { m.IsFloat(n) } }) @@ -251,21 +252,21 @@ func TestMax(t *testing.T) { m := MathFuncs{} data := []struct { - expected interface{} - n []interface{} + expected any + n []any }{ - {int64(0), []interface{}{0}}, - {int64(1), []interface{}{1}}, - {int64(-1), []interface{}{-1}}, - {int64(1), []interface{}{-1, 0, 1}}, - {3.9, []interface{}{3.14, 3, 3.9}}, - {int64(255), []interface{}{"14", "0xff", -5}}, + {int64(0), []any{0}}, + {int64(1), []any{1}}, + {int64(-1), []any{-1}}, + {int64(1), []any{-1, 0, 1}}, + {3.9, []any{3.14, 3, 3.9}}, + {int64(255), []any{"14", "0xff", -5}}, } for _, d := range data { t.Run(fmt.Sprintf("%v==%v", d.n, d.expected), func(t *testing.T) { t.Parallel() - var actual interface{} + var actual any if len(d.n) == 1 { actual, _ = m.Max(d.n[0]) } else { @@ -294,21 +295,21 @@ func TestMin(t *testing.T) { m := MathFuncs{} data := []struct { - expected interface{} - n []interface{} + expected any + n []any }{ - {int64(0), []interface{}{0}}, - {int64(1), []interface{}{1}}, - {int64(-1), []interface{}{-1}}, - {int64(-1), []interface{}{-1, 0, 1}}, - {3., []interface{}{3.14, 3, 3.9}}, - {int64(-5), []interface{}{"14", "0xff", -5}}, + {int64(0), []any{0}}, + {int64(1), []any{1}}, + {int64(-1), []any{-1}}, + {int64(-1), []any{-1, 0, 1}}, + {3., []any{3.14, 3, 3.9}}, + {int64(-5), []any{"14", "0xff", -5}}, } for _, d := range data { t.Run(fmt.Sprintf("%v==%v", d.n, d.expected), func(t *testing.T) { t.Parallel() - var actual interface{} + var actual any if len(d.n) == 1 { actual, _ = m.Min(d.n[0]) } else { @@ -338,29 +339,29 @@ func TestContainsFloat(t *testing.T) { m := MathFuncs{} data := []struct { - n []interface{} + n []any expected bool }{ - {[]interface{}{nil}, false}, - {[]interface{}{0}, false}, - {[]interface{}{"not a number"}, false}, - {[]interface{}{1}, false}, - {[]interface{}{-1}, false}, - {[]interface{}{-1, 0, 1}, false}, - {[]interface{}{3.14, 3, 3.9}, true}, - {[]interface{}{"14", "0xff", -5}, false}, - {[]interface{}{"14.8", "0xff", -5}, true}, - {[]interface{}{"-Inf", 2}, true}, - {[]interface{}{"NaN"}, true}, + {[]any{nil}, false}, + {[]any{0}, false}, + {[]any{"not a number"}, false}, + {[]any{1}, false}, + {[]any{-1}, false}, + {[]any{-1, 0, 1}, false}, + {[]any{3.14, 3, 3.9}, true}, + {[]any{"14", "0xff", -5}, false}, + {[]any{"14.8", "0xff", -5}, true}, + {[]any{"-Inf", 2}, true}, + {[]any{"NaN"}, true}, } for _, d := range data { t.Run(fmt.Sprintf("%v==%v", d.n, d.expected), func(t *testing.T) { t.Parallel() if d.expected { - assert.True(t, m.containsFloat(d.n...)) + assert.True(t, slices.ContainsFunc(d.n, m.IsFloat)) } else { - assert.False(t, m.containsFloat(d.n...)) + assert.False(t, slices.ContainsFunc(d.n, m.IsFloat)) } }) } @@ -371,7 +372,7 @@ func TestCeil(t *testing.T) { m := MathFuncs{} data := []struct { - n interface{} + n any a float64 }{ {"Inf", gmath.Inf(1)}, @@ -409,7 +410,7 @@ func TestFloor(t *testing.T) { m := MathFuncs{} data := []struct { - n interface{} + n any a float64 }{ {"Inf", gmath.Inf(1)}, @@ -447,7 +448,7 @@ func TestRound(t *testing.T) { m := MathFuncs{} data := []struct { - n interface{} + n any a float64 }{ {"Inf", gmath.Inf(1)}, @@ -489,8 +490,8 @@ func TestAbs(t *testing.T) { m := MathFuncs{} data := []struct { - n interface{} - a interface{} + n any + a any }{ {"-Inf", gmath.Inf(1)}, {0, int64(0)}, diff --git a/internal/funcs/net.go b/internal/funcs/net.go index e8d8288d..851033f2 100644 --- a/internal/funcs/net.go +++ b/internal/funcs/net.go @@ -16,10 +16,10 @@ import ( ) // CreateNetFuncs - -func CreateNetFuncs(ctx context.Context) map[string]interface{} { +func CreateNetFuncs(ctx context.Context) map[string]any { ns := &NetFuncs{ctx} - return map[string]interface{}{ - "net": func() interface{} { return ns }, + return map[string]any{ + "net": func() any { return ns }, } } @@ -29,39 +29,39 @@ type NetFuncs struct { } // LookupIP - -func (f NetFuncs) LookupIP(name interface{}) (string, error) { +func (f NetFuncs) LookupIP(name any) (string, error) { return net.LookupIP(conv.ToString(name)) } // LookupIPs - -func (f NetFuncs) LookupIPs(name interface{}) ([]string, error) { +func (f NetFuncs) LookupIPs(name any) ([]string, error) { return net.LookupIPs(conv.ToString(name)) } // LookupCNAME - -func (f NetFuncs) LookupCNAME(name interface{}) (string, error) { +func (f NetFuncs) LookupCNAME(name any) (string, error) { return net.LookupCNAME(conv.ToString(name)) } // LookupSRV - -func (f NetFuncs) LookupSRV(name interface{}) (*stdnet.SRV, error) { +func (f NetFuncs) LookupSRV(name any) (*stdnet.SRV, error) { return net.LookupSRV(conv.ToString(name)) } // LookupSRVs - -func (f NetFuncs) LookupSRVs(name interface{}) ([]*stdnet.SRV, error) { +func (f NetFuncs) LookupSRVs(name any) ([]*stdnet.SRV, error) { return net.LookupSRVs(conv.ToString(name)) } // LookupTXT - -func (f NetFuncs) LookupTXT(name interface{}) ([]string, error) { +func (f NetFuncs) LookupTXT(name any) ([]string, error) { return net.LookupTXT(conv.ToString(name)) } // ParseIP - // // Deprecated: use [ParseAddr] instead -func (f *NetFuncs) ParseIP(ip interface{}) (netaddr.IP, error) { +func (f *NetFuncs) ParseIP(ip any) (netaddr.IP, error) { deprecated.WarnDeprecated(f.ctx, "net.ParseIP is deprecated - use net.ParseAddr instead") return netaddr.ParseIP(conv.ToString(ip)) } @@ -69,7 +69,7 @@ func (f *NetFuncs) ParseIP(ip interface{}) (netaddr.IP, error) { // ParseIPPrefix - // // Deprecated: use [ParsePrefix] instead -func (f *NetFuncs) ParseIPPrefix(ipprefix interface{}) (netaddr.IPPrefix, error) { +func (f *NetFuncs) ParseIPPrefix(ipprefix any) (netaddr.IPPrefix, error) { deprecated.WarnDeprecated(f.ctx, "net.ParseIPPrefix is deprecated - use net.ParsePrefix instead") return netaddr.ParseIPPrefix(conv.ToString(ipprefix)) } @@ -77,29 +77,29 @@ func (f *NetFuncs) ParseIPPrefix(ipprefix interface{}) (netaddr.IPPrefix, error) // ParseIPRange - // // Deprecated: use [ParseRange] instead -func (f *NetFuncs) ParseIPRange(iprange interface{}) (netaddr.IPRange, error) { +func (f *NetFuncs) ParseIPRange(iprange any) (netaddr.IPRange, error) { deprecated.WarnDeprecated(f.ctx, "net.ParseIPRange is deprecated - use net.ParseRange instead") return netaddr.ParseIPRange(conv.ToString(iprange)) } // ParseAddr - -func (f NetFuncs) ParseAddr(ip interface{}) (netip.Addr, error) { +func (f NetFuncs) ParseAddr(ip any) (netip.Addr, error) { return netip.ParseAddr(conv.ToString(ip)) } // ParsePrefix - -func (f NetFuncs) ParsePrefix(ipprefix interface{}) (netip.Prefix, error) { +func (f NetFuncs) ParsePrefix(ipprefix any) (netip.Prefix, error) { return netip.ParsePrefix(conv.ToString(ipprefix)) } // ParseRange - // // Experimental: this API may change in the future -func (f NetFuncs) ParseRange(iprange interface{}) (netipx.IPRange, error) { +func (f NetFuncs) ParseRange(iprange any) (netipx.IPRange, error) { return netipx.ParseIPRange(conv.ToString(iprange)) } -func (f *NetFuncs) parseNetipPrefix(prefix interface{}) (netip.Prefix, error) { +func (f *NetFuncs) parseNetipPrefix(prefix any) (netip.Prefix, error) { switch p := prefix.(type) { case *stdnet.IPNet: return f.ipPrefixFromIPNet(p), nil @@ -122,7 +122,7 @@ func (f NetFuncs) ipPrefixFromIPNet(n *stdnet.IPNet) netip.Prefix { // CIDRHost - // Experimental! -func (f *NetFuncs) CIDRHost(hostnum interface{}, prefix interface{}) (netip.Addr, error) { +func (f *NetFuncs) CIDRHost(hostnum any, prefix any) (netip.Addr, error) { if err := checkExperimental(f.ctx); err != nil { return netip.Addr{}, err } @@ -144,7 +144,7 @@ func (f *NetFuncs) CIDRHost(hostnum interface{}, prefix interface{}) (netip.Addr // CIDRNetmask - // Experimental! -func (f *NetFuncs) CIDRNetmask(prefix interface{}) (netip.Addr, error) { +func (f *NetFuncs) CIDRNetmask(prefix any) (netip.Addr, error) { if err := checkExperimental(f.ctx); err != nil { return netip.Addr{}, err } @@ -156,7 +156,7 @@ func (f *NetFuncs) CIDRNetmask(prefix interface{}) (netip.Addr, error) { // fill an appropriately sized byte slice with as many 1s as prefix bits b := make([]byte, p.Addr().BitLen()/8) - for i := 0; i < p.Bits(); i++ { + for i := range p.Bits() { //nolint:gosec // G115 is not applicable, the value was checked at parse // time b[i/8] |= 1 << uint(7-i%8) @@ -172,7 +172,7 @@ func (f *NetFuncs) CIDRNetmask(prefix interface{}) (netip.Addr, error) { // CIDRSubnets - // Experimental! -func (f *NetFuncs) CIDRSubnets(newbits interface{}, prefix interface{}) ([]netip.Prefix, error) { +func (f *NetFuncs) CIDRSubnets(newbits any, prefix any) ([]netip.Prefix, error) { if err := checkExperimental(f.ctx); err != nil { return nil, err } @@ -206,7 +206,7 @@ func (f *NetFuncs) CIDRSubnets(newbits interface{}, prefix interface{}) ([]netip // CIDRSubnetSizes - // Experimental! -func (f *NetFuncs) CIDRSubnetSizes(args ...interface{}) ([]netip.Prefix, error) { +func (f *NetFuncs) CIDRSubnetSizes(args ...any) ([]netip.Prefix, error) { if err := checkExperimental(f.ctx); err != nil { return nil, err } diff --git a/internal/funcs/net_test.go b/internal/funcs/net_test.go index 018b75e5..4e1b120b 100644 --- a/internal/funcs/net_test.go +++ b/internal/funcs/net_test.go @@ -16,14 +16,14 @@ import ( func TestCreateNetFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateNetFuncs(ctx) - actual := fmap["net"].(func() interface{}) + actual := fmap["net"].(func() any) assert.Equal(t, ctx, actual().(*NetFuncs).ctx) }) diff --git a/internal/funcs/path.go b/internal/funcs/path.go index 3831ed5f..9c45f6f7 100644 --- a/internal/funcs/path.go +++ b/internal/funcs/path.go @@ -8,10 +8,10 @@ import ( ) // CreatePathFuncs - -func CreatePathFuncs(ctx context.Context) map[string]interface{} { +func CreatePathFuncs(ctx context.Context) map[string]any { ns := &PathFuncs{ctx} - return map[string]interface{}{ - "path": func() interface{} { return ns }, + return map[string]any{ + "path": func() any { return ns }, } } @@ -21,43 +21,43 @@ type PathFuncs struct { } // Base - -func (PathFuncs) Base(in interface{}) string { +func (PathFuncs) Base(in any) string { return path.Base(conv.ToString(in)) } // Clean - -func (PathFuncs) Clean(in interface{}) string { +func (PathFuncs) Clean(in any) string { return path.Clean(conv.ToString(in)) } // Dir - -func (PathFuncs) Dir(in interface{}) string { +func (PathFuncs) Dir(in any) string { return path.Dir(conv.ToString(in)) } // Ext - -func (PathFuncs) Ext(in interface{}) string { +func (PathFuncs) Ext(in any) string { return path.Ext(conv.ToString(in)) } // IsAbs - -func (PathFuncs) IsAbs(in interface{}) bool { +func (PathFuncs) IsAbs(in any) bool { return path.IsAbs(conv.ToString(in)) } // Join - -func (PathFuncs) Join(elem ...interface{}) string { +func (PathFuncs) Join(elem ...any) string { s := conv.ToStrings(elem...) return path.Join(s...) } // Match - -func (PathFuncs) Match(pattern, name interface{}) (matched bool, err error) { +func (PathFuncs) Match(pattern, name any) (matched bool, err error) { return path.Match(conv.ToString(pattern), conv.ToString(name)) } // Split - -func (PathFuncs) Split(in interface{}) []string { +func (PathFuncs) Split(in any) []string { dir, file := path.Split(conv.ToString(in)) return []string{dir, file} } diff --git a/internal/funcs/path_test.go b/internal/funcs/path_test.go index aa4d1322..4cb41911 100644 --- a/internal/funcs/path_test.go +++ b/internal/funcs/path_test.go @@ -11,14 +11,14 @@ import ( func TestCreatePathFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreatePathFuncs(ctx) - actual := fmap["path"].(func() interface{}) + actual := fmap["path"].(func() any) assert.Equal(t, ctx, actual().(*PathFuncs).ctx) }) diff --git a/internal/funcs/random.go b/internal/funcs/random.go index afadfef4..e6e54a38 100644 --- a/internal/funcs/random.go +++ b/internal/funcs/random.go @@ -12,10 +12,10 @@ import ( ) // CreateRandomFuncs - -func CreateRandomFuncs(ctx context.Context) map[string]interface{} { +func CreateRandomFuncs(ctx context.Context) map[string]any { ns := &RandomFuncs{ctx} - return map[string]interface{}{ - "random": func() interface{} { return ns }, + return map[string]any{ + "random": func() any { return ns }, } } @@ -25,7 +25,7 @@ type RandomFuncs struct { } // ASCII - -func (RandomFuncs) ASCII(count interface{}) (string, error) { +func (RandomFuncs) ASCII(count any) (string, error) { n, err := conv.ToInt(count) if err != nil { return "", fmt.Errorf("count must be an integer: %w", err) @@ -35,7 +35,7 @@ func (RandomFuncs) ASCII(count interface{}) (string, error) { } // Alpha - -func (RandomFuncs) Alpha(count interface{}) (string, error) { +func (RandomFuncs) Alpha(count any) (string, error) { n, err := conv.ToInt(count) if err != nil { return "", fmt.Errorf("count must be an integer: %w", err) @@ -45,7 +45,7 @@ func (RandomFuncs) Alpha(count interface{}) (string, error) { } // AlphaNum - -func (RandomFuncs) AlphaNum(count interface{}) (string, error) { +func (RandomFuncs) AlphaNum(count any) (string, error) { n, err := conv.ToInt(count) if err != nil { return "", fmt.Errorf("count must be an integer: %w", err) @@ -55,7 +55,7 @@ func (RandomFuncs) AlphaNum(count interface{}) (string, error) { } // String - -func (RandomFuncs) String(count interface{}, args ...interface{}) (string, error) { +func (RandomFuncs) String(count any, args ...any) (string, error) { c, err := conv.ToInt(count) if err != nil { return "", fmt.Errorf("count must be an integer: %w", err) @@ -98,7 +98,7 @@ func (RandomFuncs) String(count interface{}, args ...interface{}) (string, error return random.StringRE(c, m) } -func isString(s interface{}) bool { +func isString(s any) bool { switch s.(type) { case string: return true @@ -131,7 +131,7 @@ func toCodePoints(l, u string) (rune, rune, error) { } // Item - -func (RandomFuncs) Item(items interface{}) (interface{}, error) { +func (RandomFuncs) Item(items any) (any, error) { i, err := iconv.InterfaceSlice(items) if err != nil { return nil, err @@ -140,7 +140,7 @@ func (RandomFuncs) Item(items interface{}) (interface{}, error) { } // Number - -func (RandomFuncs) Number(args ...interface{}) (int64, error) { +func (RandomFuncs) Number(args ...any) (int64, error) { var nMin, nMax int64 nMin, nMax = 0, 100 @@ -169,7 +169,7 @@ func (RandomFuncs) Number(args ...interface{}) (int64, error) { } // Float - -func (RandomFuncs) Float(args ...interface{}) (float64, error) { +func (RandomFuncs) Float(args ...any) (float64, error) { var nMin, nMax float64 nMin, nMax = 0, 1.0 diff --git a/internal/funcs/random_test.go b/internal/funcs/random_test.go index c26c8ea7..d020079e 100644 --- a/internal/funcs/random_test.go +++ b/internal/funcs/random_test.go @@ -13,14 +13,14 @@ import ( func TestCreateRandomFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateRandomFuncs(ctx) - actual := fmap["random"].(func() interface{}) + actual := fmap["random"].(func() any) assert.Equal(t, ctx, actual().(*RandomFuncs).ctx) }) @@ -168,7 +168,7 @@ func TestItem(t *testing.T) { in := []string{"foo", "bar"} got := "" - for j := 0; j < 10; j++ { + for range 10 { i, err = f.Item(in) require.NoError(t, err) got += i.(string) diff --git a/internal/funcs/regexp.go b/internal/funcs/regexp.go index d7f6a685..e7091091 100644 --- a/internal/funcs/regexp.go +++ b/internal/funcs/regexp.go @@ -9,10 +9,10 @@ import ( ) // CreateReFuncs - -func CreateReFuncs(ctx context.Context) map[string]interface{} { +func CreateReFuncs(ctx context.Context) map[string]any { ns := &ReFuncs{ctx} - return map[string]interface{}{ - "regexp": func() interface{} { return ns }, + return map[string]any{ + "regexp": func() any { return ns }, } } @@ -22,12 +22,12 @@ type ReFuncs struct { } // Find - -func (ReFuncs) Find(re, input interface{}) (string, error) { +func (ReFuncs) Find(re, input any) (string, error) { return regexp.Find(conv.ToString(re), conv.ToString(input)) } // FindAll - -func (ReFuncs) FindAll(args ...interface{}) ([]string, error) { +func (ReFuncs) FindAll(args ...any) ([]string, error) { re := "" n := 0 input := "" @@ -55,31 +55,31 @@ func (ReFuncs) FindAll(args ...interface{}) ([]string, error) { } // Match - -func (ReFuncs) Match(re, input interface{}) (bool, error) { +func (ReFuncs) Match(re, input any) (bool, error) { return regexp.Match(conv.ToString(re), conv.ToString(input)) } // QuoteMeta - -func (ReFuncs) QuoteMeta(in interface{}) string { +func (ReFuncs) QuoteMeta(in any) string { return regexp.QuoteMeta(conv.ToString(in)) } // Replace - -func (ReFuncs) Replace(re, replacement, input interface{}) (string, error) { +func (ReFuncs) Replace(re, replacement, input any) (string, error) { return regexp.Replace(conv.ToString(re), conv.ToString(replacement), conv.ToString(input)) } // ReplaceLiteral - -func (ReFuncs) ReplaceLiteral(re, replacement, input interface{}) (string, error) { +func (ReFuncs) ReplaceLiteral(re, replacement, input any) (string, error) { return regexp.ReplaceLiteral(conv.ToString(re), conv.ToString(replacement), conv.ToString(input)) } // Split - -func (ReFuncs) Split(args ...interface{}) ([]string, error) { +func (ReFuncs) Split(args ...any) ([]string, error) { re := "" n := -1 input := "" diff --git a/internal/funcs/regexp_test.go b/internal/funcs/regexp_test.go index a3d30617..ac038eab 100644 --- a/internal/funcs/regexp_test.go +++ b/internal/funcs/regexp_test.go @@ -12,14 +12,14 @@ import ( func TestCreateReFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateReFuncs(ctx) - actual := fmap["regexp"].(func() interface{}) + actual := fmap["regexp"].(func() any) assert.Equal(t, ctx, actual().(*ReFuncs).ctx) }) diff --git a/internal/funcs/semver.go b/internal/funcs/semver.go index 0212c998..b4c6c203 100644 --- a/internal/funcs/semver.go +++ b/internal/funcs/semver.go @@ -7,10 +7,10 @@ import ( ) // CreateSemverFuncs - -func CreateSemverFuncs(ctx context.Context) map[string]interface{} { +func CreateSemverFuncs(ctx context.Context) map[string]any { ns := &SemverFuncs{ctx} - return map[string]interface{}{ - "semver": func() interface{} { return ns }, + return map[string]any{ + "semver": func() any { return ns }, } } diff --git a/internal/funcs/sockaddr.go b/internal/funcs/sockaddr.go index a1e607ec..b6a86643 100644 --- a/internal/funcs/sockaddr.go +++ b/internal/funcs/sockaddr.go @@ -8,10 +8,10 @@ import ( ) // CreateSockaddrFuncs - -func CreateSockaddrFuncs(ctx context.Context) map[string]interface{} { +func CreateSockaddrFuncs(ctx context.Context) map[string]any { ns := &SockaddrFuncs{ctx} - return map[string]interface{}{ - "sockaddr": func() interface{} { return ns }, + return map[string]any{ + "sockaddr": func() any { return ns }, } } @@ -56,7 +56,7 @@ func (SockaddrFuncs) Include(selectorName, selectorParam string, inputIfAddrs so } // Attr - -func (SockaddrFuncs) Attr(selectorName string, ifAddrsRaw interface{}) (string, error) { +func (SockaddrFuncs) Attr(selectorName string, ifAddrsRaw any) (string, error) { return template.Attr(selectorName, ifAddrsRaw) } diff --git a/internal/funcs/sockaddr_test.go b/internal/funcs/sockaddr_test.go index caf86bf8..d4602f6b 100644 --- a/internal/funcs/sockaddr_test.go +++ b/internal/funcs/sockaddr_test.go @@ -11,14 +11,14 @@ import ( func TestCreateSockaddrFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateSockaddrFuncs(ctx) - actual := fmap["sockaddr"].(func() interface{}) + actual := fmap["sockaddr"].(func() any) assert.Equal(t, ctx, actual().(*SockaddrFuncs).ctx) }) diff --git a/internal/funcs/strings.go b/internal/funcs/strings.go index 8b27ad19..f5f7fc1d 100644 --- a/internal/funcs/strings.go +++ b/internal/funcs/strings.go @@ -24,11 +24,11 @@ import ( ) // CreateStringFuncs - -func CreateStringFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateStringFuncs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &StringFuncs{ctx, language.Und} - f["strings"] = func() interface{} { return ns } + f["strings"] = func() any { return ns } f["replaceAll"] = ns.ReplaceAll f["title"] = ns.Title @@ -113,7 +113,7 @@ func (f *StringFuncs) oldTrim(s, cutset string) string { // ---- // Abbrev - -func (StringFuncs) Abbrev(args ...interface{}) (string, error) { +func (StringFuncs) Abbrev(args ...any) (string, error) { str := "" offset := 0 width := 0 @@ -154,27 +154,27 @@ func (StringFuncs) Abbrev(args ...interface{}) (string, error) { // ReplaceAll - // //nolint:revive -func (StringFuncs) ReplaceAll(old, new string, s interface{}) string { +func (StringFuncs) ReplaceAll(old, new string, s any) string { return strings.ReplaceAll(conv.ToString(s), old, new) } // Contains - -func (StringFuncs) Contains(substr string, s interface{}) bool { +func (StringFuncs) Contains(substr string, s any) bool { return strings.Contains(conv.ToString(s), substr) } // HasPrefix - -func (StringFuncs) HasPrefix(prefix string, s interface{}) bool { +func (StringFuncs) HasPrefix(prefix string, s any) bool { return strings.HasPrefix(conv.ToString(s), prefix) } // HasSuffix - -func (StringFuncs) HasSuffix(suffix string, s interface{}) bool { +func (StringFuncs) HasSuffix(suffix string, s any) bool { return strings.HasSuffix(conv.ToString(s), suffix) } // Repeat - -func (StringFuncs) Repeat(count int, s interface{}) (string, error) { +func (StringFuncs) Repeat(count int, s any) (string, error) { if count < 0 { return "", fmt.Errorf("negative count %d", count) } @@ -193,16 +193,16 @@ func (StringFuncs) SkipLines(skip int, in string) (string, error) { // Sort - // // Deprecated: use [CollFuncs.Sort] instead -func (f *StringFuncs) Sort(list interface{}) ([]string, error) { +func (f *StringFuncs) Sort(list any) ([]string, error) { deprecated.WarnDeprecated(f.ctx, "strings.Sort is deprecated - use coll.Sort instead") switch v := list.(type) { case []string: return gompstrings.Sort(v), nil - case []interface{}: + case []any: l := len(v) b := make([]string, len(v)) - for i := 0; i < l; i++ { + for i := range l { b[i] = conv.ToString(v[i]) } return gompstrings.Sort(b), nil @@ -212,67 +212,67 @@ func (f *StringFuncs) Sort(list interface{}) ([]string, error) { } // Split - -func (StringFuncs) Split(sep string, s interface{}) []string { +func (StringFuncs) Split(sep string, s any) []string { return strings.Split(conv.ToString(s), sep) } // SplitN - -func (StringFuncs) SplitN(sep string, n int, s interface{}) []string { +func (StringFuncs) SplitN(sep string, n int, s any) []string { return strings.SplitN(conv.ToString(s), sep, n) } // Trim - -func (StringFuncs) Trim(cutset string, s interface{}) string { +func (StringFuncs) Trim(cutset string, s any) string { return strings.Trim(conv.ToString(s), cutset) } // TrimLeft - -func (StringFuncs) TrimLeft(cutset string, s interface{}) string { +func (StringFuncs) TrimLeft(cutset string, s any) string { return strings.TrimLeft(conv.ToString(s), cutset) } // TrimPrefix - -func (StringFuncs) TrimPrefix(cutset string, s interface{}) string { +func (StringFuncs) TrimPrefix(cutset string, s any) string { return strings.TrimPrefix(conv.ToString(s), cutset) } // TrimRight - -func (StringFuncs) TrimRight(cutset string, s interface{}) string { +func (StringFuncs) TrimRight(cutset string, s any) string { return strings.TrimRight(conv.ToString(s), cutset) } // TrimSuffix - -func (StringFuncs) TrimSuffix(cutset string, s interface{}) string { +func (StringFuncs) TrimSuffix(cutset string, s any) string { return strings.TrimSuffix(conv.ToString(s), cutset) } // Title - -func (f *StringFuncs) Title(s interface{}) string { +func (f *StringFuncs) Title(s any) string { return cases.Title(f.tag, cases.NoLower).String(conv.ToString(s)) } // ToUpper - -func (f *StringFuncs) ToUpper(s interface{}) string { +func (f *StringFuncs) ToUpper(s any) string { return cases.Upper(f.tag).String(conv.ToString(s)) } // ToLower - -func (f *StringFuncs) ToLower(s interface{}) string { +func (f *StringFuncs) ToLower(s any) string { return cases.Lower(f.tag).String(conv.ToString(s)) } // TrimSpace - -func (StringFuncs) TrimSpace(s interface{}) string { +func (StringFuncs) TrimSpace(s any) string { return strings.TrimSpace(conv.ToString(s)) } // Trunc - -func (StringFuncs) Trunc(length int, s interface{}) string { +func (StringFuncs) Trunc(length int, s any) string { return gompstrings.Trunc(length, conv.ToString(s)) } // Indent - -func (StringFuncs) Indent(args ...interface{}) (string, error) { +func (StringFuncs) Indent(args ...any) (string, error) { indent := " " width := 1 @@ -309,23 +309,23 @@ func (StringFuncs) Indent(args ...interface{}) (string, error) { } // Slug - -func (StringFuncs) Slug(in interface{}) string { +func (StringFuncs) Slug(in any) string { return slug.Make(conv.ToString(in)) } // Quote - -func (StringFuncs) Quote(in interface{}) string { +func (StringFuncs) Quote(in any) string { return fmt.Sprintf("%q", conv.ToString(in)) } // ShellQuote - -func (StringFuncs) ShellQuote(in interface{}) string { +func (StringFuncs) ShellQuote(in any) string { val := reflect.ValueOf(in) switch val.Kind() { case reflect.Array, reflect.Slice: var sb strings.Builder vLen := val.Len() - for n := 0; n < vLen; n++ { + for n := range vLen { sb.WriteString(gompstrings.ShellQuote(conv.ToString(val.Index(n)))) if n+1 != vLen { sb.WriteRune(' ') @@ -337,29 +337,29 @@ func (StringFuncs) ShellQuote(in interface{}) string { } // Squote - -func (StringFuncs) Squote(in interface{}) string { +func (StringFuncs) Squote(in any) string { s := conv.ToString(in) s = strings.ReplaceAll(s, `'`, `''`) return fmt.Sprintf("'%s'", s) } // SnakeCase - -func (StringFuncs) SnakeCase(in interface{}) (string, error) { +func (StringFuncs) SnakeCase(in any) (string, error) { return gompstrings.SnakeCase(conv.ToString(in)), nil } // CamelCase - -func (StringFuncs) CamelCase(in interface{}) (string, error) { +func (StringFuncs) CamelCase(in any) (string, error) { return gompstrings.CamelCase(conv.ToString(in)), nil } // KebabCase - -func (StringFuncs) KebabCase(in interface{}) (string, error) { +func (StringFuncs) KebabCase(in any) (string, error) { return gompstrings.KebabCase(conv.ToString(in)), nil } // WordWrap - -func (StringFuncs) WordWrap(args ...interface{}) (string, error) { +func (StringFuncs) WordWrap(args ...any) (string, error) { if len(args) == 0 || len(args) > 3 { return "", fmt.Errorf("expected 1, 2, or 3 args, got %d", len(args)) } @@ -404,7 +404,7 @@ func (StringFuncs) WordWrap(args ...interface{}) (string, error) { } // RuneCount - like len(s), but for runes -func (StringFuncs) RuneCount(args ...interface{}) (int, error) { +func (StringFuncs) RuneCount(args ...any) (int, error) { s := "" for _, arg := range args { s += conv.ToString(arg) diff --git a/internal/funcs/strings_test.go b/internal/funcs/strings_test.go index 032e45e3..0194d446 100644 --- a/internal/funcs/strings_test.go +++ b/internal/funcs/strings_test.go @@ -12,14 +12,14 @@ import ( func TestCreateStringFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateStringFuncs(ctx) - actual := fmap["strings"].(func() interface{}) + actual := fmap["strings"].(func() any) assert.Equal(t, ctx, actual().(*StringFuncs).ctx) }) @@ -44,12 +44,12 @@ func TestIndent(t *testing.T) { testdata := []struct { out string - args []interface{} + args []any }{ - {" foo\n bar\n baz", []interface{}{"foo\nbar\nbaz"}}, - {" foo\n bar\n baz", []interface{}{" ", "foo\nbar\nbaz"}}, - {"---foo\n---bar\n---baz", []interface{}{3, "-", "foo\nbar\nbaz"}}, - {" foo\n bar\n baz", []interface{}{3, "foo\nbar\nbaz"}}, + {" foo\n bar\n baz", []any{"foo\nbar\nbaz"}}, + {" foo\n bar\n baz", []any{" ", "foo\nbar\nbaz"}}, + {"---foo\n---bar\n---baz", []any{3, "-", "foo\nbar\nbaz"}}, + {" foo\n bar\n baz", []any{3, "foo\nbar\nbaz"}}, } for _, d := range testdata { @@ -71,7 +71,7 @@ func TestTrimPrefix(t *testing.T) { func TestTitle(t *testing.T) { sf := &StringFuncs{} testdata := []struct { - in interface{} + in any out string }{ {``, ``}, @@ -158,7 +158,7 @@ func TestSort(t *testing.T) { out := []string{"bar", "baz", "foo"} assert.Equal(t, out, must(sf.Sort(in))) - assert.Equal(t, out, must(sf.Sort([]interface{}{"foo", "bar", "baz"}))) + assert.Equal(t, out, must(sf.Sort([]any{"foo", "bar", "baz"}))) } func TestQuote(t *testing.T) { @@ -166,7 +166,7 @@ func TestQuote(t *testing.T) { sf := &StringFuncs{} testdata := []struct { - in interface{} + in any out string }{ {``, `""`}, @@ -187,7 +187,7 @@ func TestShellQuote(t *testing.T) { sf := &StringFuncs{} testdata := []struct { - in interface{} + in any out string }{ // conventional cases are covered in gompstrings.ShellQuote() tests @@ -211,7 +211,7 @@ func TestSquote(t *testing.T) { sf := &StringFuncs{} testdata := []struct { - in interface{} + in any out string }{ {``, `''`}, @@ -263,7 +263,7 @@ func TestTrimLeft(t *testing.T) { sf := &StringFuncs{} testdata := []struct { - in interface{} + in any cutset string out string }{ @@ -287,7 +287,7 @@ func TestTrimRight(t *testing.T) { sf := &StringFuncs{} testdata := []struct { - in interface{} + in any cutset string out string }{ diff --git a/internal/funcs/test.go b/internal/funcs/test.go index 9dd780e5..9f14c5af 100644 --- a/internal/funcs/test.go +++ b/internal/funcs/test.go @@ -10,11 +10,11 @@ import ( ) // CreateTestFuncs - -func CreateTestFuncs(ctx context.Context) map[string]interface{} { - f := map[string]interface{}{} +func CreateTestFuncs(ctx context.Context) map[string]any { + f := map[string]any{} ns := &TestFuncs{ctx} - f["test"] = func() interface{} { return ns } + f["test"] = func() any { return ns } f["assert"] = ns.Assert f["fail"] = ns.Fail @@ -31,7 +31,7 @@ type TestFuncs struct { } // Assert - -func (TestFuncs) Assert(args ...interface{}) (string, error) { +func (TestFuncs) Assert(args ...any) (string, error) { input := conv.ToBool(args[len(args)-1]) switch len(args) { case 1: @@ -48,7 +48,7 @@ func (TestFuncs) Assert(args ...interface{}) (string, error) { } // Fail - -func (TestFuncs) Fail(args ...interface{}) (string, error) { +func (TestFuncs) Fail(args ...any) (string, error) { switch len(args) { case 0: return "", test.Fail("") @@ -60,7 +60,7 @@ func (TestFuncs) Fail(args ...interface{}) (string, error) { } // Required - -func (TestFuncs) Required(args ...interface{}) (interface{}, error) { +func (TestFuncs) Required(args ...any) (any, error) { switch len(args) { case 1: return test.Required("", args[0]) @@ -76,7 +76,7 @@ func (TestFuncs) Required(args ...interface{}) (interface{}, error) { } // Ternary - -func (TestFuncs) Ternary(tval, fval, b interface{}) interface{} { +func (TestFuncs) Ternary(tval, fval, b any) any { if conv.ToBool(b) { return tval } @@ -84,12 +84,12 @@ func (TestFuncs) Ternary(tval, fval, b interface{}) interface{} { } // Kind - return the kind of the argument -func (TestFuncs) Kind(arg interface{}) string { +func (TestFuncs) Kind(arg any) string { return reflect.ValueOf(arg).Kind().String() } // IsKind - return whether or not the argument is of the given kind -func (f TestFuncs) IsKind(kind string, arg interface{}) bool { +func (f TestFuncs) IsKind(kind string, arg any) bool { k := f.Kind(arg) if kind == "number" { switch k { diff --git a/internal/funcs/test_test.go b/internal/funcs/test_test.go index 98ae6753..4ce5d9b7 100644 --- a/internal/funcs/test_test.go +++ b/internal/funcs/test_test.go @@ -12,14 +12,14 @@ import ( func TestCreateTestFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateTestFuncs(ctx) - actual := fmap["test"].(func() interface{}) + actual := fmap["test"].(func() any) assert.Equal(t, ctx, actual().(*TestFuncs).ctx) }) @@ -93,8 +93,8 @@ func TestTernary(t *testing.T) { f := TestFuncs{ctx: context.Background()} testdata := []struct { - tval, fval, b interface{} - expected interface{} + tval, fval, b any + expected any }{ {"foo", 42, false, 42}, {"foo", 42, "yes", "foo"}, @@ -110,7 +110,7 @@ func TestKind(t *testing.T) { f := TestFuncs{ctx: context.Background()} testdata := []struct { - arg interface{} + arg any expected string }{ {"foo", "string"}, @@ -133,7 +133,7 @@ func TestIsKind(t *testing.T) { f := TestFuncs{ctx: context.Background()} truedata := []struct { - arg interface{} + arg any kind string }{ {"foo", "string"}, @@ -155,7 +155,7 @@ func TestIsKind(t *testing.T) { } falsedata := []struct { - arg interface{} + arg any kind string }{ {"foo", "bool"}, diff --git a/internal/funcs/time.go b/internal/funcs/time.go index fa2f6424..08217412 100644 --- a/internal/funcs/time.go +++ b/internal/funcs/time.go @@ -14,7 +14,7 @@ import ( ) // CreateTimeFuncs - -func CreateTimeFuncs(ctx context.Context) map[string]interface{} { +func CreateTimeFuncs(ctx context.Context) map[string]any { ns := &TimeFuncs{ ctx: ctx, ANSIC: gotime.ANSIC, @@ -34,8 +34,8 @@ func CreateTimeFuncs(ctx context.Context) map[string]interface{} { StampNano: gotime.StampNano, } - return map[string]interface{}{ - "time": func() interface{} { return ns }, + return map[string]any{ + "time": func() any { return ns }, } } @@ -70,18 +70,18 @@ func (TimeFuncs) ZoneOffset() int { } // Parse - -func (TimeFuncs) Parse(layout string, value interface{}) (gotime.Time, error) { +func (TimeFuncs) Parse(layout string, value any) (gotime.Time, error) { return gotime.Parse(layout, conv.ToString(value)) } // ParseLocal - -func (f TimeFuncs) ParseLocal(layout string, value interface{}) (gotime.Time, error) { +func (f TimeFuncs) ParseLocal(layout string, value any) (gotime.Time, error) { tz := env.Getenv("TZ", "Local") return f.ParseInLocation(layout, tz, value) } // ParseInLocation - -func (TimeFuncs) ParseInLocation(layout, location string, value interface{}) (gotime.Time, error) { +func (TimeFuncs) ParseInLocation(layout, location string, value any) (gotime.Time, error) { loc, err := gotime.LoadLocation(location) if err != nil { return gotime.Time{}, err @@ -96,7 +96,7 @@ func (TimeFuncs) Now() gotime.Time { // Unix - convert UNIX time (in seconds since the UNIX epoch) into a time.Time for further processing // Takes a string or number (int or float) -func (TimeFuncs) Unix(in interface{}) (gotime.Time, error) { +func (TimeFuncs) Unix(in any) (gotime.Time, error) { sec, nsec, err := parseNum(in) if err != nil { return gotime.Time{}, err @@ -105,7 +105,7 @@ func (TimeFuncs) Unix(in interface{}) (gotime.Time, error) { } // Nanosecond - -func (TimeFuncs) Nanosecond(n interface{}) (gotime.Duration, error) { +func (TimeFuncs) Nanosecond(n any) (gotime.Duration, error) { in, err := conv.ToInt64(n) if err != nil { return 0, fmt.Errorf("expected a number: %w", err) @@ -115,7 +115,7 @@ func (TimeFuncs) Nanosecond(n interface{}) (gotime.Duration, error) { } // Microsecond - -func (TimeFuncs) Microsecond(n interface{}) (gotime.Duration, error) { +func (TimeFuncs) Microsecond(n any) (gotime.Duration, error) { in, err := conv.ToInt64(n) if err != nil { return 0, fmt.Errorf("expected a number: %w", err) @@ -125,7 +125,7 @@ func (TimeFuncs) Microsecond(n interface{}) (gotime.Duration, error) { } // Millisecond - -func (TimeFuncs) Millisecond(n interface{}) (gotime.Duration, error) { +func (TimeFuncs) Millisecond(n any) (gotime.Duration, error) { in, err := conv.ToInt64(n) if err != nil { return 0, fmt.Errorf("expected a number: %w", err) @@ -135,7 +135,7 @@ func (TimeFuncs) Millisecond(n interface{}) (gotime.Duration, error) { } // Second - -func (TimeFuncs) Second(n interface{}) (gotime.Duration, error) { +func (TimeFuncs) Second(n any) (gotime.Duration, error) { in, err := conv.ToInt64(n) if err != nil { return 0, fmt.Errorf("expected a number: %w", err) @@ -145,7 +145,7 @@ func (TimeFuncs) Second(n interface{}) (gotime.Duration, error) { } // Minute - -func (TimeFuncs) Minute(n interface{}) (gotime.Duration, error) { +func (TimeFuncs) Minute(n any) (gotime.Duration, error) { in, err := conv.ToInt64(n) if err != nil { return 0, fmt.Errorf("expected a number: %w", err) @@ -155,7 +155,7 @@ func (TimeFuncs) Minute(n interface{}) (gotime.Duration, error) { } // Hour - -func (TimeFuncs) Hour(n interface{}) (gotime.Duration, error) { +func (TimeFuncs) Hour(n any) (gotime.Duration, error) { in, err := conv.ToInt64(n) if err != nil { return 0, fmt.Errorf("expected a number: %w", err) @@ -165,7 +165,7 @@ func (TimeFuncs) Hour(n interface{}) (gotime.Duration, error) { } // ParseDuration - -func (TimeFuncs) ParseDuration(n interface{}) (gotime.Duration, error) { +func (TimeFuncs) ParseDuration(n any) (gotime.Duration, error) { return gotime.ParseDuration(conv.ToString(n)) } @@ -182,7 +182,7 @@ func (TimeFuncs) Until(n gotime.Time) gotime.Duration { // convert a number input to a pair of int64s, representing the integer portion and the decimal remainder // this can handle a string as well as any integer or float type // precision is at the "nano" level (i.e. 1e+9) -func parseNum(in interface{}) (integral int64, fractional int64, err error) { +func parseNum(in any) (integral int64, fractional int64, err error) { if s, ok := in.(string); ok { ss := strings.Split(s, ".") if len(ss) > 2 { diff --git a/internal/funcs/time_test.go b/internal/funcs/time_test.go index 8d229025..f24a99b6 100644 --- a/internal/funcs/time_test.go +++ b/internal/funcs/time_test.go @@ -14,14 +14,14 @@ import ( func TestCreateTimeFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateTimeFuncs(ctx) - actual := fmap["time"].(func() interface{}) + actual := fmap["time"].(func() any) assert.Equal(t, ctx, actual().(*TimeFuncs).ctx) }) diff --git a/internal/funcs/uuid.go b/internal/funcs/uuid.go index 6831dbf7..097c5b4d 100644 --- a/internal/funcs/uuid.go +++ b/internal/funcs/uuid.go @@ -9,10 +9,10 @@ import ( ) // CreateUUIDFuncs - -func CreateUUIDFuncs(ctx context.Context) map[string]interface{} { +func CreateUUIDFuncs(ctx context.Context) map[string]any { ns := &UUIDFuncs{ctx} - return map[string]interface{}{ - "uuid": func() interface{} { return ns }, + return map[string]any{ + "uuid": func() any { return ns }, } } @@ -47,7 +47,7 @@ func (UUIDFuncs) Nil() (string, error) { // IsValid - checks if the given UUID is in the correct format. It does not // validate whether the version or variant are correct. -func (f UUIDFuncs) IsValid(in interface{}) (bool, error) { +func (f UUIDFuncs) IsValid(in any) (bool, error) { _, err := f.Parse(in) return err == nil, nil } @@ -58,7 +58,7 @@ func (f UUIDFuncs) IsValid(in interface{}) (bool, error) { // urn:uuid:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx are decoded as well as the // Microsoft encoding {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx} and the raw hex // encoding: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. -func (UUIDFuncs) Parse(in interface{}) (uuid.UUID, error) { +func (UUIDFuncs) Parse(in any) (uuid.UUID, error) { u, err := uuid.Parse(conv.ToString(in)) if err != nil { return uuid.Nil, err diff --git a/internal/funcs/uuid_test.go b/internal/funcs/uuid_test.go index 57d5c63b..627b384e 100644 --- a/internal/funcs/uuid_test.go +++ b/internal/funcs/uuid_test.go @@ -13,14 +13,14 @@ import ( func TestCreateUUIDFuncs(t *testing.T) { t.Parallel() - for i := 0; i < 10; i++ { + for i := range 10 { // Run this a bunch to catch race conditions t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() ctx := context.Background() fmap := CreateUUIDFuncs(ctx) - actual := fmap["uuid"].(func() interface{}) + actual := fmap["uuid"].(func() any) assert.Equal(t, ctx, actual().(*UUIDFuncs).ctx) }) @@ -63,7 +63,7 @@ func TestIsValid(t *testing.T) { t.Parallel() u := UUIDFuncs{ctx: context.Background()} - in := interface{}(false) + in := any(false) i, err := u.IsValid(in) require.NoError(t, err) assert.False(t, i) @@ -73,7 +73,7 @@ func TestIsValid(t *testing.T) { require.NoError(t, err) assert.False(t, i) - testdata := []interface{}{ + testdata := []any{ "123456781234123412341234567890ab", "12345678-1234-1234-1234-1234567890ab", "urn:uuid:12345678-1234-1234-1234-1234567890ab", @@ -91,7 +91,7 @@ func TestParse(t *testing.T) { t.Parallel() u := UUIDFuncs{ctx: context.Background()} - in := interface{}(false) + in := any(false) _, err := u.Parse(in) require.Error(t, err) @@ -100,7 +100,7 @@ func TestParse(t *testing.T) { require.Error(t, err) in = "12345678-1234-1234-1234-1234567890ab" - testdata := []interface{}{ + testdata := []any{ "123456781234123412341234567890ab", "12345678-1234-1234-1234-1234567890ab", "urn:uuid:12345678-1234-1234-1234-1234567890ab", diff --git a/internal/parsers/parsefuncs.go b/internal/parsers/parsefuncs.go index c16f86e7..0a309ab2 100644 --- a/internal/parsers/parsefuncs.go +++ b/internal/parsers/parsefuncs.go @@ -25,7 +25,7 @@ import ( "github.com/hairyhenderson/yaml" ) -func unmarshalObj(obj map[string]interface{}, in string, f func([]byte, interface{}) error) (map[string]interface{}, error) { +func unmarshalObj(obj map[string]any, in string, f func([]byte, any) error) (map[string]any, error) { err := f([]byte(in), &obj) if err != nil { return nil, fmt.Errorf("unable to unmarshal object %s: %w", in, err) @@ -33,7 +33,7 @@ func unmarshalObj(obj map[string]interface{}, in string, f func([]byte, interfac return obj, nil } -func unmarshalArray(obj []interface{}, in string, f func([]byte, interface{}) error) ([]interface{}, error) { +func unmarshalArray(obj []any, in string, f func([]byte, any) error) ([]any, error) { err := f([]byte(in), &obj) if err != nil { return nil, fmt.Errorf("unable to unmarshal array %s: %w", in, err) @@ -42,8 +42,8 @@ func unmarshalArray(obj []interface{}, in string, f func([]byte, interface{}) er } // JSON - Unmarshal a JSON Object. Can be ejson-encrypted. -func JSON(in string) (map[string]interface{}, error) { - obj := make(map[string]interface{}) +func JSON(in string) (map[string]any, error) { + obj := make(map[string]any) out, err := unmarshalObj(obj, in, yaml.Unmarshal) if err != nil { return out, err @@ -57,7 +57,7 @@ func JSON(in string) (map[string]interface{}, error) { } // decryptEJSON - decrypts an ejson input, and unmarshals it, stripping the _public_key field. -func decryptEJSON(in string) (map[string]interface{}, error) { +func decryptEJSON(in string) (map[string]any, error) { keyDir := getenv("EJSON_KEYDIR", "/opt/ejson/keys") key := getenv("EJSON_KEY") @@ -67,7 +67,7 @@ func decryptEJSON(in string) (map[string]interface{}, error) { if err != nil { return nil, err } - obj := make(map[string]interface{}) + obj := make(map[string]any) out, err := unmarshalObj(obj, rOut.String(), yaml.Unmarshal) if err != nil { return nil, err @@ -101,14 +101,14 @@ func getenv(key string, def ...string) string { } // JSONArray - Unmarshal a JSON Array -func JSONArray(in string) ([]interface{}, error) { - obj := make([]interface{}, 1) +func JSONArray(in string) ([]any, error) { + obj := make([]any, 1) return unmarshalArray(obj, in, yaml.Unmarshal) } // YAML - Unmarshal a YAML Object -func YAML(in string) (map[string]interface{}, error) { - obj := make(map[string]interface{}) +func YAML(in string) (map[string]any, error) { + obj := make(map[string]any) s := strings.NewReader(in) d := yaml.NewDecoder(s) for { @@ -129,8 +129,8 @@ func YAML(in string) (map[string]interface{}, error) { } // YAMLArray - Unmarshal a YAML Array -func YAMLArray(in string) ([]interface{}, error) { - obj := make([]interface{}, 1) +func YAMLArray(in string) ([]any, error) { + obj := make([]any, 1) s := strings.NewReader(in) d := yaml.NewDecoder(s) for { @@ -151,7 +151,7 @@ func YAMLArray(in string) ([]interface{}, error) { // stringifyYAMLArrayMapKeys recurses into the input array and changes all // non-string map keys to string map keys. Modifies the input array. -func stringifyYAMLArrayMapKeys(in []interface{}) error { +func stringifyYAMLArrayMapKeys(in []any) error { if _, changed := stringifyMapKeys(in); changed { return fmt.Errorf("stringifyYAMLArrayMapKeys: output type did not match input type, this should be impossible") } @@ -160,7 +160,7 @@ func stringifyYAMLArrayMapKeys(in []interface{}) error { // stringifyYAMLMapMapKeys recurses into the input map and changes all // non-string map keys to string map keys. Modifies the input map. -func stringifyYAMLMapMapKeys(in map[string]interface{}) error { +func stringifyYAMLMapMapKeys(in map[string]any) error { if _, changed := stringifyMapKeys(in); changed { return fmt.Errorf("stringifyYAMLMapMapKeys: output type did not match input type, this should be impossible") } @@ -168,28 +168,28 @@ func stringifyYAMLMapMapKeys(in map[string]interface{}) error { } // stringifyMapKeys recurses into in and changes all instances of -// map[interface{}]interface{} to map[string]interface{}. This is useful to +// map[any]any to map[string]any. This is useful to // work around the impedance mismatch between JSON and YAML unmarshaling that's // described here: https://github.com/go-yaml/yaml/issues/139 // // Taken and modified from https://github.com/gohugoio/hugo/blob/cdfd1c99baa22d69e865294dfcd783811f96c880/parser/metadecoders/decoder.go#L257, Apache License 2.0 // Originally inspired by https://github.com/stripe/stripe-mock/blob/24a2bb46a49b2a416cfea4150ab95781f69ee145/mapstr.go#L13, MIT License -func stringifyMapKeys(in interface{}) (interface{}, bool) { +func stringifyMapKeys(in any) (any, bool) { switch in := in.(type) { - case []interface{}: + case []any: for i, v := range in { if vv, replaced := stringifyMapKeys(v); replaced { in[i] = vv } } - case map[string]interface{}: + case map[string]any: for k, v := range in { if vv, changed := stringifyMapKeys(v); changed { in[k] = vv } } - case map[interface{}]interface{}: - res := make(map[string]interface{}) + case map[any]any: + res := make(map[string]any) for k, v := range in { ks := conv.ToString(k) @@ -206,18 +206,18 @@ func stringifyMapKeys(in interface{}) (interface{}, bool) { } // TOML - Unmarshal a TOML Object -func TOML(in string) (interface{}, error) { - obj := make(map[string]interface{}) +func TOML(in string) (any, error) { + obj := make(map[string]any) return unmarshalObj(obj, in, toml.Unmarshal) } // DotEnv - Unmarshal a dotenv file -func DotEnv(in string) (interface{}, error) { +func DotEnv(in string) (any, error) { env, err := godotenv.Unmarshal(in) if err != nil { return nil, err } - out := make(map[string]interface{}) + out := make(map[string]any) for k, v := range env { out[k] = v } @@ -352,7 +352,7 @@ func CSVByColumn(args ...string) (cols map[string][]string, err error) { } // ToCSV - -func ToCSV(args ...interface{}) (string, error) { +func ToCSV(args ...any) (string, error) { delim := "," var in [][]string if len(args) == 2 { @@ -367,22 +367,22 @@ func ToCSV(args ...interface{}) (string, error) { switch a := args[0].(type) { case [][]string: in = a - case [][]interface{}: + case [][]any: in = make([][]string, len(a)) for i, v := range a { in[i] = conv.ToStrings(v...) } - case []interface{}: + case []any: in = make([][]string, len(a)) for i, v := range a { - ar, ok := v.([]interface{}) + ar, ok := v.([]any) if !ok { - return "", fmt.Errorf("can't parse ToCSV input - must be a two-dimensional array (like [][]string or [][]interface{}) (was %T)", args[0]) + return "", fmt.Errorf("can't parse ToCSV input - must be a two-dimensional array (like [][]string or [][]any) (was %T)", args[0]) } in[i] = conv.ToStrings(ar...) } default: - return "", fmt.Errorf("can't parse ToCSV input - must be a two-dimensional array (like [][]string or [][]interface{}) (was %T)", args[0]) + return "", fmt.Errorf("can't parse ToCSV input - must be a two-dimensional array (like [][]string or [][]any) (was %T)", args[0]) } } b := &bytes.Buffer{} @@ -397,7 +397,7 @@ func ToCSV(args ...interface{}) (string, error) { return b.String(), nil } -func marshalObj(obj interface{}, f func(interface{}) ([]byte, error)) (string, error) { +func marshalObj(obj any, f func(any) ([]byte, error)) (string, error) { b, err := f(obj) if err != nil { return "", fmt.Errorf("unable to marshal object %s: %w", obj, err) @@ -406,7 +406,7 @@ func marshalObj(obj interface{}, f func(interface{}) ([]byte, error)) (string, e return string(b), nil } -func toJSONBytes(in interface{}) ([]byte, error) { +func toJSONBytes(in any) ([]byte, error) { h := &codec.JsonHandle{} h.Canonical = true buf := new(bytes.Buffer) @@ -418,7 +418,7 @@ func toJSONBytes(in interface{}) ([]byte, error) { } // ToJSON - Stringify a struct as JSON -func ToJSON(in interface{}) (string, error) { +func ToJSON(in any) (string, error) { s, err := toJSONBytes(in) if err != nil { return "", err @@ -427,7 +427,7 @@ func ToJSON(in interface{}) (string, error) { } // ToJSONPretty - Stringify a struct as JSON (indented) -func ToJSONPretty(indent string, in interface{}) (string, error) { +func ToJSONPretty(indent string, in any) (string, error) { out := new(bytes.Buffer) b, err := toJSONBytes(in) if err != nil { @@ -442,10 +442,10 @@ func ToJSONPretty(indent string, in interface{}) (string, error) { } // ToYAML - Stringify a struct as YAML -func ToYAML(in interface{}) (string, error) { +func ToYAML(in any) (string, error) { // I'd use yaml.Marshal, but between v2 and v3 the indent has changed from // 2 to 4. This explicitly sets it back to 2. - marshal := func(in interface{}) (out []byte, err error) { + marshal := func(in any) (out []byte, err error) { buf := &bytes.Buffer{} e := yaml.NewEncoder(buf) e.SetIndent(2) @@ -458,7 +458,7 @@ func ToYAML(in interface{}) (string, error) { } // ToTOML - Stringify a struct as TOML -func ToTOML(in interface{}) (string, error) { +func ToTOML(in any) (string, error) { buf := new(bytes.Buffer) err := toml.NewEncoder(buf).Encode(in) if err != nil { @@ -468,7 +468,7 @@ func ToTOML(in interface{}) (string, error) { } // CUE - Unmarshal a CUE expression into the appropriate type -func CUE(in string) (interface{}, error) { +func CUE(in string) (any, error) { cuectx := cuecontext.New() val := cuectx.CompileString(in) @@ -478,11 +478,11 @@ func CUE(in string) (interface{}, error) { switch val.Kind() { case cue.StructKind: - out := map[string]interface{}{} + out := map[string]any{} err := val.Decode(&out) return out, err case cue.ListKind: - out := []interface{}{} + out := []any{} err := val.Decode(&out) return out, err case cue.BytesKind: @@ -512,7 +512,7 @@ func CUE(in string) (interface{}, error) { } } -func ToCUE(in interface{}) (string, error) { +func ToCUE(in any) (string, error) { cuectx := cuecontext.New() v := cuectx.Encode(in) if v.Err() != nil { diff --git a/internal/parsers/parsefuncs_test.go b/internal/parsers/parsefuncs_test.go index 99aa1887..76e7b2ac 100644 --- a/internal/parsers/parsefuncs_test.go +++ b/internal/parsers/parsefuncs_test.go @@ -15,14 +15,14 @@ import ( ) func TestUnmarshalObj(t *testing.T) { - expected := map[string]interface{}{ - "foo": map[string]interface{}{"bar": "baz"}, + expected := map[string]any{ + "foo": map[string]any{"bar": "baz"}, "one": 1.0, "true": true, "escaped": "\"/\\\b\f\n\r\t∞", } - test := func(actual map[string]interface{}, err error) { + test := func(actual map[string]any, err error) { t.Helper() require.NoError(t, err) assert.Equal(t, expected["foo"], actual["foo"], "foo") @@ -56,24 +56,24 @@ one: 1.0 escaped: "\"\/\\\b\f\n\r\t\u221e" `)) - obj := make(map[string]interface{}) - _, err := unmarshalObj(obj, "SOMETHING", func(_ []byte, _ interface{}) error { + obj := make(map[string]any) + _, err := unmarshalObj(obj, "SOMETHING", func(_ []byte, _ any) error { return fmt.Errorf("fail") }) assert.EqualError(t, err, "unable to unmarshal object SOMETHING: fail") } func TestUnmarshalArray(t *testing.T) { - expected := []interface{}{ + expected := []any{ "foo", "bar", - map[string]interface{}{ - "baz": map[string]interface{}{"qux": true}, - "quux": map[string]interface{}{"42": 18}, - "corge": map[string]interface{}{"false": "blah"}, + map[string]any{ + "baz": map[string]any{"qux": true}, + "quux": map[string]any{"42": 18}, + "corge": map[string]any{"false": "blah"}, }, } - test := func(actual []interface{}, err error) { + test := func(actual []any, err error) { require.NoError(t, err) assert.EqualValues(t, expected, actual) } @@ -116,20 +116,20 @@ this shouldn't be reached `) require.NoError(t, err) assert.EqualValues(t, - []interface{}{ - map[string]interface{}{ - "foo": map[string]interface{}{ + []any{ + map[string]any{ + "foo": map[string]any{ "bar": "baz", }, }, - map[string]interface{}{ - "qux": map[string]interface{}{ + map[string]any{ + "qux": map[string]any{ "bar": "baz", "quux": "corge", }, }, - map[string]interface{}{ - "baz": map[string]interface{}{ + map[string]any{ + "baz": map[string]any{ "qux": true, "42": 18, "false": "blah", @@ -138,8 +138,8 @@ this shouldn't be reached }, actual) - obj := make([]interface{}, 1) - _, err = unmarshalArray(obj, "SOMETHING", func(_ []byte, _ interface{}) error { + obj := make([]any, 1) + _, err = unmarshalArray(obj, "SOMETHING", func(_ []byte, _ any) error { return fmt.Errorf("fail") }) assert.EqualError(t, err, "unable to unmarshal array SOMETHING: fail") @@ -147,12 +147,12 @@ this shouldn't be reached func TestMarshalObj(t *testing.T) { expected := "foo" - actual, err := marshalObj(nil, func(_ interface{}) ([]byte, error) { + actual, err := marshalObj(nil, func(_ any) ([]byte, error) { return []byte("foo"), nil }) require.NoError(t, err) assert.Equal(t, expected, actual) - _, err = marshalObj(nil, func(_ interface{}) ([]byte, error) { + _, err = marshalObj(nil, func(_ any) ([]byte, error) { return nil, fmt.Errorf("fail") }) require.Error(t, err) @@ -179,13 +179,13 @@ func (b *badObject) CodecDecodeSelf(_ *codec.Decoder) { func TestToJSON(t *testing.T) { expected := `{"down":{"the":{"rabbit":{"hole":true}}},"foo":"bar","one":1,"true":true}` - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "one": 1, "true": true, - "down": map[interface{}]interface{}{ - "the": map[interface{}]interface{}{ - "rabbit": map[interface{}]interface{}{ + "down": map[any]any{ + "the": map[any]any{ + "rabbit": map[any]any{ "hole": true, }, }, @@ -212,13 +212,13 @@ func TestToJSONPretty(t *testing.T) { "one": 1, "true": true }` - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "one": 1, "true": true, - "down": map[string]interface{}{ - "the": map[string]interface{}{ - "rabbit": map[string]interface{}{ + "down": map[string]any{ + "the": map[string]any{ + "rabbit": map[string]any{ "hole": true, }, }, @@ -244,13 +244,13 @@ one: 1 "true": true ` mst, _ := time.LoadLocation("MST") - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "one": 1, "true": true, `multi line -key`: map[string]interface{}{ +key`: map[string]any{ "hello": "world", }, "d": time.Date(2006, time.January, 2, 15, 4, 5, 999999999, mst), @@ -384,7 +384,7 @@ func TestToCSV(t *testing.T) { require.Error(t, err) expected = "first,second,third\r\n1,2,3\r\n4,5,6\r\n" - out, err = ToCSV([][]interface{}{ + out, err = ToCSV([][]any{ {"first", "second", "third"}, {"1", "2", "3"}, {"4", "5", "6"}, @@ -393,10 +393,10 @@ func TestToCSV(t *testing.T) { assert.Equal(t, expected, out) expected = "first|second|third\r\n1|2|3\r\n4|5|6\r\n" - out, err = ToCSV("|", []interface{}{ - []interface{}{"first", "second", "third"}, - []interface{}{1, "2", 3}, - []interface{}{"4", 5, "6"}, + out, err = ToCSV("|", []any{ + []any{"first", "second", "third"}, + []any{1, "2", 3}, + []any{"4", 5, "6"}, }) require.NoError(t, err) assert.Equal(t, expected, out) @@ -439,36 +439,36 @@ hosts = [ "omega" ] ` - expected := map[string]interface{}{ + expected := map[string]any{ "title": "TOML Example", - "owner": map[string]interface{}{ + "owner": map[string]any{ "name": "Tom Preston-Werner", "organization": "GitHub", "bio": "GitHub Cofounder & CEO\nLikes tater tots and beer.", "dob": time.Date(1979, time.May, 27, 7, 32, 0, 0, time.UTC), }, - "database": map[string]interface{}{ + "database": map[string]any{ "server": "192.168.1.1", - "ports": []interface{}{int64(8001), int64(8001), int64(8002)}, + "ports": []any{int64(8001), int64(8001), int64(8002)}, "connection_max": int64(5000), "enabled": true, }, - "servers": map[string]interface{}{ - "alpha": map[string]interface{}{ + "servers": map[string]any{ + "alpha": map[string]any{ "ip": "10.0.0.1", "dc": "eqdc10", }, - "beta": map[string]interface{}{ + "beta": map[string]any{ "ip": "10.0.0.2", "dc": "eqdc10", }, }, - "clients": map[string]interface{}{ - "data": []interface{}{ - []interface{}{"gamma", "delta"}, - []interface{}{int64(1), int64(2)}, + "clients": map[string]any{ + "data": []any{ + []any{"gamma", "delta"}, + []any{int64(1), int64(2)}, }, - "hosts": []interface{}{"alpha", "omega"}, + "hosts": []any{"alpha", "omega"}, }, } @@ -487,13 +487,13 @@ true = true [down.the.rabbit] hole = true ` - in := map[string]interface{}{ + in := map[string]any{ "foo": "bar", "one": 1, "true": true, - "down": map[interface{}]interface{}{ - "the": map[interface{}]interface{}{ - "rabbit": map[interface{}]interface{}{ + "down": map[any]any{ + "the": map[any]any{ + "rabbit": map[any]any{ "hole": true, }, }, @@ -507,7 +507,7 @@ true = true func TestDecryptEJSON(t *testing.T) { privateKey := "e282d979654f88267f7e6c2d8268f1f4314b8673579205ed0029b76de9c8223f" publicKey := "6e05ec625bcdca34864181cc43e6fcc20a57732a453bc2f4a2e117ffdf1a6762" - expected := map[string]interface{}{ + expected := map[string]any{ "password": "supersecret", "_unencrypted": "notsosecret", } @@ -555,7 +555,7 @@ FOO.BAR = "values can be double-quoted, and shell\nescapes are supported" BAZ = "variable expansion: ${FOO}" QUX='single quotes ignore $variables' ` - expected := map[string]interface{}{ + expected := map[string]any{ "FOO": "a regular unquoted value", "BAR": "another value, exports are ignored", "FOO.BAR": "values can be double-quoted, and shell\nescapes are supported", @@ -569,43 +569,43 @@ QUX='single quotes ignore $variables' func TestStringifyYAMLArrayMapKeys(t *testing.T) { cases := []struct { - input []interface{} - want []interface{} + input []any + want []any replaced bool }{ { - []interface{}{map[interface{}]interface{}{"a": 1, "b": 2}}, - []interface{}{map[string]interface{}{"a": 1, "b": 2}}, + []any{map[any]any{"a": 1, "b": 2}}, + []any{map[string]any{"a": 1, "b": 2}}, false, }, { - []interface{}{map[interface{}]interface{}{"a": []interface{}{1, map[interface{}]interface{}{"b": 2}}}}, - []interface{}{map[string]interface{}{"a": []interface{}{1, map[string]interface{}{"b": 2}}}}, + []any{map[any]any{"a": []any{1, map[any]any{"b": 2}}}}, + []any{map[string]any{"a": []any{1, map[string]any{"b": 2}}}}, false, }, { - []interface{}{map[interface{}]interface{}{true: 1, "b": false}}, - []interface{}{map[string]interface{}{"true": 1, "b": false}}, + []any{map[any]any{true: 1, "b": false}}, + []any{map[string]any{"true": 1, "b": false}}, false, }, { - []interface{}{map[interface{}]interface{}{1: "a", 2: "b"}}, - []interface{}{map[string]interface{}{"1": "a", "2": "b"}}, + []any{map[any]any{1: "a", 2: "b"}}, + []any{map[string]any{"1": "a", "2": "b"}}, false, }, { - []interface{}{map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": 1}}}, - []interface{}{map[string]interface{}{"a": map[string]interface{}{"b": 1}}}, + []any{map[any]any{"a": map[any]any{"b": 1}}}, + []any{map[string]any{"a": map[string]any{"b": 1}}}, false, }, { - []interface{}{map[string]interface{}{"a": map[string]interface{}{"b": 1}}}, - []interface{}{map[string]interface{}{"a": map[string]interface{}{"b": 1}}}, + []any{map[string]any{"a": map[string]any{"b": 1}}}, + []any{map[string]any{"a": map[string]any{"b": 1}}}, false, }, { - []interface{}{map[interface{}]interface{}{1: "a", 2: "b"}}, - []interface{}{map[string]interface{}{"1": "a", "2": "b"}}, + []any{map[any]any{1: "a", 2: "b"}}, + []any{map[string]any{"1": "a", "2": "b"}}, false, }, } @@ -619,36 +619,36 @@ func TestStringifyYAMLArrayMapKeys(t *testing.T) { func TestStringifyYAMLMapMapKeys(t *testing.T) { cases := []struct { - input map[string]interface{} - want map[string]interface{} + input map[string]any + want map[string]any }{ { - map[string]interface{}{"root": map[interface{}]interface{}{"a": 1, "b": 2}}, - map[string]interface{}{"root": map[string]interface{}{"a": 1, "b": 2}}, + map[string]any{"root": map[any]any{"a": 1, "b": 2}}, + map[string]any{"root": map[string]any{"a": 1, "b": 2}}, }, { - map[string]interface{}{"root": map[interface{}]interface{}{"a": []interface{}{1, map[interface{}]interface{}{"b": 2}}}}, - map[string]interface{}{"root": map[string]interface{}{"a": []interface{}{1, map[string]interface{}{"b": 2}}}}, + map[string]any{"root": map[any]any{"a": []any{1, map[any]any{"b": 2}}}}, + map[string]any{"root": map[string]any{"a": []any{1, map[string]any{"b": 2}}}}, }, { - map[string]interface{}{"root": map[interface{}]interface{}{true: 1, "b": false}}, - map[string]interface{}{"root": map[string]interface{}{"true": 1, "b": false}}, + map[string]any{"root": map[any]any{true: 1, "b": false}}, + map[string]any{"root": map[string]any{"true": 1, "b": false}}, }, { - map[string]interface{}{"root": map[interface{}]interface{}{1: "a", 2: "b"}}, - map[string]interface{}{"root": map[string]interface{}{"1": "a", "2": "b"}}, + map[string]any{"root": map[any]any{1: "a", 2: "b"}}, + map[string]any{"root": map[string]any{"1": "a", "2": "b"}}, }, { - map[string]interface{}{"root": map[interface{}]interface{}{"a": map[interface{}]interface{}{"b": 1}}}, - map[string]interface{}{"root": map[string]interface{}{"a": map[string]interface{}{"b": 1}}}, + map[string]any{"root": map[any]any{"a": map[any]any{"b": 1}}}, + map[string]any{"root": map[string]any{"a": map[string]any{"b": 1}}}, }, { - map[string]interface{}{"a": map[string]interface{}{"b": 1}}, - map[string]interface{}{"a": map[string]interface{}{"b": 1}}, + map[string]any{"a": map[string]any{"b": 1}}, + map[string]any{"a": map[string]any{"b": 1}}, }, { - map[string]interface{}{"root": []interface{}{map[interface{}]interface{}{1: "a", 2: "b"}}}, - map[string]interface{}{"root": []interface{}{map[string]interface{}{"1": "a", "2": "b"}}}, + map[string]any{"root": []any{map[any]any{1: "a", 2: "b"}}}, + map[string]any{"root": []any{map[string]any{"1": "a", "2": "b"}}}, }, } @@ -670,8 +670,8 @@ two: 2 list: [ 1, 2, 3 ] ` - expected := map[string]interface{}{ - "matches": []interface{}{ + expected := map[string]any{ + "matches": []any{ "localhost:443", "localhost", "443", @@ -679,7 +679,7 @@ list: [ 1, 2, 3 ] "one": int64(1), "two": int64(2), "two-and-a-half": 2.5, - "list": []interface{}{int64(1), int64(2), int64(3)}, + "list": []any{int64(1), int64(2), int64(3)}, } out, err := CUE(in) @@ -688,7 +688,7 @@ list: [ 1, 2, 3 ] out, err = CUE(`[1,2,3]`) require.NoError(t, err) - assert.Equal(t, []interface{}{int64(1), int64(2), int64(3)}, out) + assert.Equal(t, []any{int64(1), int64(2), int64(3)}, out) out, err = CUE(`"hello world"`) require.NoError(t, err) @@ -720,8 +720,8 @@ list: [ 1, 2, 3 ] } func TestToCUE(t *testing.T) { - in := map[string]interface{}{ - "matches": []interface{}{ + in := map[string]any{ + "matches": []any{ "localhost:443", "localhost", "443", @@ -729,7 +729,7 @@ func TestToCUE(t *testing.T) { "one": 1, "two": 2, "two-and-a-half": 2.5, - "list": []interface{}{1, 2, 3}, + "list": []any{1, 2, 3}, } expected := `{ @@ -744,7 +744,7 @@ func TestToCUE(t *testing.T) { require.NoError(t, err) assert.EqualValues(t, expected, out) - out, err = ToCUE([]interface{}{1, 2, 3}) + out, err = ToCUE([]any{1, 2, 3}) require.NoError(t, err) assert.EqualValues(t, `[1, 2, 3]`, out) diff --git a/internal/tests/integration/datasources_consul_test.go b/internal/tests/integration/datasources_consul_test.go index 741f91df..dc8f4d80 100644 --- a/internal/tests/integration/datasources_consul_test.go +++ b/internal/tests/integration/datasources_consul_test.go @@ -171,11 +171,11 @@ func TestDatasources_Consul_WithVaultAuth(t *testing.T) { require.NoError(t, err) defer v.vc.Sys().Unmount("consul/") - _, err = v.vc.Logical().Write("consul/config/access", map[string]interface{}{ + _, err = v.vc.Logical().Write("consul/config/access", map[string]any{ "address": consulAddr, "token": consulRootToken, }) require.NoError(t, err) - _, err = v.vc.Logical().Write("consul/roles/readonly", map[string]interface{}{ + _, err = v.vc.Logical().Write("consul/roles/readonly", map[string]any{ "policies": "readonly", }) require.NoError(t, err) diff --git a/internal/tests/integration/datasources_vault_ec2_test.go b/internal/tests/integration/datasources_vault_ec2_test.go index 4b57020d..382d0d4e 100644 --- a/internal/tests/integration/datasources_vault_ec2_test.go +++ b/internal/tests/integration/datasources_vault_ec2_test.go @@ -13,14 +13,14 @@ func TestDatasources_VaultEc2(t *testing.T) { accountID, user := "1", "Test" tmpDir, v, srv, cert := setupDatasourcesVaultAWSTest(t, accountID, user) - v.vc.Logical().Write("secret/foo", map[string]interface{}{"value": "bar"}) + v.vc.Logical().Write("secret/foo", map[string]any{"value": "bar"}) defer v.vc.Logical().Delete("secret/foo") err := v.vc.Sys().EnableAuth("aws", "aws", "") require.NoError(t, err) defer v.vc.Sys().DisableAuth("aws") - _, err = v.vc.Logical().Write("auth/aws/config/client", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/aws/config/client", map[string]any{ "secret_key": "secret", "access_key": "access", "endpoint": srv.URL + "/ec2", "iam_endpoint": srv.URL + "/iam", @@ -29,12 +29,12 @@ func TestDatasources_VaultEc2(t *testing.T) { }) require.NoError(t, err) - _, err = v.vc.Logical().Write("auth/aws/config/certificate/testcert", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/aws/config/certificate/testcert", map[string]any{ "type": "pkcs7", "aws_public_cert": string(cert), }) require.NoError(t, err) - _, err = v.vc.Logical().Write("auth/aws/role/ami-00000000", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/aws/role/ami-00000000", map[string]any{ "auth_type": "ec2", "bound_ami_id": "ami-00000000", "policies": "readpol", }) diff --git a/internal/tests/integration/datasources_vault_iam_test.go b/internal/tests/integration/datasources_vault_iam_test.go index 0cee8d3d..df776636 100644 --- a/internal/tests/integration/datasources_vault_iam_test.go +++ b/internal/tests/integration/datasources_vault_iam_test.go @@ -15,7 +15,7 @@ func TestDatasources_VaultIAM(t *testing.T) { tmpDir, v, srv, _ := setupDatasourcesVaultAWSTest(t, accountID, user) - v.vc.Logical().Write("secret/foo", map[string]interface{}{"value": "bar"}) + v.vc.Logical().Write("secret/foo", map[string]any{"value": "bar"}) defer v.vc.Logical().Delete("secret/foo") err := v.vc.Sys().EnableAuth("aws", "aws", "") @@ -27,7 +27,7 @@ func TestDatasources_VaultIAM(t *testing.T) { accessKeyID := "secret" secretAccessKey := "access" - _, err = v.vc.Logical().Write("auth/aws/config/client", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/aws/config/client", map[string]any{ "access_key": accessKeyID, "secret_key": secretAccessKey, "endpoint": endpoint, @@ -37,7 +37,7 @@ func TestDatasources_VaultIAM(t *testing.T) { }) require.NoError(t, err) - _, err = v.vc.Logical().Write("auth/aws/role/foo", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/aws/role/foo", map[string]any{ "auth_type": "iam", "bound_iam_principal_arn": "arn:aws:iam::" + accountID + ":*", "policies": "readpol", diff --git a/internal/tests/integration/datasources_vault_test.go b/internal/tests/integration/datasources_vault_test.go index 74a2512b..a3993dc1 100644 --- a/internal/tests/integration/datasources_vault_test.go +++ b/internal/tests/integration/datasources_vault_test.go @@ -109,7 +109,7 @@ func startVault(t *testing.T) (*fs.Dir, *vaultClient) { func TestDatasources_Vault_TokenAuth(t *testing.T) { v := setupDatasourcesVaultTest(t) - v.vc.Logical().Write("secret/foo", map[string]interface{}{"value": "bar"}) + v.vc.Logical().Write("secret/foo", map[string]any{"value": "bar"}) defer v.vc.Logical().Delete("secret/foo") tok, err := v.tokenCreate("readpol", 5) require.NoError(t, err) @@ -150,7 +150,7 @@ func TestDatasources_Vault_TokenAuth(t *testing.T) { func TestDatasources_Vault_UserPassAuth(t *testing.T) { v := setupDatasourcesVaultTest(t) - v.vc.Logical().Write("secret/foo", map[string]interface{}{"value": "bar"}) + v.vc.Logical().Write("secret/foo", map[string]any{"value": "bar"}) defer v.vc.Logical().Delete("secret/foo") err := v.vc.Sys().EnableAuth("userpass", "userpass", "") require.NoError(t, err) @@ -158,11 +158,11 @@ func TestDatasources_Vault_UserPassAuth(t *testing.T) { require.NoError(t, err) defer v.vc.Sys().DisableAuth("userpass") defer v.vc.Sys().DisableAuth("userpass2") - _, err = v.vc.Logical().Write("auth/userpass/users/dave", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/userpass/users/dave", map[string]any{ "password": "foo", "ttl": "10s", "policies": "readpol", }) require.NoError(t, err) - _, err = v.vc.Logical().Write("auth/userpass2/users/dave", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/userpass2/users/dave", map[string]any{ "password": "bar", "ttl": "10s", "policies": "readpol", }) require.NoError(t, err) @@ -202,7 +202,7 @@ func TestDatasources_Vault_UserPassAuth(t *testing.T) { func TestDatasources_Vault_AppRoleAuth(t *testing.T) { v := setupDatasourcesVaultTest(t) - v.vc.Logical().Write("secret/foo", map[string]interface{}{"value": "bar"}) + v.vc.Logical().Write("secret/foo", map[string]any{"value": "bar"}) defer v.vc.Logical().Delete("secret/foo") err := v.vc.Sys().EnableAuth("approle", "approle", "") require.NoError(t, err) @@ -210,12 +210,12 @@ func TestDatasources_Vault_AppRoleAuth(t *testing.T) { require.NoError(t, err) defer v.vc.Sys().DisableAuth("approle") defer v.vc.Sys().DisableAuth("approle2") - _, err = v.vc.Logical().Write("auth/approle/role/testrole", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/approle/role/testrole", map[string]any{ "secret_id_ttl": "10s", "token_ttl": "20s", "secret_id_num_uses": "1", "policies": "readpol", }) require.NoError(t, err) - _, err = v.vc.Logical().Write("auth/approle2/role/testrole", map[string]interface{}{ + _, err = v.vc.Logical().Write("auth/approle2/role/testrole", map[string]any{ "secret_id_ttl": "10s", "token_ttl": "20s", "secret_id_num_uses": "1", "policies": "readpol", }) @@ -256,7 +256,7 @@ func TestDatasources_Vault_DynamicAuth(t *testing.T) { require.NoError(t, err) defer v.vc.Sys().Unmount("ssh") - _, err = v.vc.Logical().Write("ssh/roles/test", map[string]interface{}{ + _, err = v.vc.Logical().Write("ssh/roles/test", map[string]any{ "key_type": "otp", "default_user": "user", "cidr_list": "10.0.0.0/8", }) require.NoError(t, err) @@ -284,8 +284,8 @@ func TestDatasources_Vault_DynamicAuth(t *testing.T) { func TestDatasources_Vault_List(t *testing.T) { v := setupDatasourcesVaultTest(t) - v.vc.Logical().Write("secret/dir/foo", map[string]interface{}{"value": "one"}) - v.vc.Logical().Write("secret/dir/bar", map[string]interface{}{"value": "two"}) + v.vc.Logical().Write("secret/dir/foo", map[string]any{"value": "one"}) + v.vc.Logical().Write("secret/dir/bar", map[string]any{"value": "two"}) defer v.vc.Logical().Delete("secret/dir/foo") defer v.vc.Logical().Delete("secret/dir/bar") tok, err := v.tokenCreate("listpol", 15) @@ -322,15 +322,15 @@ func setupKV2Test(ctx context.Context, t *testing.T, policy string) (string, str }) require.NoError(t, err) - s, err := v.vc.KVv2("kv2").Put(ctx, "foo", map[string]interface{}{"first": "one"}, vaultapi.WithCheckAndSet(0)) + s, err := v.vc.KVv2("kv2").Put(ctx, "foo", map[string]any{"first": "one"}, vaultapi.WithCheckAndSet(0)) require.NoError(t, err) require.Equal(t, 1, s.VersionMetadata.Version) - s, err = v.vc.KVv2("kv2").Put(ctx, "foo", map[string]interface{}{"second": "two"}, vaultapi.WithCheckAndSet(1)) + s, err = v.vc.KVv2("kv2").Put(ctx, "foo", map[string]any{"second": "two"}, vaultapi.WithCheckAndSet(1)) require.NoError(t, err) require.Equal(t, 2, s.VersionMetadata.Version) - s, err = v.vc.KVv2("a/b/c").Put(ctx, "d/e/f", map[string]interface{}{"e": "f"}) + s, err = v.vc.KVv2("a/b/c").Put(ctx, "d/e/f", map[string]any{"e": "f"}) require.NoError(t, err) require.Equal(t, 1, s.VersionMetadata.Version) diff --git a/internal/tests/integration/inputdir_unix_test.go b/internal/tests/integration/inputdir_unix_test.go index 7080f552..9fae6994 100644 --- a/internal/tests/integration/inputdir_unix_test.go +++ b/internal/tests/integration/inputdir_unix_test.go @@ -35,7 +35,7 @@ func checkFileUlimit(t *testing.T, b uint64) { func TestInputDir_RespectsUlimit(t *testing.T) { numfiles := uint32(32) flist := map[string]string{} - for i := 0; i < int(numfiles); i++ { + for i := range int(numfiles) { k := fmt.Sprintf("file_%d", i) flist[k] = fmt.Sprintf("hello world %d\n", i) } @@ -67,7 +67,7 @@ func TestInputDir_RespectsUlimit(t *testing.T) { assert.NilError(t, err) assert.Equal(t, int(numfiles), len(files)) - for i := 0; i < int(numfiles); i++ { + for i := range int(numfiles) { f := testdir.Join("out", fmt.Sprintf("file_%d", i)) _, err := os.Stat(f) assert.NilError(t, err) diff --git a/internal/tests/integration/test_ec2_utils_test.go b/internal/tests/integration/test_ec2_utils_test.go index 29b92350..9792021d 100644 --- a/internal/tests/integration/test_ec2_utils_test.go +++ b/internal/tests/integration/test_ec2_utils_test.go @@ -129,7 +129,7 @@ func stsHandler(t *testing.T, accountID, user string) http.Handler { assert.Equal(t, "GetCallerIdentity", form.Get("Action")) w.Header().Set("Content-Type", "text/xml") - _, err := w.Write([]byte(fmt.Sprintf(` + _, err := w.Write(fmt.Appendf(nil, ` arn:aws:iam::%[1]s:user/%[2]s @@ -139,7 +139,7 @@ func stsHandler(t *testing.T, accountID, user string) http.Handler { 01234567-89ab-cdef-0123-456789abcdef - `, accountID, user))) + `, accountID, user)) if err != nil { t.Errorf("failed to write response: %s", err) w.WriteHeader(http.StatusInternalServerError) @@ -284,7 +284,7 @@ func iamGetUserHandler(t *testing.T, accountID string) http.Handler { assert.Equal(t, "GetUser", form.Get("Action")) w.Header().Set("Content-Type", "text/xml") - _, err := w.Write([]byte(fmt.Sprintf(` + _, err := w.Write(fmt.Appendf(nil, ` @@ -298,7 +298,7 @@ func iamGetUserHandler(t *testing.T, accountID string) http.Handler { 3d0e2445-64ea-4bfb-9244-30d810773f9e - `, form.Get("UserName"), accountID))) + `, form.Get("UserName"), accountID)) if err != nil { w.WriteHeader(http.StatusInternalServerError) } diff --git a/net/net.go b/net/net.go index d20a96dd..79b0dc4e 100644 --- a/net/net.go +++ b/net/net.go @@ -3,6 +3,7 @@ package net import ( "net" + "slices" ) // LookupIP - @@ -30,7 +31,7 @@ func LookupIPs(name string) ([]string, error) { for _, v := range srcIPs { if v.To4() != nil { s := v.String() - if !contains(ips, s) { + if !slices.Contains(ips, s) { ips = append(ips, s) } } @@ -38,15 +39,6 @@ func LookupIPs(name string) ([]string, error) { return ips, nil } -func contains(a []string, s string) bool { - for _, v := range a { - if v == s { - return true - } - } - return false -} - // LookupCNAME - func LookupCNAME(name string) (string, error) { return net.LookupCNAME(name) diff --git a/net/net_test.go b/net/net_test.go index 49f6db7d..a7d59baa 100644 --- a/net/net_test.go +++ b/net/net_test.go @@ -7,7 +7,7 @@ import ( "github.com/stretchr/testify/require" ) -func must(r interface{}, err error) interface{} { +func must(r any, err error) any { if err != nil { panic(err) } @@ -25,7 +25,7 @@ func TestLookupIPs(t *testing.T) { } func BenchmarkLookupIPs(b *testing.B) { - for i := 0; i < b.N; i++ { + for b.Loop() { must(LookupIPs("localhost")) } } diff --git a/plugins.go b/plugins.go index fd2882ab..d87f2a64 100644 --- a/plugins.go +++ b/plugins.go @@ -64,7 +64,7 @@ type PluginOpts struct { // PluginFunc creates a template function that runs an external process - either // a shell script or commandline executable. -func PluginFunc(ctx context.Context, cmd string, opts PluginOpts) func(...interface{}) (interface{}, error) { +func PluginFunc(ctx context.Context, cmd string, opts PluginOpts) func(...any) (any, error) { timeout := opts.Timeout if timeout == 0 { timeout = 5 * time.Second @@ -126,7 +126,7 @@ func findPowershell() string { return "pwsh" } -func (p *plugin) run(args ...interface{}) (interface{}, error) { +func (p *plugin) run(args ...any) (any, error) { a := conv.ToStrings(args...) a = append(p.args, a...) diff --git a/plugins_test.go b/plugins_test.go index e919e684..a3596cda 100644 --- a/plugins_test.go +++ b/plugins_test.go @@ -58,8 +58,7 @@ func TestBuildCommand(t *testing.T) { } func TestRun(t *testing.T) { - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() + ctx := t.Context() stderr := &bytes.Buffer{} p := &plugin{ diff --git a/random/random.go b/random/random.go index ad0bb48a..4feb2884 100644 --- a/random/random.go +++ b/random/random.go @@ -74,7 +74,7 @@ func matchChars(match string) ([]rune, error) { } // Item - -func Item(items []interface{}) (interface{}, error) { +func Item(items []any) (any, error) { if len(items) == 0 { return nil, fmt.Errorf("expected a non-empty array or slice") } diff --git a/random/random_test.go b/random/random_test.go index 1e76298e..0722465e 100644 --- a/random/random_test.go +++ b/random/random_test.go @@ -82,13 +82,13 @@ func TestItem(t *testing.T) { _, err := Item(nil) require.Error(t, err) - i, err := Item([]interface{}{"foo"}) + i, err := Item([]any{"foo"}) require.NoError(t, err) assert.Equal(t, "foo", i) - in := []interface{}{"foo", "bar"} + in := []any{"foo", "bar"} got := "" - for j := 0; j < 10; j++ { + for range 10 { i, err = Item(in) require.NoError(t, err) got += i.(string) diff --git a/render.go b/render.go index c7a10dba..6c0fb4f4 100644 --- a/render.go +++ b/render.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "io/fs" + "maps" "net/http" "path" "slices" @@ -185,16 +186,16 @@ func (r *renderer) RenderTemplates(ctx context.Context, templates []Template) er return r.renderTemplatesWithData(ctx, templates, tmplctx) } -func (r *renderer) renderTemplatesWithData(ctx context.Context, templates []Template, tmplctx interface{}) error { +func (r *renderer) renderTemplatesWithData(ctx context.Context, templates []Template, tmplctx any) error { // update funcs with the current context // only done here to ensure the context is properly set in func namespaces f := CreateFuncs(ctx) // add datasource funcs here because they need to share the source reader - addToMap(f, funcs.CreateDataSourceFuncs(ctx, r.sr)) + maps.Copy(f, funcs.CreateDataSourceFuncs(ctx, r.sr)) // add user-defined funcs last so they override the built-in funcs - addToMap(f, r.funcs) + maps.Copy(f, r.funcs) // track some metrics for debug output start := time.Now() @@ -208,7 +209,7 @@ func (r *renderer) renderTemplatesWithData(ctx context.Context, templates []Temp return nil } -func (r *renderer) renderTemplate(ctx context.Context, template Template, f template.FuncMap, tmplctx interface{}) error { +func (r *renderer) renderTemplate(ctx context.Context, template Template, f template.FuncMap, tmplctx any) error { if template.Writer != nil { if wr, ok := template.Writer.(io.Closer); ok { defer wr.Close() @@ -239,7 +240,7 @@ func (r *renderer) Render(ctx context.Context, name, text string, wr io.Writer) } // parseTemplate - parses text as a Go template with the given name and options -func (r *renderer) parseTemplate(ctx context.Context, name, text string, funcs template.FuncMap, tmplctx interface{}) (tmpl *template.Template, err error) { +func (r *renderer) parseTemplate(ctx context.Context, name, text string, funcs template.FuncMap, tmplctx any) (tmpl *template.Template, err error) { tmpl = template.New(name) missingKey := r.missingKey diff --git a/strings/strings.go b/strings/strings.go index 007714e2..cf80f39c 100644 --- a/strings/strings.go +++ b/strings/strings.go @@ -33,7 +33,7 @@ func Indent(width int, indent, s string) (string, error) { res := make([]byte, 0, len(s)+len(indent)*lines) bol := true - for i := 0; i < len(s); i++ { + for i := range len(s) { c := s[i] if bol && c != '\n' { res = append(res, indent...) diff --git a/strings/strings_test.go b/strings/strings_test.go index 0fec6925..9c3afa8d 100644 --- a/strings/strings_test.go +++ b/strings/strings_test.go @@ -42,7 +42,7 @@ func BenchmarkIndent(b *testing.B) { longString := strings.Repeat("a fairly long string \n", 20) outs := make([]string, b.N*8) b.ResetTimer() - for i := 0; i < b.N; i++ { + for i := range b.N { outs[0+i*8], _ = Indent(20, " ", longString) outs[1+i*8], _ = Indent(-1, " ", actual) outs[2+i*8], _ = Indent(1, " ", actual) diff --git a/template.go b/template.go index b897ee99..0e2794ca 100644 --- a/template.go +++ b/template.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "io/fs" + "maps" "os" "path/filepath" "text/template" @@ -22,7 +23,7 @@ import ( // ignorefile name, like .gitignore const gomplateignore = ".gomplateignore" -func addTmplFuncs(f template.FuncMap, root *template.Template, tctx interface{}, path string) { +func addTmplFuncs(f template.FuncMap, root *template.Template, tctx any, path string) { t := tmpl.New(root, tctx, path) tns := func() *tmpl.Template { return t } f["tmpl"] = tns @@ -37,9 +38,8 @@ func copyFuncMap(funcMap template.FuncMap) template.FuncMap { } newFuncMap := make(template.FuncMap, len(funcMap)) - for k, v := range funcMap { - newFuncMap[k] = v - } + maps.Copy(newFuncMap, funcMap) + return newFuncMap } diff --git a/test/test.go b/test/test.go index 6a6b2035..31fccfba 100644 --- a/test/test.go +++ b/test/test.go @@ -27,7 +27,7 @@ func Fail(message string) error { } // Required - -func Required(message string, value interface{}) (interface{}, error) { +func Required(message string, value any) (any, error) { if message == "" { message = "can not render template: a required value was not set" } diff --git a/tmpl/tmpl.go b/tmpl/tmpl.go index c4f6aefd..d1e5c75b 100644 --- a/tmpl/tmpl.go +++ b/tmpl/tmpl.go @@ -11,12 +11,12 @@ import ( // Template - type Template struct { root *template.Template - defaultCtx interface{} + defaultCtx any path string } // New - -func New(root *template.Template, tctx interface{}, path string) *Template { +func New(root *template.Template, tctx any, path string) *Template { return &Template{root, tctx, path} } @@ -43,7 +43,7 @@ func (t *Template) PathDir() (string, error) { // {{ tmpl.Inline "name" "inline template" }} - named template with default context // {{ tmpl.Inline "inline template" $foo }} - unnamed (single-use) template with given context // {{ tmpl.Inline "name" "inline template" $foo }} - named template with given context -func (t *Template) Inline(args ...interface{}) (string, error) { +func (t *Template) Inline(args ...any) (string, error) { name, in, ctx, err := t.parseArgs(args...) if err != nil { return "", err @@ -51,7 +51,7 @@ func (t *Template) Inline(args ...interface{}) (string, error) { return t.inline(name, in, ctx) } -func (t *Template) inline(name, in string, ctx interface{}) (string, error) { +func (t *Template) inline(name, in string, ctx any) (string, error) { tmpl, err := t.root.New(name).Parse(in) if err != nil { return "", err @@ -60,7 +60,7 @@ func (t *Template) inline(name, in string, ctx interface{}) (string, error) { } // Exec - execute (render) a template - this is the built-in `template` action, except with output... -func (t *Template) Exec(name string, tmplcontext ...interface{}) (string, error) { +func (t *Template) Exec(name string, tmplcontext ...any) (string, error) { ctx := t.defaultCtx if len(tmplcontext) == 1 { ctx = tmplcontext[0] @@ -72,7 +72,7 @@ func (t *Template) Exec(name string, tmplcontext ...interface{}) (string, error) return render(tmpl, ctx) } -func render(tmpl *template.Template, ctx interface{}) (string, error) { +func render(tmpl *template.Template, ctx any) (string, error) { out := &bytes.Buffer{} err := tmpl.Execute(out, ctx) if err != nil { @@ -81,7 +81,7 @@ func render(tmpl *template.Template, ctx interface{}) (string, error) { return out.String(), nil } -func (t *Template) parseArgs(args ...interface{}) (name, in string, ctx interface{}, err error) { +func (t *Template) parseArgs(args ...any) (name, in string, ctx any, err error) { name = "" ctx = t.defaultCtx @@ -97,7 +97,7 @@ func (t *Template) parseArgs(args ...interface{}) (name, in string, ctx interfac case 1: in = first case 2: - // this can either be (name string, in string) or (in string, ctx interface{}) + // this can either be (name string, in string) or (in string, ctx any) switch second := args[1].(type) { case string: name = first diff --git a/version/gen/vgen.go b/version/gen/vgen.go index 4528b2d7..8fd2a00d 100644 --- a/version/gen/vgen.go +++ b/version/gen/vgen.go @@ -85,7 +85,7 @@ func latestTag() (*semver.Version, error) { // find the latest tag var latest *semver.Version - for _, tag := range strings.Split(tags, "\n") { + for tag := range strings.SplitSeq(tags, "\n") { ver, err := semver.NewVersion(tag) if err != nil { return nil, fmt.Errorf("parsing tag %q failed: %w", tag, err) -- cgit v1.2.3