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  }