This commit is contained in:
Joshua Bell 2026-01-26 21:41:26 -06:00
parent 07ec5529ac
commit f501abe660
532 changed files with 271781 additions and 0 deletions

37
vendor/github.com/samber/mo/.gitignore generated vendored Normal file
View file

@ -0,0 +1,37 @@
# Created by https://www.toptal.com/developers/gitignore/api/go
# Edit at https://www.toptal.com/developers/gitignore?templates=go
### Go ###
# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Go workspace file
go.work
### Go Patch ###
/vendor/
/Godeps/
# End of https://www.toptal.com/developers/gitignore/api/go
cover.out
cover.html
.vscode
.idea

21
vendor/github.com/samber/mo/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Samuel Berthe
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

46
vendor/github.com/samber/mo/Makefile generated vendored Normal file
View file

@ -0,0 +1,46 @@
build:
go build -v ./...
test:
go test -race -v ./...
watch-test:
reflex -t 50ms -s -- sh -c 'gotest -race -v ./...'
bench:
go test -benchmem -count 3 -bench ./...
watch-bench:
reflex -t 50ms -s -- sh -c 'go test -benchmem -count 3 -bench ./...'
coverage:
go test -v -coverprofile=cover.out -covermode=atomic ./...
go tool cover -html=cover.out -o cover.html
# tools
tools:
go install github.com/cespare/reflex@latest
go install github.com/rakyll/gotest@latest
go install github.com/psampaz/go-mod-outdated@latest
go install github.com/jondot/goweight@latest
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
go get -t -u golang.org/x/tools/cmd/cover
go install github.com/sonatype-nexus-community/nancy@latest
go install golang.org/x/perf/cmd/benchstat@latest
go install github.com/cespare/prettybench@latest
go mod tidy
lint:
golangci-lint run --timeout 60s --max-same-issues 50 ./...
lint-fix:
golangci-lint run --timeout 60s --max-same-issues 50 --fix ./...
audit:
go mod tidy
go list -json -m all | nancy sleuth
outdated:
go mod tidy
go list -u -m -json all | go-mod-outdated -update -direct
weight:
goweight

485
vendor/github.com/samber/mo/README.md generated vendored Normal file
View file

@ -0,0 +1,485 @@
# mo - Monads
[![tag](https://img.shields.io/github/tag/samber/mo.svg)](https://github.com/samber/mo/releases)
![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.18-%23007d9c)
[![GoDoc](https://godoc.org/github.com/samber/mo?status.svg)](https://pkg.go.dev/github.com/samber/mo)
![Build Status](https://github.com/samber/mo/actions/workflows/test.yml/badge.svg)
[![Go report](https://goreportcard.com/badge/github.com/samber/mo)](https://goreportcard.com/report/github.com/samber/mo)
[![Coverage](https://img.shields.io/codecov/c/github/samber/mo)](https://codecov.io/gh/samber/mo)
[![License](https://img.shields.io/github/license/samber/mo)](./LICENSE)
🦄 **`samber/mo` brings monads and popular FP abstractions to Go projects. `samber/mo` uses the recent Go 1.18+ Generics.**
**Inspired by:**
- Scala
- Rust
- FP-TS
**See also:**
- [samber/lo](https://github.com/samber/lo): A Lodash-style Go library based on Go 1.18+ Generics
- [samber/do](https://github.com/samber/do): A dependency injection toolkit based on Go 1.18+ Generics
![image](https://github.com/user-attachments/assets/1fc0f996-2a79-43e3-8db7-11e1409aca46)
**Why this name?**
I love **short name** for such utility library. This name is similar to "Monad Go" and no Go package uses this name.
## 💡 Features
We currently support the following data types:
- `Option[T]` (Maybe)
- `Result[T]`
- `Either[A, B]`
- `EitherX[T1, ..., TX]` (With X between 3 and 5)
- `Future[T]`
- `IO[T]`
- `IOEither[T]`
- `Task[T]`
- `TaskEither[T]`
- `State[S, A]`
## 🚀 Install
```sh
go get github.com/samber/mo@v1
```
This library is v1 and follows SemVer strictly.
No breaking changes will be made to exported APIs before v2.0.0.
This library has no dependencies except the Go std lib.
## 💡 Quick start
You can import `mo` using:
```go
import (
"github.com/samber/mo"
)
```
Quick example using the `option` sub-package `Pipe3` to compose transformations:
```go
import (
"github.com/samber/mo"
"github.com/samber/mo/option"
)
out := option.Pipe3(
mo.Some(21),
option.Map(func(v int) int { return v * 2 }),
option.FlatMap(func(v int) mo.Option[int] { return mo.None[int]() }),
option.Map(func(v int) int { return v + 21 }),
)
// out == None[int]
```
Then use one of the helpers below:
```go
option1 := mo.Some(42)
// Some(42)
option1.
FlatMap(func (value int) Option[int] {
return Some(value*2)
}).
FlatMap(func (value int) Option[int] {
return Some(value%2)
}).
FlatMap(func (value int) Option[int] {
return Some(value+21)
}).
OrElse(1234)
// 21
option2 := mo.None[int]()
// None
option2.OrElse(1234)
// 1234
option3 := option1.Match(
func(i int) (int, bool) {
// when value is present
return i * 2, true
},
func() (int, bool) {
// when value is absent
return 0, false
},
)
// Some(42)
```
More examples in [documentation](https://godoc.org/github.com/samber/mo).
### Tips for lazy developers
I cannot recommend it, but in case you are too lazy for repeating `mo.` everywhere, you can import the entire library into the namespace.
```go
import (
. "github.com/samber/mo"
)
```
I take no responsibility on this junk. 😁 💩
## 🤠 Documentation and examples
[GoDoc: https://godoc.org/github.com/samber/mo](https://godoc.org/github.com/samber/mo)
### Option[T any]
`Option` is a container for an optional value of type `T`. If value exists, `Option` is of type `Some`. If the value is absent, `Option` is of type `None`.
Implements:
- `mo.Foldable[T, U]`
Constructors:
- `mo.Some()` [doc](https://pkg.go.dev/github.com/samber/mo#Some) - [play](https://go.dev/play/p/iqz2n9n0tDM)
- `mo.None()` [doc](https://pkg.go.dev/github.com/samber/mo#None) - [play](https://go.dev/play/p/yYQPsYCSYlD)
- `mo.TupleToOption()` [doc](https://pkg.go.dev/github.com/samber/mo#TupleToOption) - [play](https://go.dev/play/p/gkrg2pZwOty)
- `mo.EmptyableToOption()` [doc](https://pkg.go.dev/github.com/samber/mo#EmptyableToOption) - [play](https://go.dev/play/p/GSpQQ-q-UES)
- `mo.PointerToOption()` [doc](https://pkg.go.dev/github.com/samber/mo#PointerToOption) - [play](https://go.dev/play/p/yPVMj4DUb-I)
Methods:
- `.IsPresent()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsPresent) - [play](https://go.dev/play/p/nDqIaiihyCA)
- `.IsSome()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsSome) - [play](https://go.dev/play/p/DyvGRy7fP9m)
- `.IsAbsent()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsAbsent) - [play](https://go.dev/play/p/23e2zqyVOQm)
- `.IsNone()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.IsNone) - [play](https://go.dev/play/p/EdqxKhborIP)
- `.Size()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Size) - [play](https://go.dev/play/p/7ixCNG1E9l7)
- `.Get()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Get) - [play](https://go.dev/play/p/0-JBa1usZRT)
- `.MustGet()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MustGet) - [play](https://go.dev/play/p/RVBckjdi5WR)
- `.OrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.OrElse) - [play](https://go.dev/play/p/TrGByFWCzXS)
- `.OrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.OrEmpty) - [play](https://go.dev/play/p/SpSUJcE-tQm)
- `.ToPointer()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.ToPointer) - [play](https://go.dev/play/p/N43w92SM-Bs)
- `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.ForEach)
- `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Match) - [play](https://go.dev/play/p/1V6st3LDJsM)
- `.Map()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Map) - [play](https://go.dev/play/p/mvfP3pcP_eJ)
- `.MapNone()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MapNone) - [play](https://go.dev/play/p/_KaHWZ6Q17b)
- `.MapValue()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MapValue)
- `.FlatMap()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.FlatMap) - [play](https://go.dev/play/p/OXO-zJx6n5r)
- `.MarshalJSON()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MarshalJSON)
- `.UnmarshalJSON()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.UnmarshalJSON)
- `.MarshalText()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MarshalText)
- `.UnmarshalText()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.UnmarshalText)
- `.MarshalBinary()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.MarshalBinary)
- `.UnmarshalBinary()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.UnmarshalBinary)
- `.GobEncode()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.GobEncode)
- `.GobDecode()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.GobDecode)
- `.Scan()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Scan)
- `.Value()` [doc](https://pkg.go.dev/github.com/samber/mo#Option.Value)
Other:
- `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold)
Sub-package `option` (transformations and pipes):
- `option.Map()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#Map)
- `option.FlatMap()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#FlatMap)
- `option.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#Match)
- `option.FlatMatch()()` [doc](https://pkg.go.dev/github.com/samber/mo/option#FlatMatch)
- `option.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/option#Pipe1)
### Result[T any]
`Result` respresent a result of an action having one of the following output: success or failure. An instance of `Result` is an instance of either `Ok` or `Err`. It could be compared to `Either[error, T]`.
Implements:
- `mo.Foldable[T, U]`
Constructors:
- `mo.Ok()` [doc](https://pkg.go.dev/github.com/samber/mo#Ok) - [play](https://go.dev/play/p/PDwADdzNoyZ)
- `mo.Err()` [doc](https://pkg.go.dev/github.com/samber/mo#Err) - [play](https://go.dev/play/p/PDwADdzNoyZ)
- `mo.Errf()` [doc](https://pkg.go.dev/github.com/samber/mo#Errf) - [play](https://go.dev/play/p/N43w92SM-Bs)
- `mo.TupleToResult()` [doc](https://pkg.go.dev/github.com/samber/mo#TupleToResult) - [play](https://go.dev/play/p/KWjfqQDHQwa)
- `mo.Try()` [doc](https://pkg.go.dev/github.com/samber/mo#Try) - [play](https://go.dev/play/p/ilOlQx-Mx42)
Methods:
- `.IsOk()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.IsOk) - [play](https://go.dev/play/p/sfNvBQyZfgU)
- `.IsError()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.IsError) - [play](https://go.dev/play/p/xkV9d464scV)
- `.Error()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Error) - [play](https://go.dev/play/p/CSkHGTyiXJ5)
- `.Get()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Get) - [play](https://go.dev/play/p/8KyX3z6TuNo)
- `.MustGet()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.MustGet) - [play](https://go.dev/play/p/8LSlndHoTAE)
- `.OrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.OrElse) - [play](https://go.dev/play/p/MN_ULx0soi6)
- `.OrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.OrEmpty) - [play](https://go.dev/play/p/rdKtBmOcMLh)
- `.ToEither()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.ToEither) - [play](https://go.dev/play/p/Uw1Zz6b952q)
- `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.ForEach) - [play](https://go.dev/play/p/Z59EvNdWoRx)
- `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Match) - [play](https://go.dev/play/p/-_eFaLJ31co)
- `.Map()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.Map) - [play](https://go.dev/play/p/-ndpN_b_OSc)
- `.MapValue()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.MapValue) - [play](https://go.dev/play/p/qyyjUP4XbK2)
- `.MapErr()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.MapErr) - [play](https://go.dev/play/p/WraZixg9GGf)
- `.FlatMap()` [doc](https://pkg.go.dev/github.com/samber/mo#Result.FlatMap) - [play](https://go.dev/play/p/Ud5QjZOqg-7)
Other:
- `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold)
- `mo.Do[T any](fn func() T) (result mo.Result[T])` [doc](https://pkg.go.dev/github.com/samber/mo#Do)
Sub-package `result` (transformations and pipes):
- `result.Map()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#Map)
- `result.FlatMap()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#FlatMap)
- `result.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#Match)
- `result.FlatMatch()()` [doc](https://pkg.go.dev/github.com/samber/mo/result#FlatMatch)
- `result.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/result#Pipe1)
### Either[L any, R any]
`Either` represents a value of 2 possible types. An instance of `Either` is an instance of either `A` or `B`.
Implements:
- `mo.Foldable[T, U]`
Constructors:
- `mo.Left()` [doc](https://pkg.go.dev/github.com/samber/mo#Left)
- `mo.Right()` [doc](https://pkg.go.dev/github.com/samber/mo#Right)
Methods:
- `.IsLeft()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.IsLeft)
- `.IsRight()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.IsRight)
- `.Left()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Left)
- `.Right()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Right)
- `.MustLeft()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MustLeft)
- `.MustRight()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MustRight)
- `.Unpack()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Unpack)
- `.LeftOrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.LeftOrElse)
- `.RightOrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.RightOrElse)
- `.LeftOrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.LeftOrEmpty)
- `.RightOrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.RightOrEmpty)
- `.Swap()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Swap)
- `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.ForEach)
- `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.Match)
- `.MapLeft()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MapLeft)
- `.MapRight()` [doc](https://pkg.go.dev/github.com/samber/mo#Either.MapRight)
Other:
- `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold)
Sub-package `either` (transformations and pipes):
- `either.MapLeft()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#MapLeft)
- `either.MapRight()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#MapRight)
- `either.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#Match)
- `either.Swap()()` [doc](https://pkg.go.dev/github.com/samber/mo/either#Swap)
- `either.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either#Pipe1)
### EitherX[T1, ..., TX] (With X between 3 and 5)
`EitherX` respresents a value of X possible types. For example, an `Either3` value is either `T1`, `T2` or `T3`.
Constructors:
- `mo.NewEitherXArgY()` [doc](https://pkg.go.dev/github.com/samber/mo#NewEither5Arg1). Eg:
- `mo.NewEither3Arg1[A, B, C](A)`
- `mo.NewEither3Arg2[A, B, C](B)`
- `mo.NewEither3Arg3[A, B, C](C)`
- `mo.NewEither4Arg1[A, B, C, D](A)`
- `mo.NewEither4Arg2[A, B, C, D](B)`
- ...
Methods:
- `.IsArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.IsArg1)
- `.ArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Arg1)
- `.MustArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.MustArg1)
- `.Unpack()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Unpack)
- `.ArgXOrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Arg1OrElse)
- `.ArgXOrEmpty()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Arg1OrEmpty)
- `.ForEach()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.ForEach)
- `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.Match)
- `.MapArgX()` [doc](https://pkg.go.dev/github.com/samber/mo#Either5.MapArg1)
Sub-packages `either3`, `either4`, `either5` (transformations and pipes):
- either3 docs: https://pkg.go.dev/github.com/samber/mo/either3
- `either3.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#Match)
- `either3.MapArg1()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#MapArg1)
- `either3.MapArg2()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#MapArg2)
- `either3.MapArg3()()` [doc](https://pkg.go.dev/github.com/samber/mo/either3#MapArg3)
- `either3.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either3#Pipe1)
- either4 docs: https://pkg.go.dev/github.com/samber/mo/either4
- `either4.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#Match)
- `either4.MapArg1()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#MapArg1)
- `either4.MapArg2()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#MapArg2)
- `either4.MapArg3()()` [doc](https://pkg.go.dev/github.com/samber/mo/either4#MapArg3)
- `either4.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either4#Pipe1)
- either5 docs: https://pkg.go.dev/github.com/samber/mo/either5
- `either5.Match()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#Match)
- `either5.MapArg1()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#MapArg1)
- `either5.MapArg2()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#MapArg2)
- `either5.MapArg3()()` [doc](https://pkg.go.dev/github.com/samber/mo/either5#MapArg3)
- `either5.Pipe1..Pipe10()` [docs](https://pkg.go.dev/github.com/samber/mo/either5#Pipe1)
### Future[T any]
`Future` represents a value which may or may not currently be available, but will be available at some point, or an exception if that value could not be made available.
Constructors:
- `mo.NewFuture()` [doc](https://pkg.go.dev/github.com/samber/mo#NewFuture)
Methods:
- `.Then()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Then)
- `.Catch()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Catch)
- `.Finally()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Finally)
- `.Collect()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Collect)
- `.Result()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Result)
- `.Cancel()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Cancel)
### IO[T any]
`IO` represents a non-deterministic synchronous computation that can cause side effects, yields a value of type `R` and never fails.
Constructors:
- `mo.NewIO()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO)
- `mo.NewIO1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO1)
- `mo.NewIO2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO2)
- `mo.NewIO3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO3)
- `mo.NewIO4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO4)
- `mo.NewIO5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIO5)
Methods:
- `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#Future.Run)
### IOEither[T any]
`IO` represents a non-deterministic synchronous computation that can cause side effects, yields a value of type `R` and can fail.
Constructors:
- `mo.NewIOEither()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither)
- `mo.NewIOEither1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither1)
- `mo.NewIOEither2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither2)
- `mo.NewIOEither3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither3)
- `mo.NewIOEither4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither4)
- `mo.NewIOEither5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewIOEither5)
Methods:
- `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#IOEither.Run)
### Task[T any]
`Task` represents a non-deterministic asynchronous computation that can cause side effects, yields a value of type `R` and never fails.
Constructors:
- `mo.NewTask()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask)
- `mo.NewTask1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask1)
- `mo.NewTask2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask2)
- `mo.NewTask3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask3)
- `mo.NewTask4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask4)
- `mo.NewTask5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTask5)
- `mo.NewTaskFromIO()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO)
- `mo.NewTaskFromIO1()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO1)
- `mo.NewTaskFromIO2()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO2)
- `mo.NewTaskFromIO3()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO3)
- `mo.NewTaskFromIO4()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO4)
- `mo.NewTaskFromIO5()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskFromIO5)
Methods:
- `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#Task.Run)
### TaskEither[T any]
`TaskEither` represents a non-deterministic asynchronous computation that can cause side effects, yields a value of type `R` and can fail.
Constructors:
- `mo.NewTaskEither()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskEither)
- `mo.NewTaskEitherFromIOEither()` [doc](https://pkg.go.dev/github.com/samber/mo#NewTaskEitherFromIOEither)
Methods:
- `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Run)
- `.OrElse()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.OrElse)
- `.Match()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Match)
- `.TryCatch()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.TryCatch)
- `.ToTask()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.ToTask)
- `.ToEither()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.ToEither)
### State[S any, A any]
`State` represents a function `(S) -> (A, S)`, where `S` is state, `A` is result.
Constructors:
- `mo.NewState()` [doc](https://pkg.go.dev/github.com/samber/mo#NewState)
- `mo.ReturnState()` [doc](https://pkg.go.dev/github.com/samber/mo#ReturnState)
Methods:
- `.Run()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Run)
- `.Get()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Get)
- `.Modify()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Modify)
- `.Put()` [doc](https://pkg.go.dev/github.com/samber/mo#TaskEither.Put)
### Foldable[T, U]
Foldable represents a type that can be folded into a single value based on its state.
- `mo.Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R` [doc](https://pkg.go.dev/github.com/samber/mo#Fold)
## 🛩 Benchmark
// @TODO
This library does not use `reflect` package. We don't expect overhead.
## 🤝 Contributing
- Ping me on Twitter [@samuelberthe](https://twitter.com/samuelberthe) (DMs, mentions, whatever :))
- Fork the [project](https://github.com/samber/mo)
- Fix [open issues](https://github.com/samber/mo/issues) or request new features
Don't hesitate ;)
```bash
# Install some dev dependencies
make tools
# Run tests
make test
# or
make watch-test
```
## 👤 Contributors
![Contributors](https://contrib.rocks/image?repo=samber/mo)
## 💫 Show your support
Give a ⭐️ if this project helped you!
[![GitHub Sponsors](https://img.shields.io/github/sponsors/samber?style=for-the-badge)](https://github.com/sponsors/samber)
## 📝 License
Copyright © 2022 [Samuel Berthe](https://github.com/samber).
This project is [MIT](./LICENSE) licensed.

22
vendor/github.com/samber/mo/do.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
package mo
import (
"errors"
"fmt"
)
// Do executes a function within a monadic context, capturing any errors that occur.
// If the function executes successfully, its result is wrapped in a successful Result.
// If the function panics (indicating a failure), the panic is caught and converted into an error Result.
func Do[T any](fn func() T) (result Result[T]) {
defer func() {
if r := recover(); r != nil {
if err, ok := r.(error); ok {
result = Err[T](err)
} else {
result = Err[T](errors.New(fmt.Sprint(r)))
}
}
}()
return Ok(fn())
}

189
vendor/github.com/samber/mo/either.go generated vendored Normal file
View file

@ -0,0 +1,189 @@
package mo
import "fmt"
var errEitherShouldBeLeftOrRight = fmt.Errorf("either should be Left or Right")
var errEitherMissingLeftValue = fmt.Errorf("no such Left value")
var errEitherMissingRightValue = fmt.Errorf("no such Right value")
// Left builds the left side of the Either struct, as opposed to the Right side.
func Left[L any, R any](value L) Either[L, R] {
return Either[L, R]{
isLeft: true,
left: value,
}
}
// Right builds the right side of the Either struct, as opposed to the Left side.
func Right[L any, R any](value R) Either[L, R] {
return Either[L, R]{
isLeft: false,
right: value,
}
}
// Either respresents a value of 2 possible types.
// An instance of Either is an instance of either A or B.
type Either[L any, R any] struct {
isLeft bool
left L
right R
}
// IsLeft returns true if Either is an instance of Left.
func (e Either[L, R]) IsLeft() bool {
return e.isLeft
}
// IsRight returns true if Either is an instance of Right.
func (e Either[L, R]) IsRight() bool {
return !e.isLeft
}
// Left returns left value of a Either struct.
func (e Either[L, R]) Left() (L, bool) {
if e.IsLeft() {
return e.left, true
}
return empty[L](), false
}
// Right returns right value of a Either struct.
func (e Either[L, R]) Right() (R, bool) {
if e.IsRight() {
return e.right, true
}
return empty[R](), false
}
// MustLeft returns left value of a Either struct or panics.
func (e Either[L, R]) MustLeft() L {
if !e.IsLeft() {
panic(errEitherMissingLeftValue)
}
return e.left
}
// MustRight returns right value of a Either struct or panics.
func (e Either[L, R]) MustRight() R {
if !e.IsRight() {
panic(errEitherMissingRightValue)
}
return e.right
}
// Unpack returns all values
func (e Either[L, R]) Unpack() (L, R) {
return e.left, e.right
}
// LeftOrElse returns left value of a Either struct or fallback.
func (e Either[L, R]) LeftOrElse(fallback L) L {
if e.IsLeft() {
return e.left
}
return fallback
}
// RightOrElse returns right value of a Either struct or fallback.
func (e Either[L, R]) RightOrElse(fallback R) R {
if e.IsRight() {
return e.right
}
return fallback
}
// LeftOrEmpty returns left value of a Either struct or empty value.
func (e Either[L, R]) LeftOrEmpty() L {
if e.IsLeft() {
return e.left
}
return empty[L]()
}
// RightOrEmpty returns right value of a Either struct or empty value.
func (e Either[L, R]) RightOrEmpty() R {
if e.IsRight() {
return e.right
}
return empty[R]()
}
// Swap returns the left value in Right and vice versa.
func (e Either[L, R]) Swap() Either[R, L] {
if e.IsLeft() {
return Right[R](e.left)
}
return Left[R, L](e.right)
}
// ForEach executes the given side-effecting function, depending of value is Left or Right.
func (e Either[L, R]) ForEach(leftCb func(L), rightCb func(R)) {
if e.IsLeft() {
leftCb(e.left)
} else if e.IsRight() {
rightCb(e.right)
}
}
// Match executes the given function, depending of value is Left or Right, and returns result.
func (e Either[L, R]) Match(onLeft func(L) Either[L, R], onRight func(R) Either[L, R]) Either[L, R] {
if e.IsLeft() {
return onLeft(e.left)
} else if e.IsRight() {
return onRight(e.right)
}
panic(errEitherShouldBeLeftOrRight)
}
// MapLeft executes the given function, if Either is of type Left, and returns result.
func (e Either[L, R]) MapLeft(mapper func(L) Either[L, R]) Either[L, R] {
if e.IsLeft() {
return mapper(e.left)
} else if e.IsRight() {
return Right[L, R](e.right)
}
panic(errEitherShouldBeLeftOrRight)
}
// MapRight executes the given function, if Either is of type Right, and returns result.
func (e Either[L, R]) MapRight(mapper func(R) Either[L, R]) Either[L, R] {
if e.isLeft {
return Left[L, R](e.left)
} else if e.IsRight() {
return mapper(e.right)
}
panic(errEitherShouldBeLeftOrRight)
}
// leftValue returns left value of a Either struct.(implementation of Foldable interface)
//
//nolint:unused
func (e Either[L, R]) leftValue() L {
return e.left
}
// rightValue returns right value of a Either struct.(implementation of Foldable interface)
//
//nolint:unused
func (e Either[L, R]) rightValue() R {
return e.right
}
// hasLeft returns true if the Result represents an error state.
//
//nolint:unused
func (e Either[L, R]) hasLeftValue() bool {
return e.isLeft
}

223
vendor/github.com/samber/mo/either3.go generated vendored Normal file
View file

@ -0,0 +1,223 @@
package mo
import "fmt"
const (
either3ArgId1 = iota
either3ArgId2
either3ArgId3
)
var (
errEither3InvalidArgumentId = fmt.Errorf("either3 argument should be between 1 and 3")
errEither3MissingArg1 = fmt.Errorf("either3 doesn't contain expected argument 1")
errEither3MissingArg2 = fmt.Errorf("either3 doesn't contain expected argument 2")
errEither3MissingArg3 = fmt.Errorf("either3 doesn't contain expected argument 3")
)
// NewEither3Arg1 builds the first argument of the Either3 struct.
func NewEither3Arg1[T1 any, T2 any, T3 any](value T1) Either3[T1, T2, T3] {
return Either3[T1, T2, T3]{
argId: either3ArgId1,
arg1: value,
}
}
// NewEither3Arg2 builds the second argument of the Either3 struct.
func NewEither3Arg2[T1 any, T2 any, T3 any](value T2) Either3[T1, T2, T3] {
return Either3[T1, T2, T3]{
argId: either3ArgId2,
arg2: value,
}
}
// NewEither3Arg3 builds the third argument of the Either3 struct.
func NewEither3Arg3[T1 any, T2 any, T3 any](value T3) Either3[T1, T2, T3] {
return Either3[T1, T2, T3]{
argId: either3ArgId3,
arg3: value,
}
}
// Either3 represents a value of 3 possible types.
// An instance of Either3 is an instance of either T1, T2 or T3.
type Either3[T1 any, T2 any, T3 any] struct {
argId int8
arg1 T1
arg2 T2
arg3 T3
}
// IsArg1 returns true if Either3 uses the first argument.
func (e Either3[T1, T2, T3]) IsArg1() bool {
return e.argId == either3ArgId1
}
// IsArg2 returns true if Either3 uses the second argument.
func (e Either3[T1, T2, T3]) IsArg2() bool {
return e.argId == either3ArgId2
}
// IsArg3 returns true if Either3 uses the third argument.
func (e Either3[T1, T2, T3]) IsArg3() bool {
return e.argId == either3ArgId3
}
// Arg1 returns the first argument of a Either3 struct.
func (e Either3[T1, T2, T3]) Arg1() (T1, bool) {
if e.IsArg1() {
return e.arg1, true
}
return empty[T1](), false
}
// Arg2 returns the second argument of a Either3 struct.
func (e Either3[T1, T2, T3]) Arg2() (T2, bool) {
if e.IsArg2() {
return e.arg2, true
}
return empty[T2](), false
}
// Arg3 returns the third argument of a Either3 struct.
func (e Either3[T1, T2, T3]) Arg3() (T3, bool) {
if e.IsArg3() {
return e.arg3, true
}
return empty[T3](), false
}
// MustArg1 returns the first argument of a Either3 struct or panics.
func (e Either3[T1, T2, T3]) MustArg1() T1 {
if !e.IsArg1() {
panic(errEither3MissingArg1)
}
return e.arg1
}
// MustArg2 returns the second argument of a Either3 struct or panics.
func (e Either3[T1, T2, T3]) MustArg2() T2 {
if !e.IsArg2() {
panic(errEither3MissingArg2)
}
return e.arg2
}
// MustArg3 returns the third argument of a Either3 struct or panics.
func (e Either3[T1, T2, T3]) MustArg3() T3 {
if !e.IsArg3() {
panic(errEither3MissingArg3)
}
return e.arg3
}
// Unpack returns all values
func (e Either3[T1, T2, T3]) Unpack() (T1, T2, T3) {
return e.arg1, e.arg2, e.arg3
}
// Arg1OrElse returns the first argument of a Either3 struct or fallback.
func (e Either3[T1, T2, T3]) Arg1OrElse(fallback T1) T1 {
if e.IsArg1() {
return e.arg1
}
return fallback
}
// Arg2OrElse returns the second argument of a Either3 struct or fallback.
func (e Either3[T1, T2, T3]) Arg2OrElse(fallback T2) T2 {
if e.IsArg2() {
return e.arg2
}
return fallback
}
// Arg3OrElse returns the third argument of a Either3 struct or fallback.
func (e Either3[T1, T2, T3]) Arg3OrElse(fallback T3) T3 {
if e.IsArg3() {
return e.arg3
}
return fallback
}
// Arg1OrEmpty returns the first argument of a Either3 struct or empty value.
func (e Either3[T1, T2, T3]) Arg1OrEmpty() T1 {
if e.IsArg1() {
return e.arg1
}
return empty[T1]()
}
// Arg2OrEmpty returns the second argument of a Either3 struct or empty value.
func (e Either3[T1, T2, T3]) Arg2OrEmpty() T2 {
if e.IsArg2() {
return e.arg2
}
return empty[T2]()
}
// Arg3OrEmpty returns the third argument of a Either3 struct or empty value.
func (e Either3[T1, T2, T3]) Arg3OrEmpty() T3 {
if e.IsArg3() {
return e.arg3
}
return empty[T3]()
}
// ForEach executes the given side-effecting function, depending of the argument set.
func (e Either3[T1, T2, T3]) ForEach(arg1Cb func(T1), arg2Cb func(T2), arg3Cb func(T3)) {
switch e.argId {
case either3ArgId1:
arg1Cb(e.arg1)
case either3ArgId2:
arg2Cb(e.arg2)
case either3ArgId3:
arg3Cb(e.arg3)
}
}
// Match executes the given function, depending of the argument set, and returns result.
func (e Either3[T1, T2, T3]) Match(
onArg1 func(T1) Either3[T1, T2, T3],
onArg2 func(T2) Either3[T1, T2, T3],
onArg3 func(T3) Either3[T1, T2, T3]) Either3[T1, T2, T3] {
switch e.argId {
case either3ArgId1:
return onArg1(e.arg1)
case either3ArgId2:
return onArg2(e.arg2)
case either3ArgId3:
return onArg3(e.arg3)
}
panic(errEither3InvalidArgumentId)
}
// MapArg1 executes the given function, if Either3 use the first argument, and returns result.
func (e Either3[T1, T2, T3]) MapArg1(mapper func(T1) Either3[T1, T2, T3]) Either3[T1, T2, T3] {
if e.IsArg1() {
return mapper(e.arg1)
}
return e
}
// MapArg2 executes the given function, if Either3 use the second argument, and returns result.
func (e Either3[T1, T2, T3]) MapArg2(mapper func(T2) Either3[T1, T2, T3]) Either3[T1, T2, T3] {
if e.IsArg2() {
return mapper(e.arg2)
}
return e
}
// MapArg3 executes the given function, if Either3 use the third argument, and returns result.
func (e Either3[T1, T2, T3]) MapArg3(mapper func(T3) Either3[T1, T2, T3]) Either3[T1, T2, T3] {
if e.IsArg3() {
return mapper(e.arg3)
}
return e
}

285
vendor/github.com/samber/mo/either4.go generated vendored Normal file
View file

@ -0,0 +1,285 @@
package mo
import "fmt"
const (
either4ArgId1 = iota
either4ArgId2
either4ArgId3
either4ArgId4
)
var (
errEither4InvalidArgumentId = fmt.Errorf("either4 argument should be between 1 and 4")
errEither4MissingArg1 = fmt.Errorf("either4 doesn't contain expected argument 1")
errEither4MissingArg2 = fmt.Errorf("either4 doesn't contain expected argument 2")
errEither4MissingArg3 = fmt.Errorf("either4 doesn't contain expected argument 3")
errEither4MissingArg4 = fmt.Errorf("either4 doesn't contain expected argument 4")
)
// NewEither4Arg1 builds the first argument of the Either4 struct.
func NewEither4Arg1[T1 any, T2 any, T3 any, T4 any](value T1) Either4[T1, T2, T3, T4] {
return Either4[T1, T2, T3, T4]{
argId: either4ArgId1,
arg1: value,
}
}
// NewEither4Arg2 builds the second argument of the Either4 struct.
func NewEither4Arg2[T1 any, T2 any, T3 any, T4 any](value T2) Either4[T1, T2, T3, T4] {
return Either4[T1, T2, T3, T4]{
argId: either4ArgId2,
arg2: value,
}
}
// NewEither4Arg3 builds the third argument of the Either4 struct.
func NewEither4Arg3[T1 any, T2 any, T3 any, T4 any](value T3) Either4[T1, T2, T3, T4] {
return Either4[T1, T2, T3, T4]{
argId: either4ArgId3,
arg3: value,
}
}
// NewEither4Arg4 builds the fourth argument of the Either4 struct.
func NewEither4Arg4[T1 any, T2 any, T3 any, T4 any](value T4) Either4[T1, T2, T3, T4] {
return Either4[T1, T2, T3, T4]{
argId: either4ArgId4,
arg4: value,
}
}
// Either4 respresents a value of 4 possible types.
// An instance of Either4 is an instance of either T1, T2, T3 or T4.
type Either4[T1 any, T2 any, T3 any, T4 any] struct {
argId int8
arg1 T1
arg2 T2
arg3 T3
arg4 T4
}
// IsArg1 returns true if Either4 uses the first argument.
func (e Either4[T1, T2, T3, T4]) IsArg1() bool {
return e.argId == either4ArgId1
}
// IsArg2 returns true if Either4 uses the second argument.
func (e Either4[T1, T2, T3, T4]) IsArg2() bool {
return e.argId == either4ArgId2
}
// IsArg3 returns true if Either4 uses the third argument.
func (e Either4[T1, T2, T3, T4]) IsArg3() bool {
return e.argId == either4ArgId3
}
// IsArg4 returns true if Either4 uses the fourth argument.
func (e Either4[T1, T2, T3, T4]) IsArg4() bool {
return e.argId == either4ArgId4
}
// Arg1 returns the first argument of a Either4 struct.
func (e Either4[T1, T2, T3, T4]) Arg1() (T1, bool) {
if e.IsArg1() {
return e.arg1, true
}
return empty[T1](), false
}
// Arg2 returns the second argument of a Either4 struct.
func (e Either4[T1, T2, T3, T4]) Arg2() (T2, bool) {
if e.IsArg2() {
return e.arg2, true
}
return empty[T2](), false
}
// Arg3 returns the third argument of a Either4 struct.
func (e Either4[T1, T2, T3, T4]) Arg3() (T3, bool) {
if e.IsArg3() {
return e.arg3, true
}
return empty[T3](), false
}
// Arg4 returns the fourth argument of a Either4 struct.
func (e Either4[T1, T2, T3, T4]) Arg4() (T4, bool) {
if e.IsArg4() {
return e.arg4, true
}
return empty[T4](), false
}
// MustArg1 returns the first argument of a Either4 struct or panics.
func (e Either4[T1, T2, T3, T4]) MustArg1() T1 {
if !e.IsArg1() {
panic(errEither4MissingArg1)
}
return e.arg1
}
// MustArg2 returns the second argument of a Either4 struct or panics.
func (e Either4[T1, T2, T3, T4]) MustArg2() T2 {
if !e.IsArg2() {
panic(errEither4MissingArg2)
}
return e.arg2
}
// MustArg3 returns the third argument of a Either4 struct or panics.
func (e Either4[T1, T2, T3, T4]) MustArg3() T3 {
if !e.IsArg3() {
panic(errEither4MissingArg3)
}
return e.arg3
}
// MustArg4 returns the fourth argument of a Either4 struct or panics.
func (e Either4[T1, T2, T3, T4]) MustArg4() T4 {
if !e.IsArg4() {
panic(errEither4MissingArg4)
}
return e.arg4
}
// Unpack returns all values
func (e Either4[T1, T2, T3, T4]) Unpack() (T1, T2, T3, T4) {
return e.arg1, e.arg2, e.arg3, e.arg4
}
// Arg1OrElse returns the first argument of a Either4 struct or fallback.
func (e Either4[T1, T2, T3, T4]) Arg1OrElse(fallback T1) T1 {
if e.IsArg1() {
return e.arg1
}
return fallback
}
// Arg2OrElse returns the second argument of a Either4 struct or fallback.
func (e Either4[T1, T2, T3, T4]) Arg2OrElse(fallback T2) T2 {
if e.IsArg2() {
return e.arg2
}
return fallback
}
// Arg3OrElse returns the third argument of a Either4 struct or fallback.
func (e Either4[T1, T2, T3, T4]) Arg3OrElse(fallback T3) T3 {
if e.IsArg3() {
return e.arg3
}
return fallback
}
// Arg4OrElse returns the fourth argument of a Either4 struct or fallback.
func (e Either4[T1, T2, T3, T4]) Arg4OrElse(fallback T4) T4 {
if e.IsArg4() {
return e.arg4
}
return fallback
}
// Arg1OrEmpty returns the first argument of a Either4 struct or empty value.
func (e Either4[T1, T2, T3, T4]) Arg1OrEmpty() T1 {
if e.IsArg1() {
return e.arg1
}
return empty[T1]()
}
// Arg2OrEmpty returns the second argument of a Either4 struct or empty value.
func (e Either4[T1, T2, T3, T4]) Arg2OrEmpty() T2 {
if e.IsArg2() {
return e.arg2
}
return empty[T2]()
}
// Arg3OrEmpty returns the third argument of a Either4 struct or empty value.
func (e Either4[T1, T2, T3, T4]) Arg3OrEmpty() T3 {
if e.IsArg3() {
return e.arg3
}
return empty[T3]()
}
// Arg4OrEmpty returns the fourth argument of a Either4 struct or empty value.
func (e Either4[T1, T2, T3, T4]) Arg4OrEmpty() T4 {
if e.IsArg4() {
return e.arg4
}
return empty[T4]()
}
// ForEach executes the given side-effecting function, depending of the argument set.
func (e Either4[T1, T2, T3, T4]) ForEach(arg1Cb func(T1), arg2Cb func(T2), arg3Cb func(T3), arg4Cb func(T4)) {
switch e.argId {
case either4ArgId1:
arg1Cb(e.arg1)
case either4ArgId2:
arg2Cb(e.arg2)
case either4ArgId3:
arg3Cb(e.arg3)
case either4ArgId4:
arg4Cb(e.arg4)
}
}
// Match executes the given function, depending of the argument set, and returns result.
func (e Either4[T1, T2, T3, T4]) Match(
onArg1 func(T1) Either4[T1, T2, T3, T4],
onArg2 func(T2) Either4[T1, T2, T3, T4],
onArg3 func(T3) Either4[T1, T2, T3, T4],
onArg4 func(T4) Either4[T1, T2, T3, T4]) Either4[T1, T2, T3, T4] {
switch e.argId {
case either4ArgId1:
return onArg1(e.arg1)
case either4ArgId2:
return onArg2(e.arg2)
case either4ArgId3:
return onArg3(e.arg3)
case either4ArgId4:
return onArg4(e.arg4)
}
panic(errEither4InvalidArgumentId)
}
// MapArg1 executes the given function, if Either4 use the first argument, and returns result.
func (e Either4[T1, T2, T3, T4]) MapArg1(mapper func(T1) Either4[T1, T2, T3, T4]) Either4[T1, T2, T3, T4] {
if e.IsArg1() {
return mapper(e.arg1)
}
return e
}
// MapArg2 executes the given function, if Either4 use the second argument, and returns result.
func (e Either4[T1, T2, T3, T4]) MapArg2(mapper func(T2) Either4[T1, T2, T3, T4]) Either4[T1, T2, T3, T4] {
if e.IsArg2() {
return mapper(e.arg2)
}
return e
}
// MapArg3 executes the given function, if Either4 use the third argument, and returns result.
func (e Either4[T1, T2, T3, T4]) MapArg3(mapper func(T3) Either4[T1, T2, T3, T4]) Either4[T1, T2, T3, T4] {
if e.IsArg3() {
return mapper(e.arg3)
}
return e
}
// MapArg4 executes the given function, if Either4 use the fourth argument, and returns result.
func (e Either4[T1, T2, T3, T4]) MapArg4(mapper func(T4) Either4[T1, T2, T3, T4]) Either4[T1, T2, T3, T4] {
if e.IsArg4() {
return mapper(e.arg4)
}
return e
}

347
vendor/github.com/samber/mo/either5.go generated vendored Normal file
View file

@ -0,0 +1,347 @@
package mo
import "fmt"
const (
either5ArgId1 = iota
either5ArgId2
either5ArgId3
either5ArgId4
either5ArgId5
)
var (
errEither5InvalidArgumentId = fmt.Errorf("either5 argument should be between 1 and 5")
errEither5MissingArg1 = fmt.Errorf("either5 doesn't contain expected argument 1")
errEither5MissingArg2 = fmt.Errorf("either5 doesn't contain expected argument 2")
errEither5MissingArg3 = fmt.Errorf("either5 doesn't contain expected argument 3")
errEither5MissingArg4 = fmt.Errorf("either5 doesn't contain expected argument 4")
errEither5MissingArg5 = fmt.Errorf("either5 doesn't contain expected argument 5")
)
// NewEither5Arg1 builds the first argument of the Either5 struct.
func NewEither5Arg1[T1 any, T2 any, T3 any, T4 any, T5 any](value T1) Either5[T1, T2, T3, T4, T5] {
return Either5[T1, T2, T3, T4, T5]{
argId: either5ArgId1,
arg1: value,
}
}
// NewEither5Arg2 builds the second argument of the Either5 struct.
func NewEither5Arg2[T1 any, T2 any, T3 any, T4 any, T5 any](value T2) Either5[T1, T2, T3, T4, T5] {
return Either5[T1, T2, T3, T4, T5]{
argId: either5ArgId2,
arg2: value,
}
}
// NewEither5Arg3 builds the third argument of the Either5 struct.
func NewEither5Arg3[T1 any, T2 any, T3 any, T4 any, T5 any](value T3) Either5[T1, T2, T3, T4, T5] {
return Either5[T1, T2, T3, T4, T5]{
argId: either5ArgId3,
arg3: value,
}
}
// NewEither5Arg4 builds the fourth argument of the Either5 struct.
func NewEither5Arg4[T1 any, T2 any, T3 any, T4 any, T5 any](value T4) Either5[T1, T2, T3, T4, T5] {
return Either5[T1, T2, T3, T4, T5]{
argId: either5ArgId4,
arg4: value,
}
}
// NewEither5Arg5 builds the fith argument of the Either5 struct.
func NewEither5Arg5[T1 any, T2 any, T3 any, T4 any, T5 any](value T5) Either5[T1, T2, T3, T4, T5] {
return Either5[T1, T2, T3, T4, T5]{
argId: either5ArgId5,
arg5: value,
}
}
// Either5 respresents a value of 5 possible types.
// An instance of Either5 is an instance of either T1, T2, T3, T4, or T5.
type Either5[T1 any, T2 any, T3 any, T4 any, T5 any] struct {
argId int8
arg1 T1
arg2 T2
arg3 T3
arg4 T4
arg5 T5
}
// IsArg1 returns true if Either5 uses the first argument.
func (e Either5[T1, T2, T3, T4, T5]) IsArg1() bool {
return e.argId == either5ArgId1
}
// IsArg2 returns true if Either5 uses the second argument.
func (e Either5[T1, T2, T3, T4, T5]) IsArg2() bool {
return e.argId == either5ArgId2
}
// IsArg3 returns true if Either5 uses the third argument.
func (e Either5[T1, T2, T3, T4, T5]) IsArg3() bool {
return e.argId == either5ArgId3
}
// IsArg4 returns true if Either5 uses the fourth argument.
func (e Either5[T1, T2, T3, T4, T5]) IsArg4() bool {
return e.argId == either5ArgId4
}
// IsArg5 returns true if Either5 uses the fith argument.
func (e Either5[T1, T2, T3, T4, T5]) IsArg5() bool {
return e.argId == either5ArgId5
}
// Arg1 returns the first argument of a Either5 struct.
func (e Either5[T1, T2, T3, T4, T5]) Arg1() (T1, bool) {
if e.IsArg1() {
return e.arg1, true
}
return empty[T1](), false
}
// Arg2 returns the second argument of a Either5 struct.
func (e Either5[T1, T2, T3, T4, T5]) Arg2() (T2, bool) {
if e.IsArg2() {
return e.arg2, true
}
return empty[T2](), false
}
// Arg3 returns the third argument of a Either5 struct.
func (e Either5[T1, T2, T3, T4, T5]) Arg3() (T3, bool) {
if e.IsArg3() {
return e.arg3, true
}
return empty[T3](), false
}
// Arg4 returns the fourth argument of a Either5 struct.
func (e Either5[T1, T2, T3, T4, T5]) Arg4() (T4, bool) {
if e.IsArg4() {
return e.arg4, true
}
return empty[T4](), false
}
// Arg5 returns the fith argument of a Either5 struct.
func (e Either5[T1, T2, T3, T4, T5]) Arg5() (T5, bool) {
if e.IsArg5() {
return e.arg5, true
}
return empty[T5](), false
}
// MustArg1 returns the first argument of a Either5 struct or panics.
func (e Either5[T1, T2, T3, T4, T5]) MustArg1() T1 {
if !e.IsArg1() {
panic(errEither5MissingArg1)
}
return e.arg1
}
// MustArg2 returns the second argument of a Either5 struct or panics.
func (e Either5[T1, T2, T3, T4, T5]) MustArg2() T2 {
if !e.IsArg2() {
panic(errEither5MissingArg2)
}
return e.arg2
}
// MustArg3 returns the third argument of a Either5 struct or panics.
func (e Either5[T1, T2, T3, T4, T5]) MustArg3() T3 {
if !e.IsArg3() {
panic(errEither5MissingArg3)
}
return e.arg3
}
// MustArg4 returns the fourth argument of a Either5 struct or panics.
func (e Either5[T1, T2, T3, T4, T5]) MustArg4() T4 {
if !e.IsArg4() {
panic(errEither5MissingArg4)
}
return e.arg4
}
// MustArg5 returns the fith argument of a Either5 struct or panics.
func (e Either5[T1, T2, T3, T4, T5]) MustArg5() T5 {
if !e.IsArg5() {
panic(errEither5MissingArg5)
}
return e.arg5
}
// Unpack returns all values
func (e Either5[T1, T2, T3, T4, T5]) Unpack() (T1, T2, T3, T4, T5) {
return e.arg1, e.arg2, e.arg3, e.arg4, e.arg5
}
// Arg1OrElse returns the first argument of a Either5 struct or fallback.
func (e Either5[T1, T2, T3, T4, T5]) Arg1OrElse(fallback T1) T1 {
if e.IsArg1() {
return e.arg1
}
return fallback
}
// Arg2OrElse returns the second argument of a Either5 struct or fallback.
func (e Either5[T1, T2, T3, T4, T5]) Arg2OrElse(fallback T2) T2 {
if e.IsArg2() {
return e.arg2
}
return fallback
}
// Arg3OrElse returns the third argument of a Either5 struct or fallback.
func (e Either5[T1, T2, T3, T4, T5]) Arg3OrElse(fallback T3) T3 {
if e.IsArg3() {
return e.arg3
}
return fallback
}
// Arg4OrElse returns the fourth argument of a Either5 struct or fallback.
func (e Either5[T1, T2, T3, T4, T5]) Arg4OrElse(fallback T4) T4 {
if e.IsArg4() {
return e.arg4
}
return fallback
}
// Arg5OrElse returns the fith argument of a Either5 struct or fallback.
func (e Either5[T1, T2, T3, T4, T5]) Arg5OrElse(fallback T5) T5 {
if e.IsArg5() {
return e.arg5
}
return fallback
}
// Arg1OrEmpty returns the first argument of a Either5 struct or empty value.
func (e Either5[T1, T2, T3, T4, T5]) Arg1OrEmpty() T1 {
if e.IsArg1() {
return e.arg1
}
return empty[T1]()
}
// Arg2OrEmpty returns the second argument of a Either5 struct or empty value.
func (e Either5[T1, T2, T3, T4, T5]) Arg2OrEmpty() T2 {
if e.IsArg2() {
return e.arg2
}
return empty[T2]()
}
// Arg3OrEmpty returns the third argument of a Either5 struct or empty value.
func (e Either5[T1, T2, T3, T4, T5]) Arg3OrEmpty() T3 {
if e.IsArg3() {
return e.arg3
}
return empty[T3]()
}
// Arg4OrEmpty returns the fourth argument of a Either5 struct or empty value.
func (e Either5[T1, T2, T3, T4, T5]) Arg4OrEmpty() T4 {
if e.IsArg4() {
return e.arg4
}
return empty[T4]()
}
// Arg5OrEmpty returns the fifth argument of a Either5 struct or empty value.
func (e Either5[T1, T2, T3, T4, T5]) Arg5OrEmpty() T5 {
if e.IsArg5() {
return e.arg5
}
return empty[T5]()
}
// ForEach executes the given side-effecting function, depending of the argument set.
func (e Either5[T1, T2, T3, T4, T5]) ForEach(arg1Cb func(T1), arg2Cb func(T2), arg3Cb func(T3), arg4Cb func(T4), arg5Cb func(T5)) {
switch e.argId {
case either5ArgId1:
arg1Cb(e.arg1)
case either5ArgId2:
arg2Cb(e.arg2)
case either5ArgId3:
arg3Cb(e.arg3)
case either5ArgId4:
arg4Cb(e.arg4)
case either5ArgId5:
arg5Cb(e.arg5)
}
}
// Match executes the given function, depending of the argument set, and returns result.
func (e Either5[T1, T2, T3, T4, T5]) Match(
onArg1 func(T1) Either5[T1, T2, T3, T4, T5],
onArg2 func(T2) Either5[T1, T2, T3, T4, T5],
onArg3 func(T3) Either5[T1, T2, T3, T4, T5],
onArg4 func(T4) Either5[T1, T2, T3, T4, T5],
onArg5 func(T5) Either5[T1, T2, T3, T4, T5]) Either5[T1, T2, T3, T4, T5] {
switch e.argId {
case either5ArgId1:
return onArg1(e.arg1)
case either5ArgId2:
return onArg2(e.arg2)
case either5ArgId3:
return onArg3(e.arg3)
case either5ArgId4:
return onArg4(e.arg4)
case either5ArgId5:
return onArg5(e.arg5)
}
panic(errEither5InvalidArgumentId)
}
// MapArg1 executes the given function, if Either5 use the first argument, and returns result.
func (e Either5[T1, T2, T3, T4, T5]) MapArg1(mapper func(T1) Either5[T1, T2, T3, T4, T5]) Either5[T1, T2, T3, T4, T5] {
if e.IsArg1() {
return mapper(e.arg1)
}
return e
}
// MapArg2 executes the given function, if Either5 use the second argument, and returns result.
func (e Either5[T1, T2, T3, T4, T5]) MapArg2(mapper func(T2) Either5[T1, T2, T3, T4, T5]) Either5[T1, T2, T3, T4, T5] {
if e.IsArg2() {
return mapper(e.arg2)
}
return e
}
// MapArg3 executes the given function, if Either5 use the third argument, and returns result.
func (e Either5[T1, T2, T3, T4, T5]) MapArg3(mapper func(T3) Either5[T1, T2, T3, T4, T5]) Either5[T1, T2, T3, T4, T5] {
if e.IsArg3() {
return mapper(e.arg3)
}
return e
}
// MapArg4 executes the given function, if Either5 use the fourth argument, and returns result.
func (e Either5[T1, T2, T3, T4, T5]) MapArg4(mapper func(T4) Either5[T1, T2, T3, T4, T5]) Either5[T1, T2, T3, T4, T5] {
if e.IsArg4() {
return mapper(e.arg4)
}
return e
}
// MapArg5 executes the given function, if Either5 use the fith argument, and returns result.
func (e Either5[T1, T2, T3, T4, T5]) MapArg5(mapper func(T5) Either5[T1, T2, T3, T4, T5]) Either5[T1, T2, T3, T4, T5] {
if e.IsArg5() {
return mapper(e.arg5)
}
return e
}

28
vendor/github.com/samber/mo/fold.go generated vendored Normal file
View file

@ -0,0 +1,28 @@
package mo
// Foldable represents a type that can be folded into a single value
// based on its state.
//
// - T: the type of the value in the failure state (e.g., an error type).
// - U: the type of the value in the success state.
type Foldable[T any, U any] interface {
leftValue() T
rightValue() U
hasLeftValue() bool
}
// Fold applies one of the two functions based on the state of the Foldable type,
// and it returns the result of applying either successFunc or failureFunc.
//
// - T: the type of the failure value (e.g., an error type)
// - U: the type of the success value
// - R: the type of the return value from the folding functions
//
// successFunc is applied when the Foldable is in the success state (i.e., isLeft() is false).
// failureFunc is applied when the Foldable is in the failure state (i.e., isLeft() is true).
func Fold[T, U, R any](f Foldable[T, U], successFunc func(U) R, failureFunc func(T) R) R {
if f.hasLeftValue() {
return failureFunc(f.leftValue())
}
return successFunc(f.rightValue())
}

197
vendor/github.com/samber/mo/future.go generated vendored Normal file
View file

@ -0,0 +1,197 @@
package mo
import (
"sync"
)
// NewFuture instanciate a new future.
func NewFuture[T any](cb func(resolve func(T), reject func(error))) *Future[T] {
future := Future[T]{
cb: cb,
cancelCb: func() {},
done: make(chan struct{}),
}
future.active()
return &future
}
// Future represents a value which may or may not currently be available, but will be
// available at some point, or an exception if that value could not be made available.
type Future[T any] struct {
mu sync.Mutex
cb func(func(T), func(error))
cancelCb func()
next *Future[T]
done chan struct{}
doneOnce sync.Once
result Result[T]
}
func (f *Future[T]) active() {
go f.cb(f.resolve, f.reject)
}
func (f *Future[T]) activeSync() {
f.cb(f.resolve, f.reject)
}
func (f *Future[T]) resolve(value T) {
f.doneOnce.Do(func() {
f.mu.Lock()
defer f.mu.Unlock()
f.result = Ok(value)
if f.next != nil {
f.next.activeSync()
}
close(f.done)
})
}
func (f *Future[T]) reject(err error) {
f.doneOnce.Do(func() {
f.mu.Lock()
defer f.mu.Unlock()
f.result = Err[T](err)
if f.next != nil {
f.next.activeSync()
}
close(f.done)
})
}
// Then is called when Future is resolved. It returns a new Future.
func (f *Future[T]) Then(cb func(T) (T, error)) *Future[T] {
f.mu.Lock()
next := &Future[T]{
cb: func(resolve func(T), reject func(error)) {
if f.result.IsError() {
reject(f.result.Error())
return
}
newValue, err := cb(f.result.MustGet())
if err != nil {
reject(err)
return
}
resolve(newValue)
},
cancelCb: func() {
f.Cancel()
},
done: make(chan struct{}),
}
f.next = next
select {
case <-f.done:
f.mu.Unlock()
next.active()
default:
f.mu.Unlock()
}
return next
}
// Catch is called when Future is rejected. It returns a new Future.
func (f *Future[T]) Catch(cb func(error) (T, error)) *Future[T] {
f.mu.Lock()
next := &Future[T]{
cb: func(resolve func(T), reject func(error)) {
if f.result.IsOk() {
resolve(f.result.MustGet())
return
}
newValue, err := cb(f.result.Error())
if err != nil {
reject(err)
return
}
resolve(newValue)
},
cancelCb: func() {
f.Cancel()
},
done: make(chan struct{}),
}
f.next = next
select {
case <-f.done:
f.mu.Unlock()
next.active()
default:
f.mu.Unlock()
}
return next
}
// Finally is called when Future is processed either resolved or rejected. It returns a new Future.
func (f *Future[T]) Finally(cb func(T, error) (T, error)) *Future[T] {
f.mu.Lock()
next := &Future[T]{
cb: func(resolve func(T), reject func(error)) {
newValue, err := cb(f.result.Get())
if err != nil {
reject(err)
return
}
resolve(newValue)
},
cancelCb: func() {
f.Cancel()
},
done: make(chan struct{}),
}
f.next = next
select {
case <-f.done:
f.mu.Unlock()
next.active()
default:
f.mu.Unlock()
}
return next
}
// Cancel cancels the Future chain.
func (f *Future[T]) Cancel() {
f.mu.Lock()
defer f.mu.Unlock()
f.next = nil
if f.cancelCb != nil {
f.cancelCb()
}
}
// Collect awaits and return result of the Future.
func (f *Future[T]) Collect() (T, error) {
<-f.done
return f.result.Get()
}
// Result wraps Collect and returns a Result.
func (f *Future[T]) Result() Result[T] {
return TupleToResult(f.Collect())
}
// Either wraps Collect and returns a Either.
func (f *Future[T]) Either() Either[error, T] {
v, err := f.Collect()
if err != nil {
return Left[error, T](err)
}
return Right[error](v)
}

109
vendor/github.com/samber/mo/io.go generated vendored Normal file
View file

@ -0,0 +1,109 @@
package mo
// NewIO instanciates a new IO.
func NewIO[R any](f f0[R]) IO[R] {
return IO[R]{
unsafePerform: f,
}
}
// IO represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type IO[R any] struct {
unsafePerform f0[R]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IO[R]) Run() R {
return io.unsafePerform()
}
// NewIO1 instanciates a new IO1.
func NewIO1[R any, A any](f f1[R, A]) IO1[R, A] {
return IO1[R, A]{
unsafePerform: f,
}
}
// IO1 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type IO1[R any, A any] struct {
unsafePerform f1[R, A]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IO1[R, A]) Run(a A) R {
return io.unsafePerform(a)
}
// NewIO2 instanciates a new IO2.
func NewIO2[R any, A any, B any](f f2[R, A, B]) IO2[R, A, B] {
return IO2[R, A, B]{
unsafePerform: f,
}
}
// IO2 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type IO2[R any, A any, B any] struct {
unsafePerform f2[R, A, B]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IO2[R, A, B]) Run(a A, b B) R {
return io.unsafePerform(a, b)
}
// NewIO3 instanciates a new IO3.
func NewIO3[R any, A any, B any, C any](f f3[R, A, B, C]) IO3[R, A, B, C] {
return IO3[R, A, B, C]{
unsafePerform: f,
}
}
// IO3 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type IO3[R any, A any, B any, C any] struct {
unsafePerform f3[R, A, B, C]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IO3[R, A, B, C]) Run(a A, b B, c C) R {
return io.unsafePerform(a, b, c)
}
// NewIO4 instanciates a new IO4.
func NewIO4[R any, A any, B any, C any, D any](f f4[R, A, B, C, D]) IO4[R, A, B, C, D] {
return IO4[R, A, B, C, D]{
unsafePerform: f,
}
}
// IO4 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type IO4[R any, A any, B any, C any, D any] struct {
unsafePerform f4[R, A, B, C, D]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IO4[R, A, B, C, D]) Run(a A, b B, c C, d D) R {
return io.unsafePerform(a, b, c, d)
}
// NewIO5 instanciates a new IO5.
func NewIO5[R any, A any, B any, C any, D any, E any](f f5[R, A, B, C, D, E]) IO5[R, A, B, C, D, E] {
return IO5[R, A, B, C, D, E]{
unsafePerform: f,
}
}
// IO5 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type IO5[R any, A any, B any, C any, D any, E any] struct {
unsafePerform f5[R, A, B, C, D, E]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IO5[R, A, B, C, D, E]) Run(a A, b B, c C, d D, e E) R {
return io.unsafePerform(a, b, c, d, e)
}

139
vendor/github.com/samber/mo/io_either.go generated vendored Normal file
View file

@ -0,0 +1,139 @@
package mo
// NewIOEither instanciates a new IO.
func NewIOEither[R any](f fe0[R]) IOEither[R] {
return IOEither[R]{
unsafePerform: f,
}
}
// IOEither represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and can fail.
type IOEither[R any] struct {
unsafePerform fe0[R]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IOEither[R]) Run() Either[error, R] {
v, err := io.unsafePerform()
if err != nil {
return Left[error, R](err)
}
return Right[error, R](v)
}
// NewIOEither1 instanciates a new IO1.
func NewIOEither1[R any, A any](f fe1[R, A]) IOEither1[R, A] {
return IOEither1[R, A]{
unsafePerform: f,
}
}
// IOEither1 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and can fail.
type IOEither1[R any, A any] struct {
unsafePerform fe1[R, A]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IOEither1[R, A]) Run(a A) Either[error, R] {
v, err := io.unsafePerform(a)
if err != nil {
return Left[error, R](err)
}
return Right[error, R](v)
}
// NewIOEither2 instanciates a new IO2.
func NewIOEither2[R any, A any, B any](f fe2[R, A, B]) IOEither2[R, A, B] {
return IOEither2[R, A, B]{
unsafePerform: f,
}
}
// IOEither2 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and can fail.
type IOEither2[R any, A any, B any] struct {
unsafePerform fe2[R, A, B]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IOEither2[R, A, B]) Run(a A, b B) Either[error, R] {
v, err := io.unsafePerform(a, b)
if err != nil {
return Left[error, R](err)
}
return Right[error, R](v)
}
// NewIOEither3 instanciates a new IO3.
func NewIOEither3[R any, A any, B any, C any](f fe3[R, A, B, C]) IOEither3[R, A, B, C] {
return IOEither3[R, A, B, C]{
unsafePerform: f,
}
}
// IOEither3 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and can fail.
type IOEither3[R any, A any, B any, C any] struct {
unsafePerform fe3[R, A, B, C]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IOEither3[R, A, B, C]) Run(a A, b B, c C) Either[error, R] {
v, err := io.unsafePerform(a, b, c)
if err != nil {
return Left[error, R](err)
}
return Right[error, R](v)
}
// NewIOEither4 instanciates a new IO4.
func NewIOEither4[R any, A any, B any, C any, D any](f fe4[R, A, B, C, D]) IOEither4[R, A, B, C, D] {
return IOEither4[R, A, B, C, D]{
unsafePerform: f,
}
}
// IOEither4 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and can fail.
type IOEither4[R any, A any, B any, C any, D any] struct {
unsafePerform fe4[R, A, B, C, D]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IOEither4[R, A, B, C, D]) Run(a A, b B, c C, d D) Either[error, R] {
v, err := io.unsafePerform(a, b, c, d)
if err != nil {
return Left[error, R](err)
}
return Right[error, R](v)
}
// NewIOEither5 instanciates a new IO5.
func NewIOEither5[R any, A any, B any, C any, D any, E any](f fe5[R, A, B, C, D, E]) IOEither5[R, A, B, C, D, E] {
return IOEither5[R, A, B, C, D, E]{
unsafePerform: f,
}
}
// IOEither5 represents a non-deterministic synchronous computation that
// can cause side effects, yields a value of type `R` and can fail.
type IOEither5[R any, A any, B any, C any, D any, E any] struct {
unsafePerform fe5[R, A, B, C, D, E]
}
// Run execute the non-deterministic synchronous computation, with side effect.
func (io IOEither5[R, A, B, C, D, E]) Run(a A, b B, c C, d D, e E) Either[error, R] {
v, err := io.unsafePerform(a, b, c, d, e)
if err != nil {
return Left[error, R](err)
}
return Right[error, R](v)
}

399
vendor/github.com/samber/mo/option.go generated vendored Normal file
View file

@ -0,0 +1,399 @@
package mo
import (
"bytes"
"database/sql"
"database/sql/driver"
"encoding/gob"
"encoding/json"
"errors"
"fmt"
"reflect"
)
var errOptionNoSuchElement = fmt.Errorf("no such element")
type zeroer interface {
IsZero() bool
}
// Some builds an Option when value is present.
// Play: https://go.dev/play/p/iqz2n9n0tDM
func Some[T any](value T) Option[T] {
return Option[T]{
isPresent: true,
value: value,
}
}
// None builds an Option when value is absent.
// Play: https://go.dev/play/p/yYQPsYCSYlD
func None[T any]() Option[T] {
return Option[T]{
isPresent: false,
}
}
// TupleToOption builds a Some Option when second argument is true, or None.
// Play: https://go.dev/play/p/gkrg2pZwOty
func TupleToOption[T any](value T, ok bool) Option[T] {
if ok {
return Some(value)
}
return None[T]()
}
// EmptyableToOption builds a Some Option when value is not empty, or None.
// Play: https://go.dev/play/p/GSpQQ-q-UES
func EmptyableToOption[T any](value T) Option[T] {
// 🤮
isZero := reflect.ValueOf(&value).Elem().IsZero()
if isZero {
return None[T]()
}
return Some(value)
}
// PointerToOption builds a Some Option when value is not nil, or None.
// Play: https://go.dev/play/p/yPVMj4DUb-I
func PointerToOption[T any](value *T) Option[T] {
if value == nil {
return None[T]()
}
return Some(*value)
}
// Option is a container for an optional value of type T. If value exists, Option is
// of type Some. If the value is absent, Option is of type None.
type Option[T any] struct {
isPresent bool
value T
}
// IsPresent returns false when value is absent.
// Play: https://go.dev/play/p/nDqIaiihyCA
func (o Option[T]) IsPresent() bool {
return o.isPresent
}
// IsSome is an alias to IsPresent.
// Play: https://go.dev/play/p/DyvGRy7fP9m
func (o Option[T]) IsSome() bool {
return o.IsPresent()
}
// IsAbsent returns false when value is present.
// Play: https://go.dev/play/p/23e2zqyVOQm
func (o Option[T]) IsAbsent() bool {
return !o.isPresent
}
// IsNone is an alias to IsAbsent.
// Play: https://go.dev/play/p/EdqxKhborIP
func (o Option[T]) IsNone() bool {
return o.IsAbsent()
}
// Size returns 1 when value is present or 0 instead.
// Play: https://go.dev/play/p/7ixCNG1E9l7
func (o Option[T]) Size() int {
if o.isPresent {
return 1
}
return 0
}
// Get returns value and presence.
// Play: https://go.dev/play/p/0-JBa1usZRT
func (o Option[T]) Get() (T, bool) {
if !o.isPresent {
return empty[T](), false
}
return o.value, true
}
// MustGet returns value if present or panics instead.
// Play: https://go.dev/play/p/RVBckjdi5WR
func (o Option[T]) MustGet() T {
if !o.isPresent {
panic(errOptionNoSuchElement)
}
return o.value
}
// OrElse returns value if present or default value.
// Play: https://go.dev/play/p/TrGByFWCzXS
func (o Option[T]) OrElse(fallback T) T {
if !o.isPresent {
return fallback
}
return o.value
}
// OrEmpty returns value if present or empty value.
// Play: https://go.dev/play/p/SpSUJcE-tQm
func (o Option[T]) OrEmpty() T {
return o.value
}
// ForEach executes the given side-effecting function of value is present.
func (o Option[T]) ForEach(onValue func(value T)) {
if o.isPresent {
onValue(o.value)
}
}
// Match executes the first function if value is present and second function if absent.
// It returns a new Option.
// Play: https://go.dev/play/p/1V6st3LDJsM
func (o Option[T]) Match(onValue func(value T) (T, bool), onNone func() (T, bool)) Option[T] {
if o.isPresent {
return TupleToOption(onValue(o.value))
}
return TupleToOption(onNone())
}
// Map executes the mapper function if value is present or returns None if absent.
// Play: https://go.dev/play/p/mvfP3pcP_eJ
func (o Option[T]) Map(mapper func(value T) (T, bool)) Option[T] {
if o.isPresent {
return TupleToOption(mapper(o.value))
}
return None[T]()
}
// MapNone executes the mapper function if value is absent or returns Option.
// Play: https://go.dev/play/p/_KaHWZ6Q17b
func (o Option[T]) MapNone(mapper func() (T, bool)) Option[T] {
if o.isPresent {
return Some(o.value)
}
return TupleToOption(mapper())
}
// FlatMap executes the mapper function if value is present or returns None if absent.
// Play: https://go.dev/play/p/OXO-zJx6n5r
func (o Option[T]) FlatMap(mapper func(value T) Option[T]) Option[T] {
if o.isPresent {
return mapper(o.value)
}
return None[T]()
}
// MapValue executes the mapper function if value is present or returns None if absent.
func (o Option[T]) MapValue(mapper func(value T) T) Option[T] {
if o.isPresent {
return Some(mapper(o.value))
}
return None[T]()
}
// ToPointer returns value if present or a nil pointer.
// Play: https://go.dev/play/p/N43w92SM-Bs
func (o Option[T]) ToPointer() *T {
if !o.isPresent {
return nil
}
return &o.value
}
// MarshalJSON encodes Option into json.
// Go 1.20+ relies on the IsZero method when the `omitempty` tag is used
// unless a custom MarshalJSON method is defined. Then the IsZero method is ignored.
// current best workaround is to instead use `omitzero` tag with Go 1.24+
func (o Option[T]) MarshalJSON() ([]byte, error) {
if o.isPresent {
return json.Marshal(o.value)
}
return json.Marshal(nil)
}
// UnmarshalJSON decodes Option from json.
func (o *Option[T]) UnmarshalJSON(b []byte) error {
o.value = empty[T]() // reset the value if not set later.
// If user manually set the field to be `null`, then it either means the option is absent or present with a zero value.
if bytes.Equal([]byte("null"), bytes.ToLower(b)) {
// // If the type is a pointer, then it means the option is present with a zero value.
// o.isPresent = reflect.TypeOf(o.value).Kind() == reflect.Ptr
// return nil
o.isPresent = false
return nil
}
err := json.Unmarshal(b, &o.value)
if err != nil {
return err
}
o.isPresent = true
return nil
}
// IsZero assists `omitzero` tag introduced in Go 1.24
func (o Option[T]) IsZero() bool {
if !o.isPresent {
return true
}
var v any = o.value
if v, ok := v.(zeroer); ok {
return v.IsZero()
}
return reflect.ValueOf(o.value).IsZero()
}
// MarshalText implements the encoding.TextMarshaler interface.
func (o Option[T]) MarshalText() ([]byte, error) {
return json.Marshal(o)
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
func (o *Option[T]) UnmarshalText(data []byte) error {
return json.Unmarshal(data, o)
}
// MarshalBinary is the interface implemented by an object that can marshal itself into a binary form.
func (o Option[T]) MarshalBinary() ([]byte, error) {
if !o.isPresent {
return []byte{0}, nil
}
var buf bytes.Buffer
enc := gob.NewEncoder(&buf)
if err := enc.Encode(o.value); err != nil {
return []byte{}, err
}
return append([]byte{1}, buf.Bytes()...), nil
}
// UnmarshalBinary is the interface implemented by an object that can unmarshal a binary representation of itself.
func (o *Option[T]) UnmarshalBinary(data []byte) error {
if len(data) == 0 {
return errors.New("Option[T].UnmarshalBinary: no data")
}
if data[0] == 0 {
o.isPresent = false
o.value = empty[T]()
return nil
}
buf := bytes.NewBuffer(data[1:])
dec := gob.NewDecoder(buf)
err := dec.Decode(&o.value)
if err != nil {
return err
}
o.isPresent = true
return nil
}
// GobEncode implements the gob.GobEncoder interface.
func (o Option[T]) GobEncode() ([]byte, error) {
return o.MarshalBinary()
}
// GobDecode implements the gob.GobDecoder interface.
func (o *Option[T]) GobDecode(data []byte) error {
return o.UnmarshalBinary(data)
}
// Scan implements the SQL sql.Scanner interface.
func (o *Option[T]) Scan(src any) error {
if src == nil {
o.isPresent = false
o.value = empty[T]()
return nil
}
// is is only possible to assert interfaces, so convert first
// https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md#why-not-permit-type-assertions-on-values-whose-type-is-a-type-parameter
var t T
if tScanner, ok := interface{}(&t).(sql.Scanner); ok {
if err := tScanner.Scan(src); err != nil {
return fmt.Errorf("failed to scan: %w", err)
}
o.isPresent = true
o.value = t
return nil
}
if av, err := driver.DefaultParameterConverter.ConvertValue(src); err == nil {
if v, ok := av.(T); ok {
o.isPresent = true
o.value = v
return nil
}
}
return o.scanConvertValue(src)
}
// Value implements the driver Valuer interface.
func (o Option[T]) Value() (driver.Value, error) {
if !o.isPresent {
return nil, nil
}
return driver.DefaultParameterConverter.ConvertValue(o.value)
}
// Equal compares two Option[T] instances for equality
func (o Option[T]) Equal(other Option[T]) bool {
if !o.isPresent && !other.isPresent {
return true
}
if o.isPresent != other.isPresent {
return false
}
return reflect.DeepEqual(o.value, other.value)
}
// leftValue returns an error if the Option is None, otherwise nil
//
//nolint:unused
func (o Option[T]) leftValue() error {
if !o.isPresent {
return errOptionNoSuchElement
}
return nil
}
// rightValue returns the value if the Option is Some, otherwise the zero value of T
//
//nolint:unused
func (o Option[T]) rightValue() T {
if !o.isPresent {
var zero T
return zero
}
return o.value
}
// hasLeftValue returns true if the Option represents a None state
//
//nolint:unused
func (o Option[T]) hasLeftValue() bool {
return !o.isPresent
}

327
vendor/github.com/samber/mo/option_go118.go generated vendored Normal file
View file

@ -0,0 +1,327 @@
//go:build !go1.22
// +build !go1.22
package mo
//
// sql.Null[T] has been introduce in go1.22
// This file is a copy of stdlib and ensure retro-compatibility.
// See https://github.com/samber/mo/pull/49
//
import (
"database/sql"
"database/sql/driver"
"errors"
"fmt"
"reflect"
"strconv"
"time"
)
var errNilPtr = errors.New("destination pointer is nil")
func cloneBytes(b []byte) []byte {
if b == nil {
return nil
}
c := make([]byte, len(b))
copy(c, b)
return c
}
func asString(src any) string {
switch v := src.(type) {
case string:
return v
case []byte:
return string(v)
}
rv := reflect.ValueOf(src)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.FormatInt(rv.Int(), 10)
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.FormatUint(rv.Uint(), 10)
case reflect.Float64:
return strconv.FormatFloat(rv.Float(), 'g', -1, 64)
case reflect.Float32:
return strconv.FormatFloat(rv.Float(), 'g', -1, 32)
case reflect.Bool:
return strconv.FormatBool(rv.Bool())
}
return fmt.Sprintf("%v", src)
}
func asBytes(buf []byte, rv reflect.Value) (b []byte, ok bool) {
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.AppendInt(buf, rv.Int(), 10), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
return strconv.AppendUint(buf, rv.Uint(), 10), true
case reflect.Float32:
return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 32), true
case reflect.Float64:
return strconv.AppendFloat(buf, rv.Float(), 'g', -1, 64), true
case reflect.Bool:
return strconv.AppendBool(buf, rv.Bool()), true
case reflect.String:
s := rv.String()
return append(buf, s...), true
}
return
}
func strconvErr(err error) error {
if ne, ok := err.(*strconv.NumError); ok {
return ne.Err
}
return err
}
// convertAssignRows copies to dest the value in src, converting it if possible.
// An error is returned if the copy would result in loss of information.
// dest should be a pointer type. If rows is passed in, the rows will
// be used as the parent for any cursor values converted from a
// driver.Rows to a *Rows.
func convertAssign(dest, src any) error {
// Common cases, without reflect.
switch s := src.(type) {
case string:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = s
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = []byte(s)
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = append((*d)[:0], s...)
return nil
}
case []byte:
switch d := dest.(type) {
case *string:
if d == nil {
return errNilPtr
}
*d = string(s)
return nil
case *any:
if d == nil {
return errNilPtr
}
*d = cloneBytes(s)
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = cloneBytes(s)
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = s
return nil
}
case time.Time:
switch d := dest.(type) {
case *time.Time:
*d = s
return nil
case *string:
*d = s.Format(time.RFC3339Nano)
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = []byte(s.Format(time.RFC3339Nano))
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = s.AppendFormat((*d)[:0], time.RFC3339Nano)
return nil
}
case nil:
switch d := dest.(type) {
case *any:
if d == nil {
return errNilPtr
}
*d = nil
return nil
case *[]byte:
if d == nil {
return errNilPtr
}
*d = nil
return nil
case *sql.RawBytes:
if d == nil {
return errNilPtr
}
*d = nil
return nil
}
}
var sv reflect.Value
switch d := dest.(type) {
case *string:
sv = reflect.ValueOf(src)
switch sv.Kind() {
case reflect.Bool,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
*d = asString(src)
return nil
}
case *[]byte:
sv = reflect.ValueOf(src)
if b, ok := asBytes(nil, sv); ok {
*d = b
return nil
}
case *sql.RawBytes:
sv = reflect.ValueOf(src)
if b, ok := asBytes([]byte(*d)[:0], sv); ok {
*d = sql.RawBytes(b)
return nil
}
case *bool:
bv, err := driver.Bool.ConvertValue(src)
if err == nil {
*d = bv.(bool)
}
return err
case *any:
*d = src
return nil
}
if scanner, ok := dest.(sql.Scanner); ok {
return scanner.Scan(src)
}
dpv := reflect.ValueOf(dest)
if dpv.Kind() != reflect.Pointer {
return errors.New("destination not a pointer")
}
if dpv.IsNil() {
return errNilPtr
}
if !sv.IsValid() {
sv = reflect.ValueOf(src)
}
dv := reflect.Indirect(dpv)
if sv.IsValid() && sv.Type().AssignableTo(dv.Type()) {
switch b := src.(type) {
case []byte:
dv.Set(reflect.ValueOf(cloneBytes(b)))
default:
dv.Set(sv)
}
return nil
}
if dv.Kind() == sv.Kind() && sv.Type().ConvertibleTo(dv.Type()) {
dv.Set(sv.Convert(dv.Type()))
return nil
}
// The following conversions use a string value as an intermediate representation
// to convert between various numeric types.
//
// This also allows scanning into user defined types such as "type Int int64".
// For symmetry, also check for string destination types.
switch dv.Kind() {
case reflect.Pointer:
if src == nil {
dv.Set(reflect.Zero(dv.Type()))
return nil
}
dv.Set(reflect.New(dv.Type().Elem()))
return convertAssign(dv.Interface(), src)
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if src == nil {
return fmt.Errorf("converting NULL to %s is unsupported", dv.Kind())
}
s := asString(src)
i64, err := strconv.ParseInt(s, 10, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetInt(i64)
return nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if src == nil {
return fmt.Errorf("converting NULL to %s is unsupported", dv.Kind())
}
s := asString(src)
u64, err := strconv.ParseUint(s, 10, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetUint(u64)
return nil
case reflect.Float32, reflect.Float64:
if src == nil {
return fmt.Errorf("converting NULL to %s is unsupported", dv.Kind())
}
s := asString(src)
f64, err := strconv.ParseFloat(s, dv.Type().Bits())
if err != nil {
err = strconvErr(err)
return fmt.Errorf("converting driver.Value type %T (%q) to a %s: %v", src, s, dv.Kind(), err)
}
dv.SetFloat(f64)
return nil
case reflect.String:
if src == nil {
return fmt.Errorf("converting NULL to %s is unsupported", dv.Kind())
}
switch v := src.(type) {
case string:
dv.SetString(v)
return nil
case []byte:
dv.SetString(string(v))
return nil
}
}
return fmt.Errorf("unsupported Scan, storing driver.Value type %T into type %T", src, dest)
}
func (o *Option[T]) scanConvertValue(src any) error {
// we try to convertAssign values that we can't directly assign because ConvertValue
// will return immediately for v that is already a Value, even if it is a different
// Value type than the one we expect here.
var dest T
if err := convertAssign(&dest, src); err == nil {
o.isPresent = true
o.value = dest
return nil
}
return fmt.Errorf("failed to scan Option[T]")
}

22
vendor/github.com/samber/mo/option_go122.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
//go:build go1.22
// +build go1.22
package mo
import (
"database/sql"
"fmt"
)
func (o *Option[T]) scanConvertValue(src any) error {
// we try to convertAssign values that we can't directly assign because ConvertValue
// will return immediately for v that is already a Value, even if it is a different
// Value type than the one we expect here.
var st sql.Null[T]
if err := st.Scan(src); err == nil {
o.isPresent = true
o.value = st.V
return nil
}
return fmt.Errorf("failed to scan Option[T]")
}

245
vendor/github.com/samber/mo/result.go generated vendored Normal file
View file

@ -0,0 +1,245 @@
package mo
import (
"encoding/json"
"errors"
"fmt"
)
// Ok builds a Result when value is valid.
// Play: https://go.dev/play/p/PDwADdzNoyZ
func Ok[T any](value T) Result[T] {
return Result[T]{
value: value,
isErr: false,
}
}
// Err builds a Result when value is invalid.
// Play: https://go.dev/play/p/PDwADdzNoyZ
func Err[T any](err error) Result[T] {
return Result[T]{
err: err,
isErr: true,
}
}
// Errf builds a Result when value is invalid.
// Errf formats according to a format specifier and returns the error as a value that satisfies Result[T].
// Play: https://go.dev/play/p/N43w92SM-Bs
func Errf[T any](format string, a ...any) Result[T] {
return Err[T](fmt.Errorf(format, a...))
}
// TupleToResult convert a pair of T and error into a Result.
// Play: https://go.dev/play/p/KWjfqQDHQwa
func TupleToResult[T any](value T, err error) Result[T] {
if err != nil {
return Err[T](err)
}
return Ok(value)
}
// Try returns either a Ok or Err object.
// Play: https://go.dev/play/p/ilOlQx-Mx42
func Try[T any](f func() (T, error)) Result[T] {
return TupleToResult(f())
}
// Result represents a result of an action having one
// of the following output: success or failure.
// An instance of Result is an instance of either Ok or Err.
// It could be compared to `Either[error, T]`.
type Result[T any] struct {
isErr bool
value T
err error
}
// IsOk returns true when value is valid.
// Play: https://go.dev/play/p/sfNvBQyZfgU
func (r Result[T]) IsOk() bool {
return !r.isErr
}
// IsError returns true when value is invalid.
// Play: https://go.dev/play/p/xkV9d464scV
func (r Result[T]) IsError() bool {
return r.isErr
}
// Error returns error when value is invalid or nil.
// Play: https://go.dev/play/p/CSkHGTyiXJ5
func (r Result[T]) Error() error {
return r.err
}
// Get returns value and error.
// Play: https://go.dev/play/p/8KyX3z6TuNo
func (r Result[T]) Get() (T, error) {
if r.isErr {
return empty[T](), r.err
}
return r.value, nil
}
// MustGet returns value when Result is valid or panics.
// Play: https://go.dev/play/p/8LSlndHoTAE
func (r Result[T]) MustGet() T {
if r.isErr {
panic(r.err)
}
return r.value
}
// OrElse returns value when Result is valid or default value.
// Play: https://go.dev/play/p/MN_ULx0soi6
func (r Result[T]) OrElse(fallback T) T {
if r.isErr {
return fallback
}
return r.value
}
// OrEmpty returns value when Result is valid or empty value.
// Play: https://go.dev/play/p/rdKtBmOcMLh
func (r Result[T]) OrEmpty() T {
return r.value
}
// ToEither transforms a Result into an Either type.
// Play: https://go.dev/play/p/Uw1Zz6b952q
func (r Result[T]) ToEither() Either[error, T] {
if r.isErr {
return Left[error, T](r.err)
}
return Right[error, T](r.value)
}
// ForEach executes the given side-effecting function if Result is valid.
func (r Result[T]) ForEach(mapper func(value T)) {
if !r.isErr {
mapper(r.value)
}
}
// Match executes the first function if Result is valid and second function if invalid.
// It returns a new Result.
// Play: https://go.dev/play/p/-_eFaLJ31co
func (r Result[T]) Match(onSuccess func(value T) (T, error), onError func(err error) (T, error)) Result[T] {
if r.isErr {
return TupleToResult(onError(r.err))
}
return TupleToResult(onSuccess(r.value))
}
// Map executes the mapper function if Result is valid. It returns a new Result.
// Play: https://go.dev/play/p/-ndpN_b_OSc
func (r Result[T]) Map(mapper func(value T) (T, error)) Result[T] {
if !r.isErr {
return TupleToResult(mapper(r.value))
}
return Err[T](r.err)
}
// MapValue executes the mapper function if Result is valid. It returns a new Result.
func (r Result[T]) MapValue(mapper func(value T) T) Result[T] {
if !r.isErr {
return TupleToResult(mapper(r.value), nil)
}
return Err[T](r.err)
}
// MapErr executes the mapper function if Result is invalid. It returns a new Result.
// Play: https://go.dev/play/p/WraZixg9GGf
func (r Result[T]) MapErr(mapper func(error) (T, error)) Result[T] {
if r.isErr {
return TupleToResult(mapper(r.err))
}
return Ok(r.value)
}
// FlatMap executes the mapper function if Result is valid. It returns a new Result.
// Play: https://go.dev/play/p/Ud5QjZOqg-7
func (r Result[T]) FlatMap(mapper func(value T) Result[T]) Result[T] {
if !r.isErr {
return mapper(r.value)
}
return Err[T](r.err)
}
// MarshalJSON encodes Result into json, following the JSON-RPC specification for results,
// with one exception: when the result is an error, the "code" field is not included.
// Reference: https://www.jsonrpc.org/specification
func (o Result[T]) MarshalJSON() ([]byte, error) {
if o.isErr {
return json.Marshal(map[string]any{
"error": map[string]any{
"message": o.err.Error(),
},
})
}
return json.Marshal(map[string]any{
"result": o.value,
})
}
// UnmarshalJSON decodes json into Result. If "error" is set, the result is an
// Err containing the error message as a generic error object. Otherwise, the
// result is an Ok containing the result. If the JSON object contains netiher
// an error nor a result, the result is an Ok containing an empty value. If the
// JSON object contains both an error and a result, the result is an Err. Finally,
// if the JSON object contains an error but is not structured correctly (no message
// field), the unmarshaling fails.
func (o *Result[T]) UnmarshalJSON(data []byte) error {
var result struct {
Result T `json:"result"`
Error struct {
Message string `json:"message"`
} `json:"error"`
}
if err := json.Unmarshal(data, &result); err != nil {
return err
}
if result.Error.Message != "" {
o.err = errors.New(result.Error.Message)
o.isErr = true
return nil
}
o.value = result.Result
o.isErr = false
return nil
}
// leftValue returns the error if the Result is an error, otherwise nil
//
//nolint:unused
func (r Result[T]) leftValue() error {
return r.err
}
// rightValue returns the value if the Result is a success, otherwise the zero value of T
//
//nolint:unused
func (r Result[T]) rightValue() T {
return r.value
}
// hasLeftValue returns true if the Result represents an error state.
//
//nolint:unused
func (r Result[T]) hasLeftValue() bool {
return r.isErr
}

52
vendor/github.com/samber/mo/state.go generated vendored Normal file
View file

@ -0,0 +1,52 @@
package mo
func NewState[S any, A any](f func(state S) (A, S)) State[S, A] {
return State[S, A]{
run: f,
}
}
func ReturnState[S any, A any](x A) State[S, A] {
return State[S, A]{
run: func(state S) (A, S) {
return x, state
},
}
}
// State represents a function `(S) -> (A, S)`, where `S` is state, `A` is result.
type State[S any, A any] struct {
run func(state S) (A, S)
}
// Run executes a computation in the State monad.
func (s State[S, A]) Run(state S) (A, S) {
return s.run(state)
}
// Get returns the current state.
func (s State[S, A]) Get() State[S, S] {
return State[S, S]{
run: func(state S) (S, S) {
return state, state
},
}
}
// Modify the state by applying a function to the current state.
func (s State[S, A]) Modify(f func(state S) S) State[S, A] {
return State[S, A]{
run: func(state S) (A, S) {
return empty[A](), f(state)
},
}
}
// Put set the state.
func (s State[S, A]) Put(state S) State[S, A] {
return State[S, A]{
run: func(state S) (A, S) {
return empty[A](), state
},
}
}

175
vendor/github.com/samber/mo/task.go generated vendored Normal file
View file

@ -0,0 +1,175 @@
package mo
// NewTask instanciates a new Task.
func NewTask[R any](f ff0[R]) Task[R] {
return Task[R]{
unsafePerform: f,
}
}
// NewTaskFromIO instanciates a new Task from an existing IO.
func NewTaskFromIO[R any](io IO[R]) Task[R] {
return Task[R]{
unsafePerform: func() *Future[R] {
return NewFuture[R](func(resolve func(R), reject func(error)) {
resolve(io.unsafePerform())
})
},
}
}
// Task represents a non-deterministic asynchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type Task[R any] struct {
unsafePerform ff0[R]
}
// Run execute the non-deterministic asynchronous computation, with side effect.
func (t Task[R]) Run() *Future[R] {
return t.unsafePerform()
}
// NewTask1 instanciates a new Task1.
func NewTask1[R any, A any](f ff1[R, A]) Task1[R, A] {
return Task1[R, A]{
unsafePerform: f,
}
}
// NewTaskFromIO1 instanciates a new Task1 from an existing IO1.
func NewTaskFromIO1[R any, A any](io IO1[R, A]) Task1[R, A] {
return Task1[R, A]{
unsafePerform: func(a A) *Future[R] {
return NewFuture[R](func(resolve func(R), reject func(error)) {
resolve(io.unsafePerform(a))
})
},
}
}
// Task1 represents a non-deterministic asynchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type Task1[R any, A any] struct {
unsafePerform ff1[R, A]
}
// Run execute the non-deterministic asynchronous computation, with side effect.
func (t Task1[R, A]) Run(a A) *Future[R] {
return t.unsafePerform(a)
}
// NewTask2 instanciates a new Task2.
func NewTask2[R any, A any, B any](f ff2[R, A, B]) Task2[R, A, B] {
return Task2[R, A, B]{
unsafePerform: f,
}
}
// NewTaskFromIO2 instanciates a new Task2 from an existing IO2.
func NewTaskFromIO2[R any, A any, B any](io IO2[R, A, B]) Task2[R, A, B] {
return Task2[R, A, B]{
unsafePerform: func(a A, b B) *Future[R] {
return NewFuture[R](func(resolve func(R), reject func(error)) {
resolve(io.unsafePerform(a, b))
})
},
}
}
// Task2 represents a non-deterministic asynchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type Task2[R any, A any, B any] struct {
unsafePerform ff2[R, A, B]
}
// Run execute the non-deterministic asynchronous computation, with side effect.
func (t Task2[R, A, B]) Run(a A, b B) *Future[R] {
return t.unsafePerform(a, b)
}
// NewTask3 instanciates a new Task3.
func NewTask3[R any, A any, B any, C any](f ff3[R, A, B, C]) Task3[R, A, B, C] {
return Task3[R, A, B, C]{
unsafePerform: f,
}
}
// NewTaskFromIO3 instanciates a new Task3 from an existing IO3.
func NewTaskFromIO3[R any, A any, B any, C any](io IO3[R, A, B, C]) Task3[R, A, B, C] {
return Task3[R, A, B, C]{
unsafePerform: func(a A, b B, c C) *Future[R] {
return NewFuture[R](func(resolve func(R), reject func(error)) {
resolve(io.unsafePerform(a, b, c))
})
},
}
}
// Task3 represents a non-deterministic asynchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type Task3[R any, A any, B any, C any] struct {
unsafePerform ff3[R, A, B, C]
}
// Run execute the non-deterministic asynchronous computation, with side effect.
func (t Task3[R, A, B, C]) Run(a A, b B, c C) *Future[R] {
return t.unsafePerform(a, b, c)
}
// NewTask4 instanciates a new Task4.
func NewTask4[R any, A any, B any, C any, D any](f ff4[R, A, B, C, D]) Task4[R, A, B, C, D] {
return Task4[R, A, B, C, D]{
unsafePerform: f,
}
}
// NewTaskFromIO4 instanciates a new Task4 from an existing IO4.
func NewTaskFromIO4[R any, A any, B any, C any, D any](io IO4[R, A, B, C, D]) Task4[R, A, B, C, D] {
return Task4[R, A, B, C, D]{
unsafePerform: func(a A, b B, c C, d D) *Future[R] {
return NewFuture[R](func(resolve func(R), reject func(error)) {
resolve(io.unsafePerform(a, b, c, d))
})
},
}
}
// Task4 represents a non-deterministic asynchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type Task4[R any, A any, B any, C any, D any] struct {
unsafePerform ff4[R, A, B, C, D]
}
// Run execute the non-deterministic asynchronous computation, with side effect.
func (t Task4[R, A, B, C, D]) Run(a A, b B, c C, d D) *Future[R] {
return t.unsafePerform(a, b, c, d)
}
// NewTask5 instanciates a new Task5.
func NewTask5[R any, A any, B any, C any, D any, E any](f ff5[R, A, B, C, D, E]) Task5[R, A, B, C, D, E] {
return Task5[R, A, B, C, D, E]{
unsafePerform: f,
}
}
// NewTaskFromIO5 instanciates a new Task5 from an existing IO5.
func NewTaskFromIO5[R any, A any, B any, C any, D any, E any](io IO5[R, A, B, C, D, E]) Task5[R, A, B, C, D, E] {
return Task5[R, A, B, C, D, E]{
unsafePerform: func(a A, b B, c C, d D, e E) *Future[R] {
return NewFuture[R](func(resolve func(R), reject func(error)) {
resolve(io.unsafePerform(a, b, c, d, e))
})
},
}
}
// Task5 represents a non-deterministic asynchronous computation that
// can cause side effects, yields a value of type `R` and never fails.
type Task5[R any, A any, B any, C any, D any, E any] struct {
unsafePerform ff5[R, A, B, C, D, E]
}
// Run execute the non-deterministic asynchronous computation, with side effect.
func (t Task5[R, A, B, C, D, E]) Run(a A, b B, c C, d D, e E) *Future[R] {
return t.unsafePerform(a, b, c, d, e)
}

56
vendor/github.com/samber/mo/task_either.go generated vendored Normal file
View file

@ -0,0 +1,56 @@
package mo
// NewTaskEither instanciates a new TaskEither.
func NewTaskEither[R any](f ff0[R]) TaskEither[R] {
return TaskEither[R]{NewTask[R](f)}
}
// NewTaskEitherFromIO instanciates a new TaskEither from an existing IO.
func NewTaskEitherFromIO[R any](io IO[R]) TaskEither[R] {
return TaskEither[R]{NewTaskFromIO[R](io)}
}
// TaskEither represents a non-deterministic asynchronous computation that
// can cause side effects, yields a value of type `R` and can fail.
type TaskEither[R any] struct {
Task[R]
}
// OrElse returns value if task succeeded or default value.
func (t TaskEither[R]) OrElse(fallback R) R {
either := t.Run().Either()
right, isRight := either.Right()
if !isRight {
return fallback
}
return right
}
// Match executes the first function if task succeeded and second function if task failed.
// It returns a new Option.
func (t TaskEither[R]) Match(onLeft func(error) Either[error, R], onRight func(R) Either[error, R]) Either[error, R] {
either := t.Run().Either()
return either.Match(onLeft, onRight)
}
// TryCatch is an alias to Match
func (t TaskEither[R]) TryCatch(onLeft func(error) Either[error, R], onRight func(R) Either[error, R]) Either[error, R] {
return t.Match(onLeft, onRight)
}
// ToTask converts TaskEither to Task
func (t TaskEither[R]) ToTask(fallback R) Task[R] {
return NewTask(func() *Future[R] {
return t.Run().
Catch(func(err error) (R, error) {
return fallback, nil
})
})
}
// ToEither converts TaskEither to Either.
func (t TaskEither[R]) ToEither() Either[error, R] {
return t.Run().Either()
}

22
vendor/github.com/samber/mo/types.go generated vendored Normal file
View file

@ -0,0 +1,22 @@
package mo
type f0[R any] func() R
type f1[R any, A any] func(A) R
type f2[R any, A any, B any] func(A, B) R
type f3[R any, A any, B any, C any] func(A, B, C) R
type f4[R any, A any, B any, C any, D any] func(A, B, C, D) R
type f5[R any, A any, B any, C any, D any, E any] func(A, B, C, D, E) R
type ff0[R any] func() *Future[R]
type ff1[R any, A any] func(A) *Future[R]
type ff2[R any, A any, B any] func(A, B) *Future[R]
type ff3[R any, A any, B any, C any] func(A, B, C) *Future[R]
type ff4[R any, A any, B any, C any, D any] func(A, B, C, D) *Future[R]
type ff5[R any, A any, B any, C any, D any, E any] func(A, B, C, D, E) *Future[R]
type fe0[R any] func() (R, error)
type fe1[R any, A any] func(A) (R, error)
type fe2[R any, A any, B any] func(A, B) (R, error)
type fe3[R any, A any, B any, C any] func(A, B, C) (R, error)
type fe4[R any, A any, B any, C any, D any] func(A, B, C, D) (R, error)
type fe5[R any, A any, B any, C any, D any, E any] func(A, B, C, D, E) (R, error)

5
vendor/github.com/samber/mo/utils.go generated vendored Normal file
View file

@ -0,0 +1,5 @@
package mo
func empty[T any]() (t T) {
return
}