go.temporal.io/server@v1.23.0/common/util/util.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 // util contains small standalone utility functions. This should have no 26 // dependencies on other server packages. 27 package util 28 29 import ( 30 "sort" 31 "time" 32 33 "golang.org/x/exp/constraints" 34 "golang.org/x/exp/maps" 35 ) 36 37 // MinTime returns the earlier of two given time.Time 38 func MinTime(a, b time.Time) time.Time { 39 if a.Before(b) { 40 return a 41 } 42 return b 43 } 44 45 // MaxTime returns the later of two given time.Time 46 func MaxTime(a, b time.Time) time.Time { 47 if a.After(b) { 48 return a 49 } 50 return b 51 } 52 53 // SortSlice sorts the given slice of an ordered type. 54 // Sort is not guaranteed to be stable. 55 func SortSlice[S ~[]E, E constraints.Ordered](slice S) { 56 sort.Slice(slice, func(i, j int) bool { 57 return slice[i] < slice[j] 58 }) 59 } 60 61 // SliceHead returns the first n elements of s. n may be greater than len(s). 62 func SliceHead[S ~[]E, E any](s S, n int) S { 63 if n < len(s) { 64 return s[:n] 65 } 66 return s 67 } 68 69 // SliceTail returns the last n elements of s. n may be greater than len(s). 70 func SliceTail[S ~[]E, E any](s S, n int) S { 71 if extra := len(s) - n; extra > 0 { 72 return s[extra:] 73 } 74 return s 75 } 76 77 // CloneMapNonNil is like maps.Clone except it can't return nil, it will return an empty map instead. 78 func CloneMapNonNil[M ~map[K]V, K comparable, V any](m M) M { 79 m = maps.Clone(m) 80 if m == nil { 81 m = make(M) 82 } 83 return m 84 } 85 86 // InverseMap creates the inverse map, ie., for a key-value map, it builds the value-key map. 87 func InverseMap[M ~map[K]V, K, V comparable](m M) map[V]K { 88 if m == nil { 89 return nil 90 } 91 invm := make(map[V]K, len(m)) 92 for k, v := range m { 93 invm[v] = k 94 } 95 return invm 96 } 97 98 // MapConcurrent concurrently maps a function over input and fails fast on error. 99 func MapConcurrent[IN any, OUT any](input []IN, mapper func(IN) (OUT, error)) ([]OUT, error) { 100 errorsCh := make(chan error, len(input)) 101 results := make([]OUT, len(input)) 102 103 for i, in := range input { 104 i := i 105 in := in 106 go func() { 107 var err error 108 results[i], err = mapper(in) 109 errorsCh <- err 110 }() 111 } 112 for range input { 113 if err := <-errorsCh; err != nil { 114 return nil, err 115 } 116 } 117 return results, nil 118 } 119 120 // MapSlice given slice xs []T and f(T) S produces slice []S by applying f to every element of xs 121 func MapSlice[T, S any](xs []T, f func(T) S) []S { 122 if xs == nil { 123 return nil 124 } 125 result := make([]S, len(xs)) 126 for i, s := range xs { 127 result[i] = f(s) 128 } 129 return result 130 } 131 132 // FilterSlice iterates over elements of a slice, returning a new slice of all elements predicate returns true for. 133 func FilterSlice[T any](in []T, predicate func(T) bool) []T { 134 var out []T 135 for _, elem := range in { 136 if predicate(elem) { 137 out = append(out, elem) 138 } 139 } 140 return out 141 } 142 143 // FoldSlice folds left a slice using given reducer function and initial value. 144 func FoldSlice[T any, A any](in []T, initializer A, reducer func(A, T) A) A { 145 acc := initializer 146 for _, val := range in { 147 acc = reducer(acc, val) 148 } 149 return acc 150 } 151 152 // RepeatSlice given slice and a number (n) produces a new slice containing original slice n times 153 // if n is non-positive will produce nil 154 func RepeatSlice[T any](xs []T, n int) []T { 155 if xs == nil || n <= 0 { 156 return nil 157 } 158 ys := make([]T, n*len(xs)) 159 for i := 0; i < n; i++ { 160 copy(ys[i*len(xs):], xs) 161 } 162 return ys 163 } 164 165 // Coalesce returns the first non-zero value of its arguments, or the zero value for the type 166 // if all are zero. 167 func Coalesce[T comparable](vals ...T) T { 168 var zero T 169 for _, v := range vals { 170 if v != zero { 171 return v 172 } 173 } 174 return zero 175 }