Skip to content

Commit

Permalink
[utils] add more helper funcitons
Browse files Browse the repository at this point in the history
  • Loading branch information
ehsannm committed Dec 23, 2023
1 parent b405fd0 commit de28499
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 0 deletions.
62 changes: 62 additions & 0 deletions kit/utils/array.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ func Paginate[T any](arr []T, pageSize int, fn func(start, end int) error) error
return nil
}

// MapToArray converts a map's values to a slice.
func MapToArray[K comparable, V any](s map[K]V) []V {
arr := make([]V, 0, len(s))
for _, v := range s {
Expand All @@ -143,3 +144,64 @@ func MapToArray[K comparable, V any](s map[K]V) []V {

return arr
}

// ArrayToMap converts a slice to a map with the index as the key.
func ArrayToMap[V any](s []V) map[int]V {
m := make(map[int]V, len(s))
for idx, v := range s {
m[idx] = v
}

return m
}

func Contains[T comparable](s []T, v T) bool {
for _, vv := range s {
if vv == v {
return true
}
}

return false
}

func ContainsAny[T comparable](s []T, v []T) bool {
for _, vv := range v {
if Contains(s, vv) {
return true
}
}

return false
}

func ContainsAll[T comparable](s []T, v []T) bool {
for _, vv := range v {
if !Contains(s, vv) {
return false
}
}

return true
}

// First returns the first value found in the map for the given keys.
func First[K, V comparable](in map[K]V, keys ...K) (V, bool) {
var zero V
for _, k := range keys {
if v, ok := in[k]; ok {
return v, true
}
}

return zero, false
}

func FirstOr[K, V comparable](def V, in map[K]V, keys ...K) V {
v, ok := First(in, keys...)
if ok {
return v
}

return def
}
52 changes: 52 additions & 0 deletions kit/utils/visitor.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package utils

// VisitAll runs all visitors and returns the final state
func VisitAll[VisitorState any](
initial VisitorState,
visitors ...func(ctx *VisitorState),
) VisitorState {
state := initial
for _, visitor := range visitors {
visitor(&state)
}

return state
}

// VisitCond runs all visitors if the condition is true and returns the final state
// If the condition is false, the visitor will stop and DO NOT run the rest of the visitors.
// cond function is called before each visitor.
//
// NOTE: `cond` is called before each visitor, hence, it will be run on initial state too.
func VisitCond[VisitorState any](
initial VisitorState,
cond func(ctx *VisitorState) bool,
visitors ...func(ctx *VisitorState),
) VisitorState {
state := initial
for _, visitor := range visitors {
if cond(&state) {
visitor(&state)
}
}

return state
}

// VisitStopOnErr runs all visitors and returns the final state
// If any of the visitors returns an error, the visitor will stop and DO NOT run the rest of the visitors.
// It returns the latest state and the error.
func VisitStopOnErr[VisitorState any](
initial VisitorState,
visitors ...func(ctx *VisitorState) error,
) (VisitorState, error) {
state := initial
for _, visitor := range visitors {
err := visitor(&state)
if err != nil {
return state, err
}
}

return state, nil
}

0 comments on commit de28499

Please sign in to comment.