From 3bc72e49b8ee5cb9e66d652e7f39482f3e59afd6 Mon Sep 17 00:00:00 2001 From: Denis Issoupov Date: Wed, 24 Apr 2024 15:53:36 +0100 Subject: [PATCH] Added RangeOrderedMap --- .VERSION | 2 +- .github/workflows/release.yml | 2 +- .gitignore | 3 ++- go.mod | 9 +++++---- go.sum | 18 ++++++++++-------- slices/slices.go | 5 +++-- values/mapany.go | 27 +++++++++++++++++++++++++++ values/value_test.go | 11 +++++++++++ 8 files changed, 60 insertions(+), 17 deletions(-) diff --git a/.VERSION b/.VERSION index 866c31a..4ea1309 100644 --- a/.VERSION +++ b/.VERSION @@ -1 +1 @@ -v0.4 \ No newline at end of file +v0.5 \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b9f02c2..402349f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -34,7 +34,7 @@ jobs: fi - name: Create Tag - uses: actions/github-script@v6 + uses: actions/github-script@v7 with: script: | const {DIST_VERSION} = process.env diff --git a/.gitignore b/.gitignore index 30ffb4b..7396fa8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ bin/ debug debug.test -.vscode/launch.json \ No newline at end of file +.vscode/launch.json +.aider* diff --git a/go.mod b/go.mod index f16a1c6..82c3f3b 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,12 @@ go 1.21 require ( github.com/alecthomas/kong v0.9.0 github.com/deckarep/golang-set v1.8.0 - github.com/effective-security/xlog v0.8.79 + github.com/effective-security/xlog v0.8.81 github.com/oleiade/reflections v1.0.1 github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.9.0 go.uber.org/config v1.4.0 + golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f gopkg.in/yaml.v3 v3.0.1 ) @@ -22,10 +23,10 @@ require ( go.uber.org/multierr v1.4.0 // indirect go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee // indirect golang.org/x/lint v0.0.0-20190930215403-16217165b5de // indirect - golang.org/x/mod v0.9.0 // indirect - golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/sync v0.7.0 // indirect golang.org/x/text v0.3.7 // indirect - golang.org/x/tools v0.1.12 // indirect + golang.org/x/tools v0.20.0 // indirect gopkg.in/yaml.v2 v2.2.5 // indirect honnef.co/go/tools v0.0.1-2019.2.3 // indirect ) diff --git a/go.sum b/go.sum index 801092a..be1ee0f 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4= github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo= -github.com/effective-security/xlog v0.8.79 h1:bdiG+967kzF1KkQ3GmNLZqp//lbVroz0KGvhVw3NJJA= -github.com/effective-security/xlog v0.8.79/go.mod h1:8ymyxSvtDtqzwE6VUhgsPRMT6/hBDymgyeoNtHmRz9Y= +github.com/effective-security/xlog v0.8.81 h1:2plZrshDubHerwi8sRlQ1Au04R6z9nXlB3DDnF2+Ahg= +github.com/effective-security/xlog v0.8.81/go.mod h1:8ymyxSvtDtqzwE6VUhgsPRMT6/hBDymgyeoNtHmRz9Y= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= @@ -48,19 +48,21 @@ go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEa go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY= +golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI= golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= -golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= @@ -71,8 +73,8 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191104232314-dc038396d1f0/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= +golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/slices/slices.go b/slices/slices.go index 7a30b80..57f714a 100644 --- a/slices/slices.go +++ b/slices/slices.go @@ -255,11 +255,12 @@ func Contains[T comparable](arr []T, val T) bool { // - {key} is required; // - the first '=' is the separator (also required); // - {value} is optional. +var reStringArrayToMap = regexp.MustCompile(`^([^=]+)=(.*)$`) + func StringArrayToMap(arr []string) (map[string]string, error) { m := make(map[string]string) for _, v := range arr { - re := regexp.MustCompile(`^([^=]+)=(.*)$`) - matches := re.FindStringSubmatch(v) + matches := reStringArrayToMap.FindStringSubmatch(v) if len(matches) != 3 { return nil, errors.New("invalid format for string array") } diff --git a/values/mapany.go b/values/mapany.go index 7be9ad4..e129b35 100644 --- a/values/mapany.go +++ b/values/mapany.go @@ -3,10 +3,12 @@ package values import ( "bytes" "encoding/json" + "sort" "time" "github.com/effective-security/xlog" "github.com/pkg/errors" + "golang.org/x/exp/constraints" "gopkg.in/yaml.v3" ) @@ -141,3 +143,28 @@ func (c MapAny) GetOrSet(key string, getter func(key string) any) any { c[key] = v return v } + +// OrderedMapKeys returns ordered keys +func OrderedMapKeys[K constraints.Ordered, V any](m map[K]V) []K { + r := make([]K, 0, len(m)) + for k := range m { + r = append(r, k) + } + sort.Slice(r, func(i, j int) bool { + return r[i] < r[j] + }) + return r +} + +// RangeOrderedMap range over ordered map +func RangeOrderedMap[K constraints.Ordered, V any](c map[K]V, f func(k K, v V) bool) { + if c == nil { + return + } + + for _, k := range OrderedMapKeys(c) { + if !f(k, c[k]) { + break + } + } +} diff --git a/values/value_test.go b/values/value_test.go index bbbaad4..5ad2fc8 100644 --- a/values/value_test.go +++ b/values/value_test.go @@ -411,3 +411,14 @@ func TestSelect(t *testing.T) { assert.Equal(t, 1, Select(false, 0, 1)) assert.Equal(t, uint64(0), Select(true, 0, uint64(1))) } + +func TestRangeOrderedMap(t *testing.T) { + m1 := map[string]string{"ya": "1", "b": "2", "c": "3"} + + var keys []string + RangeOrderedMap(m1, func(k, v string) bool { + keys = append(keys, k) + return true + }) + assert.Equal(t, []string{"b", "c", "ya"}, keys) +}