-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from KyberNetwork/phu/init
add some utils
- Loading branch information
Showing
13 changed files
with
825 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
### Why | ||
|
||
Reusable util code | ||
|
||
### What | ||
|
||
- ctx.go: Context that ignores being cancelled | ||
- map.go: Collects values from a slice | ||
- num.go: Conversions, Min, Max, Abs | ||
- slice.go: Checks for existence, maps with fn, gets unique elements, filters |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package kutils | ||
|
||
import ( | ||
"context" | ||
"time" | ||
) | ||
|
||
type ctxWithoutCancel struct { | ||
ctx context.Context | ||
} | ||
|
||
func (c ctxWithoutCancel) Deadline() (time.Time, bool) { return time.Time{}, false } | ||
func (c ctxWithoutCancel) Done() <-chan struct{} { return nil } | ||
func (c ctxWithoutCancel) Err() error { return nil } | ||
func (c ctxWithoutCancel) Value(key interface{}) interface{} { return c.ctx.Value(key) } | ||
|
||
func CtxWithoutCancel(ctx context.Context) context.Context { | ||
if ctx == nil { | ||
return context.Background() | ||
} | ||
return &ctxWithoutCancel{ctx: ctx} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package kutils | ||
|
||
import ( | ||
"context" | ||
"testing" | ||
"time" | ||
|
||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestCtxWithoutCancel(t *testing.T) { | ||
cancelledCtx, cancel := context.WithTimeout( | ||
context.WithValue(CtxWithoutCancel(nil), "key", "value"), time.Second) | ||
detachedCtx := CtxWithoutCancel(cancelledCtx) | ||
|
||
t.Run("Deadline()", func(t *testing.T) { | ||
_, ok := cancelledCtx.Deadline() | ||
assert.True(t, ok, "cancelledCtx should have Deadline") | ||
_, ok = detachedCtx.Deadline() | ||
assert.False(t, ok, "detachedCtx should not have Deadline") | ||
cancel() | ||
}) | ||
|
||
t.Run("Err()", func(t *testing.T) { | ||
assert.NotNil(t, cancelledCtx.Err()) | ||
assert.Nil(t, detachedCtx.Err()) | ||
}) | ||
|
||
t.Run("Done()", func(t *testing.T) { | ||
select { | ||
case <-cancelledCtx.Done(): | ||
default: | ||
assert.Fail(t, "cancelledCtx.Done() should be closed") | ||
} | ||
select { | ||
case <-detachedCtx.Done(): | ||
assert.Fail(t, "detachedCtx.Done() should not be closed") | ||
default: | ||
} | ||
}) | ||
|
||
t.Run("Value()", func(t *testing.T) { | ||
assert.Equal(t, "value", cancelledCtx.Value("key")) | ||
assert.Equal(t, "value", detachedCtx.Value("key")) | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
module github.com/KyberNetwork/kutils | ||
|
||
go 1.20 | ||
|
||
require ( | ||
github.com/stretchr/testify v1.8.4 | ||
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= | ||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= | ||
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31 h1:9k5exFQKQglLo+RoP+4zMjOFE14P6+vyR0baDAi0Rcs= | ||
golang.org/x/exp v0.0.0-20231005195138-3e424a577f31/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package kutils | ||
|
||
func Map[T any, K comparable, V any](lst []T, keyFn func(T) K, valFn func(T) V) map[K]V { | ||
res := make(map[K]V, len(lst)) | ||
for _, elem := range lst { | ||
res[keyFn(elem)] = valFn(elem) | ||
} | ||
return res | ||
} | ||
|
||
func MapMulti[T any, K comparable, V any](lst []T, keyFn func(T) K, valFn func(T) V) map[K][]V { | ||
res := make(map[K][]V) | ||
for _, elem := range lst { | ||
res[keyFn(elem)] = append(res[keyFn(elem)], valFn(elem)) | ||
} | ||
return res | ||
} | ||
|
||
func MapKey[T any, K comparable](lst []T, keyFn func(T) K) map[K]T { | ||
res := make(map[K]T, len(lst)) | ||
for _, elem := range lst { | ||
res[keyFn(elem)] = elem | ||
} | ||
return res | ||
} | ||
|
||
func MapKeyMulti[T any, K comparable](lst []T, keyFn func(T) K) map[K][]T { | ||
res := make(map[K][]T) | ||
for _, elem := range lst { | ||
res[keyFn(elem)] = append(res[keyFn(elem)], elem) | ||
} | ||
return res | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package kutils | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
) | ||
|
||
func TestMap(t *testing.T) { | ||
testMap[int, int, string](t, "int to map[abs]string", | ||
[]int{-1, 2, -3, 2}, Abs[int], Itoa[int], | ||
map[int]string{1: "-1", 2: "2", 3: "-3"}) | ||
testMap[uint, string, uint](t, "uint to map[string]cappedIncr", | ||
[]uint{1, 2, 9, 3}, Utoa[uint], func(u uint) uint { return Min(9, u+1) }, | ||
map[string]uint{"1": 2, "2": 3, "9": 9, "3": 4}) | ||
} | ||
|
||
func testMap[T any, K comparable, V any](t *testing.T, name string, lst []T, keyFn func(T) K, valFn func(T) V, | ||
want map[K]V) { | ||
t.Run(name, func(t *testing.T) { | ||
if got := Map(lst, keyFn, valFn); !reflect.DeepEqual(got, want) { | ||
t.Errorf("Map() = %v, want %v", got, want) | ||
} | ||
}) | ||
} | ||
|
||
func TestMapMulti(t *testing.T) { | ||
testMapMulti[int, int, string](t, "int to map[abs][]string", | ||
[]int{-1, 2, -3, -2}, Abs[int], Itoa[int], | ||
map[int][]string{1: {"-1"}, 2: {"2", "-2"}, 3: {"-3"}}) | ||
testMapMulti[uint, string, uint](t, "uint to map[string][]cappedIncr", | ||
[]uint{1, 2, 9, 3}, Utoa[uint], func(u uint) uint { return Min(9, u+1) }, | ||
map[string][]uint{"1": {2}, "2": {3}, "9": {9}, "3": {4}}) | ||
} | ||
|
||
func testMapMulti[T any, K comparable, V any](t *testing.T, name string, lst []T, keyFn func(T) K, valFn func(T) V, | ||
want map[K][]V) { | ||
t.Run(name, func(t *testing.T) { | ||
if got := MapMulti(lst, keyFn, valFn); !reflect.DeepEqual(got, want) { | ||
t.Errorf("MapMulti() = %v, want %v", got, want) | ||
} | ||
}) | ||
} | ||
|
||
func TestMapKey(t *testing.T) { | ||
testMapKey[int, int](t, "int to map[abs]", | ||
[]int{-1, 2, -3, 2}, Abs[int], | ||
map[int]int{1: -1, 2: 2, 3: -3}) | ||
testMapKey[uint, string](t, "uint to map[string]", | ||
[]uint{1, 2, 9, 3}, Utoa[uint], | ||
map[string]uint{"1": 1, "2": 2, "9": 9, "3": 3}) | ||
} | ||
|
||
func testMapKey[T any, K comparable](t *testing.T, name string, lst []T, keyFn func(T) K, want map[K]T) { | ||
t.Run(name, func(t *testing.T) { | ||
if got := MapKey(lst, keyFn); !reflect.DeepEqual(got, want) { | ||
t.Errorf("MapKey() = %v, want %v", got, want) | ||
} | ||
}) | ||
} | ||
|
||
func TestMapKeyMulti(t *testing.T) { | ||
testMapKeyMulti[int, int](t, "int to map[abs]", | ||
[]int{-1, 2, -3, -2}, Abs[int], | ||
map[int][]int{1: {-1}, 2: {2, -2}, 3: {-3}}) | ||
testMapKeyMulti[uint, string](t, "uint to map[string]", | ||
[]uint{1, 2, 9, 3}, Utoa[uint], | ||
map[string][]uint{"1": {1}, "2": {2}, "9": {9}, "3": {3}}) | ||
} | ||
|
||
func testMapKeyMulti[T any, K comparable](t *testing.T, name string, lst []T, keyFn func(T) K, want map[K][]T) { | ||
t.Run(name, func(t *testing.T) { | ||
if got := MapKeyMulti(lst, keyFn); !reflect.DeepEqual(got, want) { | ||
t.Errorf("MapKeyMulti() = %v, want %v", got, want) | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
package kutils | ||
|
||
import ( | ||
"fmt" | ||
"strconv" | ||
|
||
"golang.org/x/exp/constraints" | ||
) | ||
|
||
func Itoa[T constraints.Signed](i T) string { | ||
return strconv.FormatInt(int64(i), 10) | ||
} | ||
|
||
func Utoa[T constraints.Unsigned](u T) string { | ||
return strconv.FormatUint(uint64(u), 10) | ||
} | ||
|
||
func Atoi[T constraints.Signed](a string) (i T, err error) { | ||
bitSize := 0 | ||
switch any(i).(type) { | ||
case int: | ||
bitSize = strconv.IntSize | ||
case int8: | ||
bitSize = 8 | ||
case int16: | ||
bitSize = 16 | ||
case int32: | ||
bitSize = 32 | ||
case int64: | ||
bitSize = 64 | ||
} | ||
if i, err := strconv.ParseInt(a, 10, bitSize); err != nil { | ||
return 0, err | ||
} else if bitSize == 0 && int64(T(i)) != i { | ||
return 0, &strconv.NumError{Func: "ParseInt", Num: a, Err: strconv.ErrRange} | ||
} else { | ||
return T(i), nil | ||
} | ||
} | ||
|
||
func Atou[T constraints.Unsigned](a string) (u T, err error) { | ||
bitSize := 0 | ||
switch any(u).(type) { | ||
case uint, uintptr: | ||
bitSize = strconv.IntSize | ||
case uint8: | ||
bitSize = 8 | ||
case uint16: | ||
bitSize = 16 | ||
case uint32: | ||
bitSize = 32 | ||
case uint64: | ||
bitSize = 64 | ||
} | ||
if u, err := strconv.ParseUint(a, 10, bitSize); err != nil { | ||
return 0, err | ||
} else if bitSize == 0 && uint64(T(u)) != u { | ||
return 0, &strconv.NumError{Func: "ParseUint", Num: a, Err: strconv.ErrRange} | ||
} else { | ||
return T(u), nil | ||
} | ||
} | ||
|
||
func Min[T constraints.Ordered](a, b T) T { | ||
if b < a { | ||
return b | ||
} | ||
return a | ||
} | ||
|
||
func Max[T constraints.Ordered](a, b T) T { | ||
if b > a { | ||
return b | ||
} | ||
return a | ||
} | ||
|
||
func Abs[T constraints.Signed | constraints.Float](a T) T { | ||
if a < 0 { | ||
if a-1 > 0 { | ||
panic(fmt.Sprintf("Abs result of %v will overflow", a)) | ||
} | ||
return -a | ||
} | ||
return a | ||
} |
Oops, something went wrong.