vendor
This commit is contained in:
parent
07ec5529ac
commit
f501abe660
532 changed files with 271781 additions and 0 deletions
197
vendor/github.com/samber/mo/future.go
generated
vendored
Normal file
197
vendor/github.com/samber/mo/future.go
generated
vendored
Normal 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)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue