1
0
mirror of https://github.com/jesseduffield/lazygit.git synced 2025-07-31 14:24:25 +03:00

use boxlayout from lazycore

This commit is contained in:
Jesse Duffield
2022-10-09 08:31:14 -07:00
parent 7b4b42abd6
commit dba0edb998
40 changed files with 4356 additions and 803 deletions

View File

@ -34,3 +34,5 @@ go.work
cover.out
cover.html
.vscode
.idea/

View File

@ -1,5 +1,281 @@
# Changelog
@samber: I sometimes forget to update this file. Ping me on [Twitter](https://twitter.com/samuelberthe) or open an issue in case of error. We need to keep a clear changelog for easier lib upgrade.
## 1.31.0 (2022-10-06)
Adding:
- lo.SliceToChannel
- lo.Generator
- lo.Batch
- lo.BatchWithTimeout
## 1.30.1 (2022-10-06)
Fix:
- lo.Try1: remove generic type
- lo.Validate: format error properly
## 1.30.0 (2022-10-04)
Adding:
- lo.TernaryF
- lo.Validate
## 1.29.0 (2022-10-02)
Adding:
- lo.ErrorAs
- lo.TryOr
- lo.TryOrX
## 1.28.0 (2022-09-05)
Adding:
- lo.ChannelDispatcher with 6 dispatching strategies:
- lo.DispatchingStrategyRoundRobin
- lo.DispatchingStrategyRandom
- lo.DispatchingStrategyWeightedRandom
- lo.DispatchingStrategyFirst
- lo.DispatchingStrategyLeast
- lo.DispatchingStrategyMost
## 1.27.1 (2022-08-15)
Bugfix:
- Removed comparable constraint for lo.FindKeyBy
## 1.27.0 (2022-07-29)
Breaking:
- Change of MapToSlice prototype: `MapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(V, K) R) []R` -> `MapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(K, V) R) []R`
Added:
- lo.ChunkString
- lo.SliceToMap (alias to lo.Associate)
## 1.26.0 (2022-07-24)
Adding:
- lo.Associate
- lo.ReduceRight
- lo.FromPtrOr
- lo.MapToSlice
- lo.IsSorted
- lo.IsSortedByKey
## 1.25.0 (2022-07-04)
Adding:
- lo.FindUniques
- lo.FindUniquesBy
- lo.FindDuplicates
- lo.FindDuplicatesBy
- lo.IsNotEmpty
## 1.24.0 (2022-07-04)
Adding:
- lo.Without
- lo.WithoutEmpty
## 1.23.0 (2022-07-04)
Adding:
- lo.FindKey
- lo.FindKeyBy
## 1.22.0 (2022-07-04)
Adding:
- lo.Slice
- lo.FromPtr
- lo.IsEmpty
- lo.Compact
- lo.ToPairs: alias to lo.Entries
- lo.FromPairs: alias to lo.FromEntries
- lo.Partial
Change:
- lo.Must + lo.MustX: add context to panic message
Fix:
- lo.Nth: out of bound exception (#137)
## 1.21.0 (2022-05-10)
Adding:
- lo.ToAnySlice
- lo.FromAnySlice
## 1.20.0 (2022-05-02)
Adding:
- lo.Synchronize
- lo.SumBy
Change:
- Removed generic type definition for lo.Try0: `lo.Try0[T]()` -> `lo.Try0()`
## 1.19.0 (2022-04-30)
Adding:
- lo.RepeatBy
- lo.Subset
- lo.Replace
- lo.ReplaceAll
- lo.Substring
- lo.RuneLength
## 1.18.0 (2022-04-28)
Adding:
- lo.SomeBy
- lo.EveryBy
- lo.None
- lo.NoneBy
## 1.17.0 (2022-04-27)
Adding:
- lo.Unpack2 -> lo.Unpack3
- lo.Async0 -> lo.Async6
## 1.16.0 (2022-04-26)
Adding:
- lo.AttemptWithDelay
## 1.15.0 (2022-04-22)
Improvement:
- lo.Must: error or boolean value
## 1.14.0 (2022-04-21)
Adding:
- lo.Coalesce
## 1.13.0 (2022-04-14)
Adding:
- PickBy
- PickByKeys
- PickByValues
- OmitBy
- OmitByKeys
- OmitByValues
- Clamp
- MapKeys
- Invert
- IfF + ElseIfF + ElseF
- T0() + T1() + T2() + T3() + ...
## 1.12.0 (2022-04-12)
Adding:
- Must
- Must{0-6}
- FindOrElse
- Async
- MinBy
- MaxBy
- Count
- CountBy
- FindIndexOf
- FindLastIndexOf
- FilterMap
## 1.11.0 (2022-03-11)
Adding:
- Try
- Try{0-6}
- TryWitchValue
- TryCatch
- TryCatchWitchValue
- Debounce
- Reject
## 1.10.0 (2022-03-11)
Adding:
- Range
- RangeFrom
- RangeWithSteps
## 1.9.0 (2022-03-10)
Added
- Drop
- DropRight
- DropWhile
- DropRightWhile
## 1.8.0 (2022-03-10)
Adding Union.
## 1.7.0 (2022-03-09)
Adding ContainBy
Adding MapValues
Adding FlatMap
## 1.6.0 (2022-03-07)
Fixed PartitionBy.
Adding Sample
Adding Samples
## 1.5.0 (2022-03-07)
Adding Times
Adding Attempt
Adding Repeat
## 1.4.0 (2022-03-07)
- adding tuple types (2->9)
- adding Zip + Unzip
- adding lo.PartitionBy + lop.PartitionBy
- adding lop.GroupBy
- fixing Nth
## 1.3.0 (2022-03-03)
Last and Nth return errors

View File

@ -1,8 +1,8 @@
FROM golang:1.18rc1-bullseye
FROM golang:1.18
WORKDIR /go/src/github.com/samber/lo
COPY Makefile go.* /go/src/github.com/samber/lo/
COPY Makefile go.* ./
RUN make tools

15
vendor/github.com/samber/lo/Makefile generated vendored
View File

@ -1,10 +1,5 @@
BIN=go
# BIN=go1.18beta1
go1.18beta1:
go install golang.org/dl/go1.18beta1@latest
go1.18beta1 download
build:
${BIN} build -v ./...
@ -12,15 +7,15 @@ build:
test:
go test -race -v ./...
watch-test:
reflex -R assets.go -t 50ms -s -- sh -c 'gotest -race -v ./...'
reflex -t 50ms -s -- sh -c 'gotest -race -v ./...'
bench:
go test -benchmem -count 3 -bench ./...
watch-bench:
reflex -R assets.go -t 50ms -s -- sh -c 'go test -benchmem -count 3 -bench ./...'
reflex -t 50ms -s -- sh -c 'go test -benchmem -count 3 -bench ./...'
coverage:
${BIN} test -v -coverprofile cover.out .
${BIN} test -v -coverprofile=cover.out -covermode=atomic .
${BIN} tool cover -html=cover.out -o cover.html
# tools
@ -31,7 +26,7 @@ tools:
${BIN} install github.com/jondot/goweight@latest
${BIN} install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
${BIN} get -t -u golang.org/x/tools/cmd/cover
${BIN} get -t -u github.com/sonatype-nexus-community/nancy@latest
${BIN} install github.com/sonatype-nexus-community/nancy@latest
go mod tidy
lint:
@ -40,11 +35,9 @@ lint-fix:
golangci-lint run --timeout 60s --max-same-issues 50 --fix ./...
audit: tools
${BIN} mod tidy
${BIN} list -json -m all | nancy sleuth
outdated: tools
${BIN} mod tidy
${BIN} list -u -m -json all | go-mod-outdated -update -direct
weight: tools

1833
vendor/github.com/samber/lo/README.md generated vendored

File diff suppressed because it is too large Load Diff

228
vendor/github.com/samber/lo/channel.go generated vendored Normal file
View File

@ -0,0 +1,228 @@
package lo
import (
"math/rand"
"time"
)
type DispatchingStrategy[T any] func(msg T, index uint64, channels []<-chan T) int
// ChannelDispatcher distributes messages from input channels into N child channels.
// Close events are propagated to children.
// Underlying channels can have a fixed buffer capacity or be unbuffered when cap is 0.
func ChannelDispatcher[T any](stream <-chan T, count int, channelBufferCap int, strategy DispatchingStrategy[T]) []<-chan T {
children := createChannels[T](count, channelBufferCap)
roChildren := channelsToReadOnly(children)
go func() {
// propagate channel closing to children
defer closeChannels(children)
var i uint64 = 0
for {
msg, ok := <-stream
if !ok {
return
}
destination := strategy(msg, i, roChildren) % count
children[destination] <- msg
i++
}
}()
return roChildren
}
func createChannels[T any](count int, channelBufferCap int) []chan T {
children := make([]chan T, 0, count)
for i := 0; i < count; i++ {
children = append(children, make(chan T, channelBufferCap))
}
return children
}
func channelsToReadOnly[T any](children []chan T) []<-chan T {
roChildren := make([]<-chan T, 0, len(children))
for i := range children {
roChildren = append(roChildren, children[i])
}
return roChildren
}
func closeChannels[T any](children []chan T) {
for i := 0; i < len(children); i++ {
close(children[i])
}
}
func channelIsNotFull[T any](ch <-chan T) bool {
return cap(ch) == 0 || len(ch) < cap(ch)
}
// DispatchingStrategyRoundRobin distributes messages in a rotating sequential manner.
// If the channel capacity is exceeded, the next channel will be selected and so on.
func DispatchingStrategyRoundRobin[T any](msg T, index uint64, channels []<-chan T) int {
for {
i := int(index % uint64(len(channels)))
if channelIsNotFull(channels[i]) {
return i
}
index++
time.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥
}
}
// DispatchingStrategyRandom distributes messages in a random manner.
// If the channel capacity is exceeded, another random channel will be selected and so on.
func DispatchingStrategyRandom[T any](msg T, index uint64, channels []<-chan T) int {
for {
i := rand.Intn(len(channels))
if channelIsNotFull(channels[i]) {
return i
}
time.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥
}
}
// DispatchingStrategyRandom distributes messages in a weighted manner.
// If the channel capacity is exceeded, another random channel will be selected and so on.
func DispatchingStrategyWeightedRandom[T any](weights []int) DispatchingStrategy[T] {
seq := []int{}
for i := 0; i < len(weights); i++ {
for j := 0; j < weights[i]; j++ {
seq = append(seq, i)
}
}
return func(msg T, index uint64, channels []<-chan T) int {
for {
i := seq[rand.Intn(len(seq))]
if channelIsNotFull(channels[i]) {
return i
}
time.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥
}
}
}
// DispatchingStrategyFirst distributes messages in the first non-full channel.
// If the capacity of the first channel is exceeded, the second channel will be selected and so on.
func DispatchingStrategyFirst[T any](msg T, index uint64, channels []<-chan T) int {
for {
for i := range channels {
if channelIsNotFull(channels[i]) {
return i
}
}
time.Sleep(10 * time.Microsecond) // prevent CPU from burning 🔥
}
}
// DispatchingStrategyLeast distributes messages in the emptiest channel.
func DispatchingStrategyLeast[T any](msg T, index uint64, channels []<-chan T) int {
seq := Range(len(channels))
return MinBy(seq, func(item int, min int) bool {
return len(channels[item]) < len(channels[min])
})
}
// DispatchingStrategyMost distributes messages in the fulliest channel.
// If the channel capacity is exceeded, the next channel will be selected and so on.
func DispatchingStrategyMost[T any](msg T, index uint64, channels []<-chan T) int {
seq := Range(len(channels))
return MaxBy(seq, func(item int, max int) bool {
return len(channels[item]) > len(channels[max]) && channelIsNotFull(channels[item])
})
}
// SliceToChannel returns a read-only channels of collection elements.
func SliceToChannel[T any](bufferSize int, collection []T) <-chan T {
ch := make(chan T, bufferSize)
go func() {
for _, item := range collection {
ch <- item
}
close(ch)
}()
return ch
}
// Generator implements the generator design pattern.
func Generator[T any](bufferSize int, generator func(yield func(T))) <-chan T {
ch := make(chan T, bufferSize)
go func() {
// WARNING: infinite loop
generator(func(t T) {
ch <- t
})
close(ch)
}()
return ch
}
// Batch creates a slice of n elements from a channel. Returns the slice and the slice length.
// @TODO: we should probaby provide an helper that reuse the same buffer.
func Batch[T any](ch <-chan T, size int) (collection []T, length int, readTime time.Duration, ok bool) {
buffer := make([]T, 0, size)
index := 0
now := time.Now()
for ; index < size; index++ {
item, ok := <-ch
if !ok {
return buffer, index, time.Since(now), false
}
buffer = append(buffer, item)
}
return buffer, index, time.Since(now), true
}
// BatchWithTimeout creates a slice of n elements from a channel, with timeout. Returns the slice and the slice length.
// @TODO: we should probaby provide an helper that reuse the same buffer.
func BatchWithTimeout[T any](ch <-chan T, size int, timeout time.Duration) (collection []T, length int, readTime time.Duration, ok bool) {
expire := time.NewTimer(timeout)
defer expire.Stop()
buffer := make([]T, 0, size)
index := 0
now := time.Now()
for ; index < size; index++ {
select {
case item, ok := <-ch:
if !ok {
return buffer, index, time.Since(now), false
}
buffer = append(buffer, item)
case <-expire.C:
return buffer, index, time.Since(now), true
}
}
return buffer, index, time.Since(now), true
}

95
vendor/github.com/samber/lo/concurrency.go generated vendored Normal file
View File

@ -0,0 +1,95 @@
package lo
import "sync"
type synchronize struct {
locker sync.Locker
}
func (s *synchronize) Do(cb func()) {
s.locker.Lock()
Try0(cb)
s.locker.Unlock()
}
// Synchronize wraps the underlying callback in a mutex. It receives an optional mutex.
func Synchronize(opt ...sync.Locker) *synchronize {
if len(opt) > 1 {
panic("unexpected arguments")
} else if len(opt) == 0 {
opt = append(opt, &sync.Mutex{})
}
return &synchronize{
locker: opt[0],
}
}
// Async executes a function in a goroutine and returns the result in a channel.
func Async[A any](f func() A) chan A {
ch := make(chan A)
go func() {
ch <- f()
}()
return ch
}
// Async0 executes a function in a goroutine and returns a channel set once the function finishes.
func Async0(f func()) chan struct{} {
ch := make(chan struct{})
go func() {
f()
ch <- struct{}{}
}()
return ch
}
// Async1 is an alias to Async.
func Async1[A any](f func() A) chan A {
return Async(f)
}
// Async2 has the same behavior as Async, but returns the 2 results as a tuple inside the channel.
func Async2[A any, B any](f func() (A, B)) chan Tuple2[A, B] {
ch := make(chan Tuple2[A, B])
go func() {
ch <- T2(f())
}()
return ch
}
// Async3 has the same behavior as Async, but returns the 3 results as a tuple inside the channel.
func Async3[A any, B any, C any](f func() (A, B, C)) chan Tuple3[A, B, C] {
ch := make(chan Tuple3[A, B, C])
go func() {
ch <- T3(f())
}()
return ch
}
// Async4 has the same behavior as Async, but returns the 4 results as a tuple inside the channel.
func Async4[A any, B any, C any, D any](f func() (A, B, C, D)) chan Tuple4[A, B, C, D] {
ch := make(chan Tuple4[A, B, C, D])
go func() {
ch <- T4(f())
}()
return ch
}
// Async5 has the same behavior as Async, but returns the 5 results as a tuple inside the channel.
func Async5[A any, B any, C any, D any, E any](f func() (A, B, C, D, E)) chan Tuple5[A, B, C, D, E] {
ch := make(chan Tuple5[A, B, C, D, E])
go func() {
ch <- T5(f())
}()
return ch
}
// Async6 has the same behavior as Async, but returns the 6 results as a tuple inside the channel.
func Async6[A any, B any, C any, D any, E any, F any](f func() (A, B, C, D, E, F)) chan Tuple6[A, B, C, D, E, F] {
ch := make(chan Tuple6[A, B, C, D, E, F])
go func() {
ch <- T6(f())
}()
return ch
}

View File

@ -1,6 +1,7 @@
package lo
// Ternary is a 1 line if/else statement.
// Play: https://go.dev/play/p/t-D7WBL44h2
func Ternary[T any](condition bool, ifOutput T, elseOutput T) T {
if condition {
return ifOutput
@ -9,12 +10,23 @@ func Ternary[T any](condition bool, ifOutput T, elseOutput T) T {
return elseOutput
}
// TernaryF is a 1 line if/else statement whose options are functions
// Play: https://go.dev/play/p/AO4VW20JoqM
func TernaryF[T any](condition bool, ifFunc func() T, elseFunc func() T) T {
if condition {
return ifFunc()
}
return elseFunc()
}
type ifElse[T any] struct {
result T
done bool
}
// If.
// Play: https://go.dev/play/p/WSw3ApMxhyW
func If[T any](condition bool, result T) *ifElse[T] {
if condition {
return &ifElse[T]{result, true}
@ -24,7 +36,19 @@ func If[T any](condition bool, result T) *ifElse[T] {
return &ifElse[T]{t, false}
}
// IfF.
// Play: https://go.dev/play/p/WSw3ApMxhyW
func IfF[T any](condition bool, resultF func() T) *ifElse[T] {
if condition {
return &ifElse[T]{resultF(), true}
}
var t T
return &ifElse[T]{t, false}
}
// ElseIf.
// Play: https://go.dev/play/p/WSw3ApMxhyW
func (i *ifElse[T]) ElseIf(condition bool, result T) *ifElse[T] {
if !i.done && condition {
i.result = result
@ -34,7 +58,19 @@ func (i *ifElse[T]) ElseIf(condition bool, result T) *ifElse[T] {
return i
}
// ElseIfF.
// Play: https://go.dev/play/p/WSw3ApMxhyW
func (i *ifElse[T]) ElseIfF(condition bool, resultF func() T) *ifElse[T] {
if !i.done && condition {
i.result = resultF()
i.done = true
}
return i
}
// Else.
// Play: https://go.dev/play/p/WSw3ApMxhyW
func (i *ifElse[T]) Else(result T) T {
if i.done {
return i.result
@ -43,6 +79,16 @@ func (i *ifElse[T]) Else(result T) T {
return result
}
// ElseF.
// Play: https://go.dev/play/p/WSw3ApMxhyW
func (i *ifElse[T]) ElseF(resultF func() T) T {
if i.done {
return i.result
}
return resultF()
}
type switchCase[T comparable, R any] struct {
predicate T
result R
@ -50,6 +96,7 @@ type switchCase[T comparable, R any] struct {
}
// Switch is a pure functional switch/case/default statement.
// Play: https://go.dev/play/p/TGbKUMAeRUd
func Switch[T comparable, R any](predicate T) *switchCase[T, R] {
var result R
@ -61,6 +108,7 @@ func Switch[T comparable, R any](predicate T) *switchCase[T, R] {
}
// Case.
// Play: https://go.dev/play/p/TGbKUMAeRUd
func (s *switchCase[T, R]) Case(val T, result R) *switchCase[T, R] {
if !s.done && s.predicate == val {
s.result = result
@ -71,6 +119,7 @@ func (s *switchCase[T, R]) Case(val T, result R) *switchCase[T, R] {
}
// CaseF.
// Play: https://go.dev/play/p/TGbKUMAeRUd
func (s *switchCase[T, R]) CaseF(val T, cb func() R) *switchCase[T, R] {
if !s.done && s.predicate == val {
s.result = cb()
@ -81,6 +130,7 @@ func (s *switchCase[T, R]) CaseF(val T, cb func() R) *switchCase[T, R] {
}
// Default.
// Play: https://go.dev/play/p/TGbKUMAeRUd
func (s *switchCase[T, R]) Default(result R) R {
if !s.done {
s.result = result
@ -90,6 +140,7 @@ func (s *switchCase[T, R]) Default(result R) R {
}
// DefaultF.
// Play: https://go.dev/play/p/TGbKUMAeRUd
func (s *switchCase[T, R]) DefaultF(cb func() R) R {
if !s.done {
s.result = cb()

View File

@ -2,8 +2,8 @@ version: '3'
services:
dev:
build: .
image: golang:1.18-bullseye
volumes:
- ./:/go/src/github.com/samber/lo
working_dir: /go/src/github.com/samber/lo
command: bash -c 'make tools ; make watch-test'
command: make watch-test

65
vendor/github.com/samber/lo/drop.go generated vendored
View File

@ -1,65 +0,0 @@
package lo
//Drop drops n elements from the beginning of a slice or array.
func Drop[T any](collection []T, n int) []T {
if len(collection) <= n {
return make([]T, 0)
}
result := make([]T, len(collection)-n)
for i := n; i < len(collection); i++ {
result[i-n] = collection[i]
}
return result
}
//DropWhile drops elements from the beginning of a slice or array while the predicate returns true.
func DropWhile[T any](collection []T, predicate func(T) bool) []T {
i := 0
for ; i < len(collection); i++ {
if !predicate(collection[i]) {
break
}
}
result := make([]T, len(collection)-i)
for j := 0; i < len(collection); i, j = i+1, j+1 {
result[j] = collection[i]
}
return result
}
//DropRight drops n elements from the end of a slice or array.
func DropRight[T any](collection []T, n int) []T {
if len(collection) <= n {
return make([]T, 0)
}
result := make([]T, len(collection)-n)
for i := len(collection) - 1 - n; i != 0; i-- {
result[i] = collection[i]
}
return result
}
//DropRightWhile drops elements from the end of a slice or array while the predicate returns true.
func DropRightWhile[T any](collection []T, predicate func(T) bool) []T {
i := len(collection) - 1
for ; i >= 0; i-- {
if !predicate(collection[i]) {
break
}
}
result := make([]T, i+1)
for ; i >= 0; i-- {
result[i] = collection[i]
}
return result
}

354
vendor/github.com/samber/lo/errors.go generated vendored Normal file
View File

@ -0,0 +1,354 @@
package lo
import (
"errors"
"fmt"
"reflect"
)
// Validate is a helper that creates an error when a condition is not met.
// Play: https://go.dev/play/p/vPyh51XpCBt
func Validate(ok bool, format string, args ...any) error {
if !ok {
return fmt.Errorf(fmt.Sprintf(format, args...))
}
return nil
}
func messageFromMsgAndArgs(msgAndArgs ...interface{}) string {
if len(msgAndArgs) == 1 {
if msgAsStr, ok := msgAndArgs[0].(string); ok {
return msgAsStr
}
return fmt.Sprintf("%+v", msgAndArgs[0])
}
if len(msgAndArgs) > 1 {
return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...)
}
return ""
}
// must panics if err is error or false.
func must(err any, messageArgs ...interface{}) {
if err == nil {
return
}
switch e := err.(type) {
case bool:
if !e {
message := messageFromMsgAndArgs(messageArgs...)
if message == "" {
message = "not ok"
}
panic(message)
}
case error:
message := messageFromMsgAndArgs(messageArgs...)
if message != "" {
panic(message + ": " + e.Error())
} else {
panic(e.Error())
}
default:
panic("must: invalid err type '" + reflect.TypeOf(err).Name() + "', should either be a bool or an error")
}
}
// Must is a helper that wraps a call to a function returning a value and an error
// and panics if err is error or false.
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must[T any](val T, err any, messageArgs ...interface{}) T {
must(err, messageArgs...)
return val
}
// Must0 has the same behavior than Must, but callback returns no variable.
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must0(err any, messageArgs ...interface{}) {
must(err, messageArgs...)
}
// Must1 is an alias to Must
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must1[T any](val T, err any, messageArgs ...interface{}) T {
return Must(val, err, messageArgs...)
}
// Must2 has the same behavior than Must, but callback returns 2 variables.
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must2[T1 any, T2 any](val1 T1, val2 T2, err any, messageArgs ...interface{}) (T1, T2) {
must(err, messageArgs...)
return val1, val2
}
// Must3 has the same behavior than Must, but callback returns 3 variables.
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must3[T1 any, T2 any, T3 any](val1 T1, val2 T2, val3 T3, err any, messageArgs ...interface{}) (T1, T2, T3) {
must(err, messageArgs...)
return val1, val2, val3
}
// Must4 has the same behavior than Must, but callback returns 4 variables.
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must4[T1 any, T2 any, T3 any, T4 any](val1 T1, val2 T2, val3 T3, val4 T4, err any, messageArgs ...interface{}) (T1, T2, T3, T4) {
must(err, messageArgs...)
return val1, val2, val3, val4
}
// Must5 has the same behavior than Must, but callback returns 5 variables.
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must5[T1 any, T2 any, T3 any, T4 any, T5 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, err any, messageArgs ...interface{}) (T1, T2, T3, T4, T5) {
must(err, messageArgs...)
return val1, val2, val3, val4, val5
}
// Must6 has the same behavior than Must, but callback returns 6 variables.
// Play: https://go.dev/play/p/TMoWrRp3DyC
func Must6[T1 any, T2 any, T3 any, T4 any, T5 any, T6 any](val1 T1, val2 T2, val3 T3, val4 T4, val5 T5, val6 T6, err any, messageArgs ...interface{}) (T1, T2, T3, T4, T5, T6) {
must(err, messageArgs...)
return val1, val2, val3, val4, val5, val6
}
// Try calls the function and return false in case of error.
func Try(callback func() error) (ok bool) {
ok = true
defer func() {
if r := recover(); r != nil {
ok = false
}
}()
err := callback()
if err != nil {
ok = false
}
return
}
// Try0 has the same behavior than Try, but callback returns no variable.
// Play: https://go.dev/play/p/mTyyWUvn9u4
func Try0(callback func()) bool {
return Try(func() error {
callback()
return nil
})
}
// Try1 is an alias to Try.
// Play: https://go.dev/play/p/mTyyWUvn9u4
func Try1(callback func() error) bool {
return Try(callback)
}
// Try2 has the same behavior than Try, but callback returns 2 variables.
// Play: https://go.dev/play/p/mTyyWUvn9u4
func Try2[T any](callback func() (T, error)) bool {
return Try(func() error {
_, err := callback()
return err
})
}
// Try3 has the same behavior than Try, but callback returns 3 variables.
// Play: https://go.dev/play/p/mTyyWUvn9u4
func Try3[T, R any](callback func() (T, R, error)) bool {
return Try(func() error {
_, _, err := callback()
return err
})
}
// Try4 has the same behavior than Try, but callback returns 4 variables.
// Play: https://go.dev/play/p/mTyyWUvn9u4
func Try4[T, R, S any](callback func() (T, R, S, error)) bool {
return Try(func() error {
_, _, _, err := callback()
return err
})
}
// Try5 has the same behavior than Try, but callback returns 5 variables.
// Play: https://go.dev/play/p/mTyyWUvn9u4
func Try5[T, R, S, Q any](callback func() (T, R, S, Q, error)) bool {
return Try(func() error {
_, _, _, _, err := callback()
return err
})
}
// Try6 has the same behavior than Try, but callback returns 6 variables.
// Play: https://go.dev/play/p/mTyyWUvn9u4
func Try6[T, R, S, Q, U any](callback func() (T, R, S, Q, U, error)) bool {
return Try(func() error {
_, _, _, _, _, err := callback()
return err
})
}
// TryOr has the same behavior than Must, but returns a default value in case of error.
// Play: https://go.dev/play/p/B4F7Wg2Zh9X
func TryOr[A any](callback func() (A, error), fallbackA A) (A, bool) {
return TryOr1(callback, fallbackA)
}
// TryOr1 has the same behavior than Must, but returns a default value in case of error.
// Play: https://go.dev/play/p/B4F7Wg2Zh9X
func TryOr1[A any](callback func() (A, error), fallbackA A) (A, bool) {
ok := false
Try0(func() {
a, err := callback()
if err == nil {
fallbackA = a
ok = true
}
})
return fallbackA, ok
}
// TryOr2 has the same behavior than Must, but returns a default value in case of error.
// Play: https://go.dev/play/p/B4F7Wg2Zh9X
func TryOr2[A any, B any](callback func() (A, B, error), fallbackA A, fallbackB B) (A, B, bool) {
ok := false
Try0(func() {
a, b, err := callback()
if err == nil {
fallbackA = a
fallbackB = b
ok = true
}
})
return fallbackA, fallbackB, ok
}
// TryOr3 has the same behavior than Must, but returns a default value in case of error.
// Play: https://go.dev/play/p/B4F7Wg2Zh9X
func TryOr3[A any, B any, C any](callback func() (A, B, C, error), fallbackA A, fallbackB B, fallbackC C) (A, B, C, bool) {
ok := false
Try0(func() {
a, b, c, err := callback()
if err == nil {
fallbackA = a
fallbackB = b
fallbackC = c
ok = true
}
})
return fallbackA, fallbackB, fallbackC, ok
}
// TryOr4 has the same behavior than Must, but returns a default value in case of error.
// Play: https://go.dev/play/p/B4F7Wg2Zh9X
func TryOr4[A any, B any, C any, D any](callback func() (A, B, C, D, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D) (A, B, C, D, bool) {
ok := false
Try0(func() {
a, b, c, d, err := callback()
if err == nil {
fallbackA = a
fallbackB = b
fallbackC = c
fallbackD = d
ok = true
}
})
return fallbackA, fallbackB, fallbackC, fallbackD, ok
}
// TryOr5 has the same behavior than Must, but returns a default value in case of error.
// Play: https://go.dev/play/p/B4F7Wg2Zh9X
func TryOr5[A any, B any, C any, D any, E any](callback func() (A, B, C, D, E, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D, fallbackE E) (A, B, C, D, E, bool) {
ok := false
Try0(func() {
a, b, c, d, e, err := callback()
if err == nil {
fallbackA = a
fallbackB = b
fallbackC = c
fallbackD = d
fallbackE = e
ok = true
}
})
return fallbackA, fallbackB, fallbackC, fallbackD, fallbackE, ok
}
// TryOr6 has the same behavior than Must, but returns a default value in case of error.
// Play: https://go.dev/play/p/B4F7Wg2Zh9X
func TryOr6[A any, B any, C any, D any, E any, F any](callback func() (A, B, C, D, E, F, error), fallbackA A, fallbackB B, fallbackC C, fallbackD D, fallbackE E, fallbackF F) (A, B, C, D, E, F, bool) {
ok := false
Try0(func() {
a, b, c, d, e, f, err := callback()
if err == nil {
fallbackA = a
fallbackB = b
fallbackC = c
fallbackD = d
fallbackE = e
fallbackF = f
ok = true
}
})
return fallbackA, fallbackB, fallbackC, fallbackD, fallbackE, fallbackF, ok
}
// TryWithErrorValue has the same behavior than Try, but also returns value passed to panic.
// Play: https://go.dev/play/p/Kc7afQIT2Fs
func TryWithErrorValue(callback func() error) (errorValue any, ok bool) {
ok = true
defer func() {
if r := recover(); r != nil {
ok = false
errorValue = r
}
}()
err := callback()
if err != nil {
ok = false
errorValue = err
}
return
}
// TryCatch has the same behavior than Try, but calls the catch function in case of error.
// Play: https://go.dev/play/p/PnOON-EqBiU
func TryCatch(callback func() error, catch func()) {
if !Try(callback) {
catch()
}
}
// TryCatchWithErrorValue has the same behavior than TryWithErrorValue, but calls the catch function in case of error.
// Play: https://go.dev/play/p/8Pc9gwX_GZO
func TryCatchWithErrorValue(callback func() error, catch func(any)) {
if err, ok := TryWithErrorValue(callback); !ok {
catch(err)
}
}
// ErrorsAs is a shortcut for errors.As(err, &&T).
// Play: https://go.dev/play/p/8wk5rH8UfrE
func ErrorsAs[T error](err error) (T, bool) {
var t T
ok := errors.As(err, &t)
return t, ok
}

247
vendor/github.com/samber/lo/find.go generated vendored
View File

@ -3,7 +3,7 @@ package lo
import (
"fmt"
"math/rand"
"math"
"golang.org/x/exp/constraints"
)
@ -21,7 +21,7 @@ func IndexOf[T comparable](collection []T, element T) int {
return -1
}
// IndexOf returns the index at which the last occurrence of a value is found in an array or return -1
// LastIndexOf returns the index at which the last occurrence of a value is found in an array or return -1
// if the value cannot be found.
func LastIndexOf[T comparable](collection []T, element T) int {
length := len(collection)
@ -47,6 +47,179 @@ func Find[T any](collection []T, predicate func(T) bool) (T, bool) {
return result, false
}
// FindIndexOf searches an element in a slice based on a predicate and returns the index and true.
// It returns -1 and false if the element is not found.
func FindIndexOf[T any](collection []T, predicate func(T) bool) (T, int, bool) {
for i, item := range collection {
if predicate(item) {
return item, i, true
}
}
var result T
return result, -1, false
}
// FindLastIndexOf searches last element in a slice based on a predicate and returns the index and true.
// It returns -1 and false if the element is not found.
func FindLastIndexOf[T any](collection []T, predicate func(T) bool) (T, int, bool) {
length := len(collection)
for i := length - 1; i >= 0; i-- {
if predicate(collection[i]) {
return collection[i], i, true
}
}
var result T
return result, -1, false
}
// FindOrElse search an element in a slice based on a predicate. It returns the element if found or a given fallback value otherwise.
func FindOrElse[T any](collection []T, fallback T, predicate func(T) bool) T {
for _, item := range collection {
if predicate(item) {
return item
}
}
return fallback
}
// FindKey returns the key of the first value matching.
func FindKey[K comparable, V comparable](object map[K]V, value V) (K, bool) {
for k, v := range object {
if v == value {
return k, true
}
}
return Empty[K](), false
}
// FindKeyBy returns the key of the first element predicate returns truthy for.
func FindKeyBy[K comparable, V any](object map[K]V, predicate func(K, V) bool) (K, bool) {
for k, v := range object {
if predicate(k, v) {
return k, true
}
}
return Empty[K](), false
}
// FindUniques returns a slice with all the unique elements of the collection.
// The order of result values is determined by the order they occur in the collection.
func FindUniques[T comparable](collection []T) []T {
isDupl := make(map[T]bool, len(collection))
for _, item := range collection {
duplicated, ok := isDupl[item]
if !ok {
isDupl[item] = false
} else if !duplicated {
isDupl[item] = true
}
}
result := make([]T, 0, len(collection)-len(isDupl))
for _, item := range collection {
if duplicated := isDupl[item]; !duplicated {
result = append(result, item)
}
}
return result
}
// FindUniquesBy returns a slice with all the unique elements of the collection.
// The order of result values is determined by the order they occur in the array. It accepts `iteratee` which is
// invoked for each element in array to generate the criterion by which uniqueness is computed.
func FindUniquesBy[T any, U comparable](collection []T, iteratee func(T) U) []T {
isDupl := make(map[U]bool, len(collection))
for _, item := range collection {
key := iteratee(item)
duplicated, ok := isDupl[key]
if !ok {
isDupl[key] = false
} else if !duplicated {
isDupl[key] = true
}
}
result := make([]T, 0, len(collection)-len(isDupl))
for _, item := range collection {
key := iteratee(item)
if duplicated := isDupl[key]; !duplicated {
result = append(result, item)
}
}
return result
}
// FindDuplicates returns a slice with the first occurence of each duplicated elements of the collection.
// The order of result values is determined by the order they occur in the collection.
func FindDuplicates[T comparable](collection []T) []T {
isDupl := make(map[T]bool, len(collection))
for _, item := range collection {
duplicated, ok := isDupl[item]
if !ok {
isDupl[item] = false
} else if !duplicated {
isDupl[item] = true
}
}
result := make([]T, 0, len(collection)-len(isDupl))
for _, item := range collection {
if duplicated := isDupl[item]; duplicated {
result = append(result, item)
isDupl[item] = false
}
}
return result
}
// FindDuplicatesBy returns a slice with the first occurence of each duplicated elements of the collection.
// The order of result values is determined by the order they occur in the array. It accepts `iteratee` which is
// invoked for each element in array to generate the criterion by which uniqueness is computed.
func FindDuplicatesBy[T any, U comparable](collection []T, iteratee func(T) U) []T {
isDupl := make(map[U]bool, len(collection))
for _, item := range collection {
key := iteratee(item)
duplicated, ok := isDupl[key]
if !ok {
isDupl[key] = false
} else if !duplicated {
isDupl[key] = true
}
}
result := make([]T, 0, len(collection)-len(isDupl))
for _, item := range collection {
key := iteratee(item)
if duplicated := isDupl[key]; duplicated {
result = append(result, item)
isDupl[key] = false
}
}
return result
}
// Min search the minimum value of a collection.
func Min[T constraints.Ordered](collection []T) T {
var min T
@ -60,7 +233,6 @@ func Min[T constraints.Ordered](collection []T) T {
for i := 1; i < len(collection); i++ {
item := collection[i]
// if item.Less(min) {
if item < min {
min = item
}
@ -69,7 +241,29 @@ func Min[T constraints.Ordered](collection []T) T {
return min
}
// Max search the maximum value of a collection.
// MinBy search the minimum value of a collection using the given comparison function.
// If several values of the collection are equal to the smallest value, returns the first such value.
func MinBy[T any](collection []T, comparison func(T, T) bool) T {
var min T
if len(collection) == 0 {
return min
}
min = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if comparison(item, min) {
min = item
}
}
return min
}
// Max searches the maximum value of a collection.
func Max[T constraints.Ordered](collection []T) T {
var max T
@ -90,6 +284,28 @@ func Max[T constraints.Ordered](collection []T) T {
return max
}
// MaxBy search the maximum value of a collection using the given comparison function.
// If several values of the collection are equal to the greatest value, returns the first such value.
func MaxBy[T any](collection []T, comparison func(T, T) bool) T {
var max T
if len(collection) == 0 {
return max
}
max = collection[0]
for i := 1; i < len(collection); i++ {
item := collection[i]
if comparison(item, max) {
max = item
}
}
return max
}
// Last returns the last element of a collection or error if empty.
func Last[T any](collection []T) (T, error) {
length := len(collection)
@ -104,19 +320,18 @@ func Last[T any](collection []T) (T, error) {
// Nth returns the element at index `nth` of collection. If `nth` is negative, the nth element
// from the end is returned. An error is returned when nth is out of slice bounds.
func Nth[T any](collection []T, nth int) (T, error) {
if int(math.Abs(float64(nth))) >= len(collection) {
func Nth[T any, N constraints.Integer](collection []T, nth N) (T, error) {
n := int(nth)
l := len(collection)
if n >= l || -n > l {
var t T
return t, fmt.Errorf("nth: %d out of slice bounds", nth)
return t, fmt.Errorf("nth: %d out of slice bounds", n)
}
length := len(collection)
if nth >= 0 {
return collection[nth], nil
if n >= 0 {
return collection[n], nil
}
return collection[length+nth], nil
return collection[l+n], nil
}
// Sample returns a random item from collection.
@ -133,11 +348,7 @@ func Sample[T any](collection []T) T {
func Samples[T any](collection []T, count int) []T {
size := len(collection)
// put values into a map, for faster deletion
cOpy := make([]T, 0, size)
for _, v := range collection {
cOpy = append(cOpy, v)
}
cOpy := append([]T{}, collection...)
results := []T{}

8
vendor/github.com/samber/lo/func.go generated vendored Normal file
View File

@ -0,0 +1,8 @@
package lo
// Partial returns new function that, when called, has its first argument set to the provided value.
func Partial[T1, T2, R any](f func(T1, T2) R, arg1 T1) func(T2) R {
return func(t2 T2) R {
return f(arg1, t2)
}
}

View File

@ -22,7 +22,7 @@ func ContainsBy[T any](collection []T, predicate func(T) bool) bool {
return false
}
// Every returns true if all elements of a subset are contained into a collection.
// Every returns true if all elements of a subset are contained into a collection or if the subset is empty.
func Every[T comparable](collection []T, subset []T) bool {
for _, elem := range subset {
if !Contains(collection, elem) {
@ -33,7 +33,19 @@ func Every[T comparable](collection []T, subset []T) bool {
return true
}
// EveryBy returns true if the predicate returns true for all of the elements in the collection or if the collection is empty.
func EveryBy[V any](collection []V, predicate func(V) bool) bool {
for _, v := range collection {
if !predicate(v) {
return false
}
}
return true
}
// Some returns true if at least 1 element of a subset is contained into a collection.
// If the subset is empty Some returns false.
func Some[T comparable](collection []T, subset []T) bool {
for _, elem := range subset {
if Contains(collection, elem) {
@ -44,6 +56,40 @@ func Some[T comparable](collection []T, subset []T) bool {
return false
}
// SomeBy returns true if the predicate returns true for any of the elements in the collection.
// If the collection is empty SomeBy returns false.
func SomeBy[V any](collection []V, predicate func(V) bool) bool {
for _, v := range collection {
if predicate(v) {
return true
}
}
return false
}
// None returns true if no element of a subset are contained into a collection or if the subset is empty.
func None[V comparable](collection []V, subset []V) bool {
for _, elem := range subset {
if Contains(collection, elem) {
return false
}
}
return true
}
// NoneBy returns true if the predicate returns true for none of the elements in the collection or if the collection is empty.
func NoneBy[V any](collection []V, predicate func(V) bool) bool {
for _, v := range collection {
if predicate(v) {
return false
}
}
return true
}
// Intersect returns the intersection between two collections.
func Intersect[T comparable](list1 []T, list2 []T) []T {
result := []T{}
@ -129,3 +175,28 @@ func Union[T comparable](list1 []T, list2 []T) []T {
return result
}
// Without returns slice excluding all given values.
func Without[T comparable](collection []T, exclude ...T) []T {
result := make([]T, 0, len(collection))
for _, e := range collection {
if !Contains(exclude, e) {
result = append(result, e)
}
}
return result
}
// WithoutEmpty returns slice excluding empty values.
func WithoutEmpty[T comparable](collection []T) []T {
var empty T
result := make([]T, 0, len(collection))
for _, e := range collection {
if e != empty {
result = append(result, e)
}
}
return result
}

134
vendor/github.com/samber/lo/map.go generated vendored
View File

@ -1,10 +1,11 @@
package lo
// Keys creates an array of the map keys.
// Play: https://go.dev/play/p/Uu11fHASqrU
func Keys[K comparable, V any](in map[K]V) []K {
result := make([]K, 0, len(in))
for k, _ := range in {
for k := range in {
result = append(result, k)
}
@ -12,6 +13,7 @@ func Keys[K comparable, V any](in map[K]V) []K {
}
// Values creates an array of the map values.
// Play: https://go.dev/play/p/nnRTQkzQfF6
func Values[K comparable, V any](in map[K]V) []V {
result := make([]V, 0, len(in))
@ -22,7 +24,80 @@ func Values[K comparable, V any](in map[K]V) []V {
return result
}
// PickBy returns same map type filtered by given predicate.
// Play: https://go.dev/play/p/kdg8GR_QMmf
func PickBy[K comparable, V any](in map[K]V, predicate func(K, V) bool) map[K]V {
r := map[K]V{}
for k, v := range in {
if predicate(k, v) {
r[k] = v
}
}
return r
}
// PickByKeys returns same map type filtered by given keys.
// Play: https://go.dev/play/p/R1imbuci9qU
func PickByKeys[K comparable, V any](in map[K]V, keys []K) map[K]V {
r := map[K]V{}
for k, v := range in {
if Contains(keys, k) {
r[k] = v
}
}
return r
}
// PickByValues returns same map type filtered by given values.
// Play: https://go.dev/play/p/1zdzSvbfsJc
func PickByValues[K comparable, V comparable](in map[K]V, values []V) map[K]V {
r := map[K]V{}
for k, v := range in {
if Contains(values, v) {
r[k] = v
}
}
return r
}
// OmitBy returns same map type filtered by given predicate.
// Play: https://go.dev/play/p/EtBsR43bdsd
func OmitBy[K comparable, V any](in map[K]V, predicate func(K, V) bool) map[K]V {
r := map[K]V{}
for k, v := range in {
if !predicate(k, v) {
r[k] = v
}
}
return r
}
// OmitByKeys returns same map type filtered by given keys.
// Play: https://go.dev/play/p/t1QjCrs-ysk
func OmitByKeys[K comparable, V any](in map[K]V, keys []K) map[K]V {
r := map[K]V{}
for k, v := range in {
if !Contains(keys, k) {
r[k] = v
}
}
return r
}
// OmitByValues returns same map type filtered by given values.
// Play: https://go.dev/play/p/9UYZi-hrs8j
func OmitByValues[K comparable, V comparable](in map[K]V, values []V) map[K]V {
r := map[K]V{}
for k, v := range in {
if !Contains(values, v) {
r[k] = v
}
}
return r
}
// Entries transforms a map into array of key/value pairs.
// Play:
func Entries[K comparable, V any](in map[K]V) []Entry[K, V] {
entries := make([]Entry[K, V], 0, len(in))
@ -36,7 +111,15 @@ func Entries[K comparable, V any](in map[K]V) []Entry[K, V] {
return entries
}
// ToPairs transforms a map into array of key/value pairs.
// Alias of Entries().
// Play: https://go.dev/play/p/3Dhgx46gawJ
func ToPairs[K comparable, V any](in map[K]V) []Entry[K, V] {
return Entries(in)
}
// FromEntries transforms an array of key/value pairs into a map.
// Play: https://go.dev/play/p/oIr5KHFGCEN
func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V {
out := map[K]V{}
@ -47,7 +130,29 @@ func FromEntries[K comparable, V any](entries []Entry[K, V]) map[K]V {
return out
}
// FromPairs transforms an array of key/value pairs into a map.
// Alias of FromEntries().
// Play: https://go.dev/play/p/oIr5KHFGCEN
func FromPairs[K comparable, V any](entries []Entry[K, V]) map[K]V {
return FromEntries(entries)
}
// Invert creates a map composed of the inverted keys and values. If map
// contains duplicate values, subsequent values overwrite property assignments
// of previous values.
// Play: https://go.dev/play/p/rFQ4rak6iA1
func Invert[K comparable, V comparable](in map[K]V) map[V]K {
out := map[V]K{}
for k, v := range in {
out[v] = k
}
return out
}
// Assign merges multiple maps from left to right.
// Play: https://go.dev/play/p/VhwfJOyxf5o
func Assign[K comparable, V any](maps ...map[K]V) map[K]V {
out := map[K]V{}
@ -60,7 +165,20 @@ func Assign[K comparable, V any](maps ...map[K]V) map[K]V {
return out
}
// MapKeys manipulates a map keys and transforms it to a map of another type.
// Play: https://go.dev/play/p/9_4WPIqOetJ
func MapKeys[K comparable, V any, R comparable](in map[K]V, iteratee func(V, K) R) map[R]V {
result := map[R]V{}
for k, v := range in {
result[iteratee(v, k)] = v
}
return result
}
// MapValues manipulates a map values and transforms it to a map of another type.
// Play: https://go.dev/play/p/T_8xAfvcf0W
func MapValues[K comparable, V any, R any](in map[K]V, iteratee func(V, K) R) map[K]R {
result := map[K]R{}
@ -69,4 +187,16 @@ func MapValues[K comparable, V any, R any](in map[K]V, iteratee func(V, K) R) ma
}
return result
}
}
// MapToSlice transforms a map into a slice based on specific iteratee
// Play: https://go.dev/play/p/ZuiCZpDt6LD
func MapToSlice[K comparable, V any, R any](in map[K]V, iteratee func(K, V) R) []R {
result := make([]R, 0, len(in))
for k, v := range in {
result = append(result, iteratee(k, v))
}
return result
}

View File

@ -3,6 +3,7 @@ package lo
import "golang.org/x/exp/constraints"
// Range creates an array of numbers (positive and/or negative) with given length.
// Play: https://go.dev/play/p/0r6VimXAi9H
func Range(elementNum int) []int {
length := If(elementNum < 0, -elementNum).Else(elementNum)
result := make([]int, length)
@ -14,6 +15,7 @@ func Range(elementNum int) []int {
}
// RangeFrom creates an array of numbers from start with specified length.
// Play: https://go.dev/play/p/0r6VimXAi9H
func RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum int) []T {
length := If(elementNum < 0, -elementNum).Else(elementNum)
result := make([]T, length)
@ -26,6 +28,7 @@ func RangeFrom[T constraints.Integer | constraints.Float](start T, elementNum in
// RangeWithSteps creates an array of numbers (positive and/or negative) progressing from start up to, but not including end.
// step set to zero will return empty array.
// Play: https://go.dev/play/p/0r6VimXAi9H
func RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step T) []T {
result := []T{}
if start == end || step == 0 {
@ -48,3 +51,24 @@ func RangeWithSteps[T constraints.Integer | constraints.Float](start, end, step
}
return result
}
// Clamp clamps number within the inclusive lower and upper bounds.
// Play: https://go.dev/play/p/RU4lJNC2hlI
func Clamp[T constraints.Ordered](value T, min T, max T) T {
if value < min {
return min
} else if value > max {
return max
}
return value
}
// SumBy summarizes the values in a collection using the given return value from the iteration function. If collection is empty 0 is returned.
// Play: https://go.dev/play/p/Dz_a_7jN_ca
func SumBy[T any, R constraints.Float | constraints.Integer](collection []T, iteratee func(T) R) R {
var sum R = 0
for _, item := range collection {
sum = sum + iteratee(item)
}
return sum
}

View File

@ -1,19 +0,0 @@
package lo
// ToPtr returns a pointer copy of value.
func ToPtr[T any](x T) *T {
return &x
}
// ToPtr returns a slice of pointer copy of value.
func ToSlicePtr[T any](collection []T) []*T {
return Map(collection, func (x T, _ int) *T {
return &x
})
}
// Empty returns an empty value.
func Empty[T any]() T {
var t T
return t
}

89
vendor/github.com/samber/lo/retry.go generated vendored
View File

@ -1,6 +1,68 @@
package lo
// Attempt invokes a function N times until it returns valid output. Returning either the caught error or nil. When first argument is less than `1`, the function runs until a sucessfull response is returned.
import (
"sync"
"time"
)
type debounce struct {
after time.Duration
mu *sync.Mutex
timer *time.Timer
done bool
callbacks []func()
}
func (d *debounce) reset() *debounce {
d.mu.Lock()
defer d.mu.Unlock()
if d.done {
return d
}
if d.timer != nil {
d.timer.Stop()
}
d.timer = time.AfterFunc(d.after, func() {
for _, f := range d.callbacks {
f()
}
})
return d
}
func (d *debounce) cancel() {
d.mu.Lock()
defer d.mu.Unlock()
if d.timer != nil {
d.timer.Stop()
d.timer = nil
}
d.done = true
}
// NewDebounce creates a debounced instance that delays invoking functions given until after wait milliseconds have elapsed.
// Play: https://go.dev/play/p/mz32VMK2nqe
func NewDebounce(duration time.Duration, f ...func()) (func(), func()) {
d := &debounce{
after: duration,
mu: new(sync.Mutex),
timer: nil,
done: false,
callbacks: f,
}
return func() {
d.reset()
}, d.cancel
}
// Attempt invokes a function N times until it returns valid output. Returning either the caught error or nil. When first argument is less than `1`, the function runs until a successful response is returned.
// Play: https://go.dev/play/p/3ggJZ2ZKcMj
func Attempt(maxIteration int, f func(int) error) (int, error) {
var err error
@ -15,5 +77,28 @@ func Attempt(maxIteration int, f func(int) error) (int, error) {
return maxIteration, err
}
// AttemptWithDelay invokes a function N times until it returns valid output,
// with a pause between each call. Returning either the caught error or nil.
// When first argument is less than `1`, the function runs until a successful
// response is returned.
// Play: https://go.dev/play/p/tVs6CygC7m1
func AttemptWithDelay(maxIteration int, delay time.Duration, f func(int, time.Duration) error) (int, time.Duration, error) {
var err error
start := time.Now()
for i := 0; maxIteration <= 0 || i < maxIteration; i++ {
err = f(i, time.Since(start))
if err == nil {
return i + 1, time.Since(start), nil
}
if maxIteration <= 0 || i+1 < maxIteration {
time.Sleep(delay)
}
}
return maxIteration, time.Since(start), err
}
// throttle ?
// debounce ?

317
vendor/github.com/samber/lo/slice.go generated vendored
View File

@ -2,9 +2,12 @@ package lo
import (
"math/rand"
"golang.org/x/exp/constraints"
)
// Filter iterates over elements of collection, returning an array of all elements predicate returns truthy for.
// Play: https://go.dev/play/p/Apjg3WeSi7K
func Filter[V any](collection []V, predicate func(V, int) bool) []V {
result := []V{}
@ -18,6 +21,7 @@ func Filter[V any](collection []V, predicate func(V, int) bool) []V {
}
// Map manipulates a slice and transforms it to a slice of another type.
// Play: https://go.dev/play/p/OkPcYAhBo0D
func Map[T any, R any](collection []T, iteratee func(T, int) R) []R {
result := make([]R, len(collection))
@ -28,7 +32,26 @@ func Map[T any, R any](collection []T, iteratee func(T, int) R) []R {
return result
}
// FilterMap returns a slice which obtained after both filtering and mapping using the given callback function.
// The callback function should return two values:
// - the result of the mapping operation and
// - whether the result element should be included or not.
//
// Play: https://go.dev/play/p/-AuYXfy7opz
func FilterMap[T any, R any](collection []T, callback func(T, int) (R, bool)) []R {
result := []R{}
for i, item := range collection {
if r, ok := callback(item, i); ok {
result = append(result, r)
}
}
return result
}
// FlatMap manipulates a slice and transforms and flattens it to a slice of another type.
// Play: https://go.dev/play/p/YSoYmQTA8-U
func FlatMap[T any, R any](collection []T, iteratee func(T, int) []R) []R {
result := []R{}
@ -41,6 +64,7 @@ func FlatMap[T any, R any](collection []T, iteratee func(T, int) []R) []R {
// Reduce reduces collection to a value which is the accumulated result of running each element in collection
// through accumulator, where each successive invocation is supplied the return value of the previous.
// Play: https://go.dev/play/p/R4UHXZNaaUG
func Reduce[T any, R any](collection []T, accumulator func(R, T, int) R, initial R) R {
for i, item := range collection {
initial = accumulator(initial, item, i)
@ -49,7 +73,18 @@ func Reduce[T any, R any](collection []T, accumulator func(R, T, int) R, initial
return initial
}
// ReduceRight helper is like Reduce except that it iterates over elements of collection from right to left.
// Play: https://go.dev/play/p/Fq3W70l7wXF
func ReduceRight[T any, R any](collection []T, accumulator func(R, T, int) R, initial R) R {
for i := len(collection) - 1; i >= 0; i-- {
initial = accumulator(initial, collection[i], i)
}
return initial
}
// ForEach iterates over elements of collection and invokes iteratee for each element.
// Play: https://go.dev/play/p/oofyiUPRf8t
func ForEach[T any](collection []T, iteratee func(T, int)) {
for i, item := range collection {
iteratee(item, i)
@ -58,6 +93,7 @@ func ForEach[T any](collection []T, iteratee func(T, int)) {
// Times invokes the iteratee n times, returning an array of the results of each invocation.
// The iteratee is invoked with index as argument.
// Play: https://go.dev/play/p/vgQj3Glr6lT
func Times[T any](count int, iteratee func(int) T) []T {
result := make([]T, count)
@ -70,6 +106,7 @@ func Times[T any](count int, iteratee func(int) T) []T {
// Uniq returns a duplicate-free version of an array, in which only the first occurrence of each element is kept.
// The order of result values is determined by the order they occur in the array.
// Play: https://go.dev/play/p/DTzbeXZ6iEN
func Uniq[T comparable](collection []T) []T {
result := make([]T, 0, len(collection))
seen := make(map[T]struct{}, len(collection))
@ -86,9 +123,10 @@ func Uniq[T comparable](collection []T) []T {
return result
}
// Uniq returns a duplicate-free version of an array, in which only the first occurrence of each element is kept.
// UniqBy returns a duplicate-free version of an array, in which only the first occurrence of each element is kept.
// The order of result values is determined by the order they occur in the array. It accepts `iteratee` which is
// invoked for each element in array to generate the criterion by which uniqueness is computed.
// Play: https://go.dev/play/p/g42Z3QSb53u
func UniqBy[T any, U comparable](collection []T, iteratee func(T) U) []T {
result := make([]T, 0, len(collection))
seen := make(map[U]struct{}, len(collection))
@ -108,16 +146,13 @@ func UniqBy[T any, U comparable](collection []T, iteratee func(T) U) []T {
}
// GroupBy returns an object composed of keys generated from the results of running each element of collection through iteratee.
// Play: https://go.dev/play/p/XnQBd_v6brd
func GroupBy[T any, U comparable](collection []T, iteratee func(T) U) map[U][]T {
result := map[U][]T{}
for _, item := range collection {
key := iteratee(item)
if _, ok := result[key]; !ok {
result[key] = []T{}
}
result[key] = append(result[key], item)
}
@ -126,22 +161,25 @@ func GroupBy[T any, U comparable](collection []T, iteratee func(T) U) map[U][]T
// Chunk returns an array of elements split into groups the length of size. If array can't be split evenly,
// the final chunk will be the remaining elements.
// Play: https://go.dev/play/p/EeKl0AuTehH
func Chunk[T any](collection []T, size int) [][]T {
if size <= 0 {
panic("Second parameter must be greater than 0")
}
result := make([][]T, 0, len(collection)/2+1)
length := len(collection)
chunksNum := len(collection) / size
if len(collection)%size != 0 {
chunksNum += 1
}
for i := 0; i < length; i++ {
chunk := i / size
result := make([][]T, 0, chunksNum)
if i%size == 0 {
result = append(result, make([]T, 0, size))
for i := 0; i < chunksNum; i++ {
last := (i + 1) * size
if last > len(collection) {
last = len(collection)
}
result[chunk] = append(result[chunk], collection[i])
result = append(result, collection[i*size:last])
}
return result
@ -150,6 +188,7 @@ func Chunk[T any](collection []T, size int) [][]T {
// PartitionBy returns an array of elements split into groups. The order of grouped values is
// determined by the order they occur in collection. The grouping is generated from the results
// of running each element of collection through iteratee.
// Play: https://go.dev/play/p/NfQ_nGjkgXW
func PartitionBy[T any, K comparable](collection []T, iteratee func(x T) K) [][]T {
result := [][]T{}
seen := map[K]int{}
@ -174,18 +213,24 @@ func PartitionBy[T any, K comparable](collection []T, iteratee func(x T) K) [][]
// return Values[K, []T](groups)
}
// Flattens returns an array a single level deep.
// Flatten returns an array a single level deep.
// Play: https://go.dev/play/p/rbp9ORaMpjw
func Flatten[T any](collection [][]T) []T {
result := []T{}
totalLen := 0
for i := range collection {
totalLen += len(collection[i])
}
for _, item := range collection {
result = append(result, item...)
result := make([]T, 0, totalLen)
for i := range collection {
result = append(result, collection[i]...)
}
return result
}
// Shuffle returns an array of shuffled values. Uses the Fisher-Yates shuffle algorithm.
// Play: https://go.dev/play/p/Qp73bnTDnc7
func Shuffle[T any](collection []T) []T {
rand.Shuffle(len(collection), func(i, j int) {
collection[i], collection[j] = collection[j], collection[i]
@ -195,6 +240,7 @@ func Shuffle[T any](collection []T) []T {
}
// Reverse reverses array so that the first element becomes the last, the second element becomes the second to last, and so on.
// Play: https://go.dev/play/p/fhUMLvZ7vS6
func Reverse[T any](collection []T) []T {
length := len(collection)
half := length / 2
@ -208,10 +254,11 @@ func Reverse[T any](collection []T) []T {
}
// Fill fills elements of array with `initial` value.
// Play: https://go.dev/play/p/VwR34GzqEub
func Fill[T Clonable[T]](collection []T, initial T) []T {
result := make([]T, 0, len(collection))
for _ = range collection {
for range collection {
result = append(result, initial.Clone())
}
@ -219,6 +266,7 @@ func Fill[T Clonable[T]](collection []T, initial T) []T {
}
// Repeat builds a slice with N copies of initial value.
// Play: https://go.dev/play/p/g3uHXbmc3b6
func Repeat[T Clonable[T]](count int, initial T) []T {
result := make([]T, 0, count)
@ -229,7 +277,20 @@ func Repeat[T Clonable[T]](count int, initial T) []T {
return result
}
// RepeatBy builds a slice with values returned by N calls of callback.
// Play: https://go.dev/play/p/ozZLCtX_hNU
func RepeatBy[T any](count int, predicate func(int) T) []T {
result := make([]T, 0, count)
for i := 0; i < count; i++ {
result = append(result, predicate(i))
}
return result
}
// KeyBy transforms a slice or an array of structs to a map based on a pivot callback.
// Play: https://go.dev/play/p/mdaClUAT-zZ
func KeyBy[K comparable, V any](collection []V, iteratee func(V) K) map[K]V {
result := make(map[K]V, len(collection))
@ -240,3 +301,223 @@ func KeyBy[K comparable, V any](collection []V, iteratee func(V) K) map[K]V {
return result
}
// Associate returns a map containing key-value pairs provided by transform function applied to elements of the given slice.
// If any of two pairs would have the same key the last one gets added to the map.
// The order of keys in returned map is not specified and is not guaranteed to be the same from the original array.
// Play: https://go.dev/play/p/WHa2CfMO3Lr
func Associate[T any, K comparable, V any](collection []T, transform func(T) (K, V)) map[K]V {
result := make(map[K]V)
for _, t := range collection {
k, v := transform(t)
result[k] = v
}
return result
}
// SliceToMap returns a map containing key-value pairs provided by transform function applied to elements of the given slice.
// If any of two pairs would have the same key the last one gets added to the map.
// The order of keys in returned map is not specified and is not guaranteed to be the same from the original array.
// Alias of Associate().
// Play: https://go.dev/play/p/WHa2CfMO3Lr
func SliceToMap[T any, K comparable, V any](collection []T, transform func(T) (K, V)) map[K]V {
return Associate(collection, transform)
}
// Drop drops n elements from the beginning of a slice or array.
// Play: https://go.dev/play/p/JswS7vXRJP2
func Drop[T any](collection []T, n int) []T {
if len(collection) <= n {
return make([]T, 0)
}
result := make([]T, 0, len(collection)-n)
return append(result, collection[n:]...)
}
// DropRight drops n elements from the end of a slice or array.
// Play: https://go.dev/play/p/GG0nXkSJJa3
func DropRight[T any](collection []T, n int) []T {
if len(collection) <= n {
return []T{}
}
result := make([]T, 0, len(collection)-n)
return append(result, collection[:len(collection)-n]...)
}
// DropWhile drops elements from the beginning of a slice or array while the predicate returns true.
// Play: https://go.dev/play/p/7gBPYw2IK16
func DropWhile[T any](collection []T, predicate func(T) bool) []T {
i := 0
for ; i < len(collection); i++ {
if !predicate(collection[i]) {
break
}
}
result := make([]T, 0, len(collection)-i)
return append(result, collection[i:]...)
}
// DropRightWhile drops elements from the end of a slice or array while the predicate returns true.
// Play: https://go.dev/play/p/3-n71oEC0Hz
func DropRightWhile[T any](collection []T, predicate func(T) bool) []T {
i := len(collection) - 1
for ; i >= 0; i-- {
if !predicate(collection[i]) {
break
}
}
result := make([]T, 0, i+1)
return append(result, collection[:i+1]...)
}
// Reject is the opposite of Filter, this method returns the elements of collection that predicate does not return truthy for.
// Play: https://go.dev/play/p/YkLMODy1WEL
func Reject[V any](collection []V, predicate func(V, int) bool) []V {
result := []V{}
for i, item := range collection {
if !predicate(item, i) {
result = append(result, item)
}
}
return result
}
// Count counts the number of elements in the collection that compare equal to value.
// Play: https://go.dev/play/p/Y3FlK54yveC
func Count[T comparable](collection []T, value T) (count int) {
for _, item := range collection {
if item == value {
count++
}
}
return count
}
// CountBy counts the number of elements in the collection for which predicate is true.
// Play: https://go.dev/play/p/ByQbNYQQi4X
func CountBy[T any](collection []T, predicate func(T) bool) (count int) {
for _, item := range collection {
if predicate(item) {
count++
}
}
return count
}
// Subset returns a copy of a slice from `offset` up to `length` elements. Like `slice[start:start+length]`, but does not panic on overflow.
// Play: https://go.dev/play/p/tOQu1GhFcog
func Subset[T any](collection []T, offset int, length uint) []T {
size := len(collection)
if offset < 0 {
offset = size + offset
if offset < 0 {
offset = 0
}
}
if offset > size {
return []T{}
}
if length > uint(size)-uint(offset) {
length = uint(size - offset)
}
return collection[offset : offset+int(length)]
}
// Slice returns a copy of a slice from `start` up to, but not including `end`. Like `slice[start:end]`, but does not panic on overflow.
// Play: https://go.dev/play/p/8XWYhfMMA1h
func Slice[T any](collection []T, start int, end int) []T {
size := len(collection)
if start >= end {
return []T{}
}
if start > size {
start = size
}
if end > size {
end = size
}
return collection[start:end]
}
// Replace returns a copy of the slice with the first n non-overlapping instances of old replaced by new.
// Play: https://go.dev/play/p/XfPzmf9gql6
func Replace[T comparable](collection []T, old T, new T, n int) []T {
result := make([]T, len(collection))
copy(result, collection)
for i := range result {
if result[i] == old && n != 0 {
result[i] = new
n--
}
}
return result
}
// ReplaceAll returns a copy of the slice with all non-overlapping instances of old replaced by new.
// Play: https://go.dev/play/p/a9xZFUHfYcV
func ReplaceAll[T comparable](collection []T, old T, new T) []T {
return Replace(collection, old, new, -1)
}
// Compact returns a slice of all non-zero elements.
// Play: https://go.dev/play/p/tXiy-iK6PAc
func Compact[T comparable](collection []T) []T {
var zero T
result := []T{}
for _, item := range collection {
if item != zero {
result = append(result, item)
}
}
return result
}
// IsSorted checks if a slice is sorted.
// Play: https://go.dev/play/p/mc3qR-t4mcx
func IsSorted[T constraints.Ordered](collection []T) bool {
for i := 1; i < len(collection); i++ {
if collection[i-1] > collection[i] {
return false
}
}
return true
}
// IsSortedByKey checks if a slice is sorted by iteratee.
// Play: https://go.dev/play/p/wiG6XyBBu49
func IsSortedByKey[T any, K constraints.Ordered](collection []T, iteratee func(T) K) bool {
size := len(collection)
for i := 0; i < size-1; i++ {
if iteratee(collection[i]) > iteratee(collection[i+1]) {
return false
}
}
return true
}

65
vendor/github.com/samber/lo/string.go generated vendored Normal file
View File

@ -0,0 +1,65 @@
package lo
import (
"unicode/utf8"
)
// Substring return part of a string.
// Play: https://go.dev/play/p/TQlxQi82Lu1
func Substring[T ~string](str T, offset int, length uint) T {
size := len(str)
if offset < 0 {
offset = size + offset
if offset < 0 {
offset = 0
}
}
if offset > size {
return Empty[T]()
}
if length > uint(size)-uint(offset) {
length = uint(size - offset)
}
return str[offset : offset+int(length)]
}
// ChunkString returns an array of strings split into groups the length of size. If array can't be split evenly,
// the final chunk will be the remaining elements.
// Play: https://go.dev/play/p/__FLTuJVz54
func ChunkString[T ~string](str T, size int) []T {
if size <= 0 {
panic("lo.ChunkString: Size parameter must be greater than 0")
}
if len(str) == 0 {
return []T{""}
}
if size >= len(str) {
return []T{str}
}
var chunks []T = make([]T, 0, ((len(str)-1)/size)+1)
currentLen := 0
currentStart := 0
for i := range str {
if currentLen == size {
chunks = append(chunks, str[currentStart:i])
currentLen = 0
currentStart = i
}
currentLen++
}
chunks = append(chunks, str[currentStart:])
return chunks
}
// RuneLength is an alias to utf8.RuneCountInString which returns the number of runes in string.
// Play: https://go.dev/play/p/tuhgW_lWY8l
func RuneLength(str string) int {
return utf8.RuneCountInString(str)
}

32
vendor/github.com/samber/lo/test.go generated vendored Normal file
View File

@ -0,0 +1,32 @@
package lo
import (
"os"
"testing"
"time"
)
// https://github.com/stretchr/testify/issues/1101
func testWithTimeout(t *testing.T, timeout time.Duration) {
t.Helper()
testFinished := make(chan struct{})
t.Cleanup(func() { close(testFinished) })
go func() {
select {
case <-testFinished:
case <-time.After(timeout):
t.Errorf("test timed out after %s", timeout)
os.Exit(1)
}
}()
}
type foo struct {
bar string
}
func (f foo) Clone() foo {
return foo{f.bar}
}

220
vendor/github.com/samber/lo/tuples.go generated vendored
View File

@ -1,28 +1,113 @@
package lo
func longestCollection(collections ...[]interface{}) int {
max := 0
// T2 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T2[A any, B any](a A, b B) Tuple2[A, B] {
return Tuple2[A, B]{A: a, B: b}
}
for _, collection := range collections {
if len(collection) > max {
max = len(collection)
}
}
// T3 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T3[A any, B any, C any](a A, b B, c C) Tuple3[A, B, C] {
return Tuple3[A, B, C]{A: a, B: b, C: c}
}
return max
// T4 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T4[A any, B any, C any, D any](a A, b B, c C, d D) Tuple4[A, B, C, D] {
return Tuple4[A, B, C, D]{A: a, B: b, C: c, D: d}
}
// T5 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T5[A any, B any, C any, D any, E any](a A, b B, c C, d D, e E) Tuple5[A, B, C, D, E] {
return Tuple5[A, B, C, D, E]{A: a, B: b, C: c, D: d, E: e}
}
// T6 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T6[A any, B any, C any, D any, E any, F any](a A, b B, c C, d D, e E, f F) Tuple6[A, B, C, D, E, F] {
return Tuple6[A, B, C, D, E, F]{A: a, B: b, C: c, D: d, E: e, F: f}
}
// T7 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T7[A any, B any, C any, D any, E any, F any, G any](a A, b B, c C, d D, e E, f F, g G) Tuple7[A, B, C, D, E, F, G] {
return Tuple7[A, B, C, D, E, F, G]{A: a, B: b, C: c, D: d, E: e, F: f, G: g}
}
// T8 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T8[A any, B any, C any, D any, E any, F any, G any, H any](a A, b B, c C, d D, e E, f F, g G, h H) Tuple8[A, B, C, D, E, F, G, H] {
return Tuple8[A, B, C, D, E, F, G, H]{A: a, B: b, C: c, D: d, E: e, F: f, G: g, H: h}
}
// T8 creates a tuple from a list of values.
// Play: https://go.dev/play/p/IllL3ZO4BQm
func T9[A any, B any, C any, D any, E any, F any, G any, H any, I any](a A, b B, c C, d D, e E, f F, g G, h H, i I) Tuple9[A, B, C, D, E, F, G, H, I] {
return Tuple9[A, B, C, D, E, F, G, H, I]{A: a, B: b, C: c, D: d, E: e, F: f, G: g, H: h, I: i}
}
// Unpack2 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack2[A any, B any](tuple Tuple2[A, B]) (A, B) {
return tuple.A, tuple.B
}
// Unpack3 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack3[A any, B any, C any](tuple Tuple3[A, B, C]) (A, B, C) {
return tuple.A, tuple.B, tuple.C
}
// Unpack4 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack4[A any, B any, C any, D any](tuple Tuple4[A, B, C, D]) (A, B, C, D) {
return tuple.A, tuple.B, tuple.C, tuple.D
}
// Unpack5 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack5[A any, B any, C any, D any, E any](tuple Tuple5[A, B, C, D, E]) (A, B, C, D, E) {
return tuple.A, tuple.B, tuple.C, tuple.D, tuple.E
}
// Unpack6 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack6[A any, B any, C any, D any, E any, F any](tuple Tuple6[A, B, C, D, E, F]) (A, B, C, D, E, F) {
return tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F
}
// Unpack7 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack7[A any, B any, C any, D any, E any, F any, G any](tuple Tuple7[A, B, C, D, E, F, G]) (A, B, C, D, E, F, G) {
return tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F, tuple.G
}
// Unpack8 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack8[A any, B any, C any, D any, E any, F any, G any, H any](tuple Tuple8[A, B, C, D, E, F, G, H]) (A, B, C, D, E, F, G, H) {
return tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F, tuple.G, tuple.H
}
// Unpack9 returns values contained in tuple.
// Play: https://go.dev/play/p/xVP_k0kJ96W
func Unpack9[A any, B any, C any, D any, E any, F any, G any, H any, I any](tuple Tuple9[A, B, C, D, E, F, G, H, I]) (A, B, C, D, E, F, G, H, I) {
return tuple.A, tuple.B, tuple.C, tuple.D, tuple.E, tuple.F, tuple.G, tuple.H, tuple.I
}
// Zip2 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip2[A any, B any](a []A, b []B) []Tuple2[A, B] {
size := Max[int]([]int{len(a), len(b)})
size := Max([]int{len(a), len(b)})
result := make([]Tuple2[A, B], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
result = append(result, Tuple2[A, B]{
A: _a,
@ -36,15 +121,16 @@ func Zip2[A any, B any](a []A, b []B) []Tuple2[A, B] {
// Zip3 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip3[A any, B any, C any](a []A, b []B, c []C) []Tuple3[A, B, C] {
size := Max[int]([]int{len(a), len(b), len(c)})
size := Max([]int{len(a), len(b), len(c)})
result := make([]Tuple3[A, B, C], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_c, _ := Nth[C](c, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
_c, _ := Nth(c, index)
result = append(result, Tuple3[A, B, C]{
A: _a,
@ -59,16 +145,17 @@ func Zip3[A any, B any, C any](a []A, b []B, c []C) []Tuple3[A, B, C] {
// Zip4 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip4[A any, B any, C any, D any](a []A, b []B, c []C, d []D) []Tuple4[A, B, C, D] {
size := Max[int]([]int{len(a), len(b), len(c), len(d)})
size := Max([]int{len(a), len(b), len(c), len(d)})
result := make([]Tuple4[A, B, C, D], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_c, _ := Nth[C](c, index)
_d, _ := Nth[D](d, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
_c, _ := Nth(c, index)
_d, _ := Nth(d, index)
result = append(result, Tuple4[A, B, C, D]{
A: _a,
@ -84,17 +171,18 @@ func Zip4[A any, B any, C any, D any](a []A, b []B, c []C, d []D) []Tuple4[A, B,
// Zip5 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip5[A any, B any, C any, D any, E any](a []A, b []B, c []C, d []D, e []E) []Tuple5[A, B, C, D, E] {
size := Max[int]([]int{len(a), len(b), len(c), len(d), len(e)})
size := Max([]int{len(a), len(b), len(c), len(d), len(e)})
result := make([]Tuple5[A, B, C, D, E], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_c, _ := Nth[C](c, index)
_d, _ := Nth[D](d, index)
_e, _ := Nth[E](e, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
_c, _ := Nth(c, index)
_d, _ := Nth(d, index)
_e, _ := Nth(e, index)
result = append(result, Tuple5[A, B, C, D, E]{
A: _a,
@ -111,18 +199,19 @@ func Zip5[A any, B any, C any, D any, E any](a []A, b []B, c []C, d []D, e []E)
// Zip6 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip6[A any, B any, C any, D any, E any, F any](a []A, b []B, c []C, d []D, e []E, f []F) []Tuple6[A, B, C, D, E, F] {
size := Max[int]([]int{len(a), len(b), len(c), len(d), len(e), len(f)})
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f)})
result := make([]Tuple6[A, B, C, D, E, F], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_c, _ := Nth[C](c, index)
_d, _ := Nth[D](d, index)
_e, _ := Nth[E](e, index)
_f, _ := Nth[F](f, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
_c, _ := Nth(c, index)
_d, _ := Nth(d, index)
_e, _ := Nth(e, index)
_f, _ := Nth(f, index)
result = append(result, Tuple6[A, B, C, D, E, F]{
A: _a,
@ -140,19 +229,20 @@ func Zip6[A any, B any, C any, D any, E any, F any](a []A, b []B, c []C, d []D,
// Zip7 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip7[A any, B any, C any, D any, E any, F any, G any](a []A, b []B, c []C, d []D, e []E, f []F, g []G) []Tuple7[A, B, C, D, E, F, G] {
size := Max[int]([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g)})
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g)})
result := make([]Tuple7[A, B, C, D, E, F, G], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_c, _ := Nth[C](c, index)
_d, _ := Nth[D](d, index)
_e, _ := Nth[E](e, index)
_f, _ := Nth[F](f, index)
_g, _ := Nth[G](g, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
_c, _ := Nth(c, index)
_d, _ := Nth(d, index)
_e, _ := Nth(e, index)
_f, _ := Nth(f, index)
_g, _ := Nth(g, index)
result = append(result, Tuple7[A, B, C, D, E, F, G]{
A: _a,
@ -171,20 +261,21 @@ func Zip7[A any, B any, C any, D any, E any, F any, G any](a []A, b []B, c []C,
// Zip8 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip8[A any, B any, C any, D any, E any, F any, G any, H any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H) []Tuple8[A, B, C, D, E, F, G, H] {
size := Max[int]([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h)})
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h)})
result := make([]Tuple8[A, B, C, D, E, F, G, H], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_c, _ := Nth[C](c, index)
_d, _ := Nth[D](d, index)
_e, _ := Nth[E](e, index)
_f, _ := Nth[F](f, index)
_g, _ := Nth[G](g, index)
_h, _ := Nth[H](h, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
_c, _ := Nth(c, index)
_d, _ := Nth(d, index)
_e, _ := Nth(e, index)
_f, _ := Nth(f, index)
_g, _ := Nth(g, index)
_h, _ := Nth(h, index)
result = append(result, Tuple8[A, B, C, D, E, F, G, H]{
A: _a,
@ -204,21 +295,22 @@ func Zip8[A any, B any, C any, D any, E any, F any, G any, H any](a []A, b []B,
// Zip9 creates a slice of grouped elements, the first of which contains the first elements
// of the given arrays, the second of which contains the second elements of the given arrays, and so on.
// When collections have different size, the Tuple attributes are filled with zero value.
// Play: https://go.dev/play/p/jujaA6GaJTp
func Zip9[A any, B any, C any, D any, E any, F any, G any, H any, I any](a []A, b []B, c []C, d []D, e []E, f []F, g []G, h []H, i []I) []Tuple9[A, B, C, D, E, F, G, H, I] {
size := Max[int]([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(i)})
size := Max([]int{len(a), len(b), len(c), len(d), len(e), len(f), len(g), len(h), len(i)})
result := make([]Tuple9[A, B, C, D, E, F, G, H, I], 0, size)
for index := 0; index < size; index++ {
_a, _ := Nth[A](a, index)
_b, _ := Nth[B](b, index)
_c, _ := Nth[C](c, index)
_d, _ := Nth[D](d, index)
_e, _ := Nth[E](e, index)
_f, _ := Nth[F](f, index)
_g, _ := Nth[G](g, index)
_h, _ := Nth[H](h, index)
_i, _ := Nth[I](i, index)
_a, _ := Nth(a, index)
_b, _ := Nth(b, index)
_c, _ := Nth(c, index)
_d, _ := Nth(d, index)
_e, _ := Nth(e, index)
_f, _ := Nth(f, index)
_g, _ := Nth(g, index)
_h, _ := Nth(h, index)
_i, _ := Nth(i, index)
result = append(result, Tuple9[A, B, C, D, E, F, G, H, I]{
A: _a,
@ -238,6 +330,7 @@ func Zip9[A any, B any, C any, D any, E any, F any, G any, H any, I any](a []A,
// Unzip2 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip2[A any, B any](tuples []Tuple2[A, B]) ([]A, []B) {
size := len(tuples)
r1 := make([]A, 0, size)
@ -253,6 +346,7 @@ func Unzip2[A any, B any](tuples []Tuple2[A, B]) ([]A, []B) {
// Unzip3 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip3[A any, B any, C any](tuples []Tuple3[A, B, C]) ([]A, []B, []C) {
size := len(tuples)
r1 := make([]A, 0, size)
@ -270,6 +364,7 @@ func Unzip3[A any, B any, C any](tuples []Tuple3[A, B, C]) ([]A, []B, []C) {
// Unzip4 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip4[A any, B any, C any, D any](tuples []Tuple4[A, B, C, D]) ([]A, []B, []C, []D) {
size := len(tuples)
r1 := make([]A, 0, size)
@ -289,6 +384,7 @@ func Unzip4[A any, B any, C any, D any](tuples []Tuple4[A, B, C, D]) ([]A, []B,
// Unzip5 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip5[A any, B any, C any, D any, E any](tuples []Tuple5[A, B, C, D, E]) ([]A, []B, []C, []D, []E) {
size := len(tuples)
r1 := make([]A, 0, size)
@ -310,6 +406,7 @@ func Unzip5[A any, B any, C any, D any, E any](tuples []Tuple5[A, B, C, D, E]) (
// Unzip6 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip6[A any, B any, C any, D any, E any, F any](tuples []Tuple6[A, B, C, D, E, F]) ([]A, []B, []C, []D, []E, []F) {
size := len(tuples)
r1 := make([]A, 0, size)
@ -333,6 +430,7 @@ func Unzip6[A any, B any, C any, D any, E any, F any](tuples []Tuple6[A, B, C, D
// Unzip7 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip7[A any, B any, C any, D any, E any, F any, G any](tuples []Tuple7[A, B, C, D, E, F, G]) ([]A, []B, []C, []D, []E, []F, []G) {
size := len(tuples)
r1 := make([]A, 0, size)
@ -358,6 +456,7 @@ func Unzip7[A any, B any, C any, D any, E any, F any, G any](tuples []Tuple7[A,
// Unzip8 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip8[A any, B any, C any, D any, E any, F any, G any, H any](tuples []Tuple8[A, B, C, D, E, F, G, H]) ([]A, []B, []C, []D, []E, []F, []G, []H) {
size := len(tuples)
r1 := make([]A, 0, size)
@ -385,6 +484,7 @@ func Unzip8[A any, B any, C any, D any, E any, F any, G any, H any](tuples []Tup
// Unzip9 accepts an array of grouped elements and creates an array regrouping the elements
// to their pre-zip configuration.
// Play: https://go.dev/play/p/ciHugugvaAW
func Unzip9[A any, B any, C any, D any, E any, F any, G any, H any, I any](tuples []Tuple9[A, B, C, D, E, F, G, H, I]) ([]A, []B, []C, []D, []E, []F, []G, []H, []I) {
size := len(tuples)
r1 := make([]A, 0, size)

88
vendor/github.com/samber/lo/type_manipulation.go generated vendored Normal file
View File

@ -0,0 +1,88 @@
package lo
// ToPtr returns a pointer copy of value.
func ToPtr[T any](x T) *T {
return &x
}
// FromPtr returns the pointer value or empty.
func FromPtr[T any](x *T) T {
if x == nil {
return Empty[T]()
}
return *x
}
// FromPtrOr returns the pointer value or the fallback value.
func FromPtrOr[T any](x *T, fallback T) T {
if x == nil {
return fallback
}
return *x
}
// ToSlicePtr returns a slice of pointer copy of value.
func ToSlicePtr[T any](collection []T) []*T {
return Map(collection, func(x T, _ int) *T {
return &x
})
}
// ToAnySlice returns a slice with all elements mapped to `any` type
func ToAnySlice[T any](collection []T) []any {
result := make([]any, len(collection))
for i, item := range collection {
result[i] = item
}
return result
}
// FromAnySlice returns an `any` slice with all elements mapped to a type.
// Returns false in case of type conversion failure.
func FromAnySlice[T any](in []any) (out []T, ok bool) {
defer func() {
if r := recover(); r != nil {
out = []T{}
ok = false
}
}()
result := make([]T, len(in))
for i, item := range in {
result[i] = item.(T)
}
return result, true
}
// Empty returns an empty value.
func Empty[T any]() T {
var zero T
return zero
}
// IsEmpty returns true if argument is a zero value.
func IsEmpty[T comparable](v T) bool {
var zero T
return zero == v
}
// IsNotEmpty returns true if argument is not a zero value.
func IsNotEmpty[T comparable](v T) bool {
var zero T
return zero != v
}
// Coalesce returns the first non-empty arguments. Arguments must be comparable.
func Coalesce[T comparable](v ...T) (result T, ok bool) {
for _, e := range v {
if e != result {
result = e
ok = true
return
}
}
return
}