103 lines
1.8 KiB
Go
103 lines
1.8 KiB
Go
package channel
|
|
|
|
type Result[T any] struct {
|
|
value *T
|
|
err error
|
|
}
|
|
|
|
func ResultOf[T any](value T, err error) Result[T] {
|
|
if err != nil {
|
|
return Result[T]{value: nil, err: err}
|
|
}
|
|
|
|
return Result[T]{value: &value, err: nil}
|
|
}
|
|
|
|
func WrapMapFunc[I, O any](f func(I) (O, error)) func(I) Result[O] {
|
|
return func(i I) Result[O] { return ResultOf(f(i)) }
|
|
}
|
|
|
|
func ResultFunc[I, O any](f func(I) (O, error)) func(Result[I]) Result[O] {
|
|
resFunc := WrapMapFunc(f)
|
|
nilValue := *new(O)
|
|
return func(r Result[I]) Result[O] {
|
|
v, err := r.Get()
|
|
if err != nil {
|
|
return ResultOf(nilValue, err)
|
|
}
|
|
return resFunc(v)
|
|
}
|
|
}
|
|
|
|
func (r Result[T]) Success() bool {
|
|
return r.err == nil
|
|
}
|
|
|
|
func (r Result[T]) Fail() bool {
|
|
return !r.Success()
|
|
}
|
|
|
|
func (r Result[T]) GetOrDefault(defaultValue T) T {
|
|
if r.Fail() {
|
|
return defaultValue
|
|
}
|
|
|
|
return *r.value
|
|
}
|
|
|
|
func (r Result[T]) Get() (T, error) {
|
|
if r.err != nil {
|
|
return *new(T), r.err
|
|
}
|
|
return *r.value, r.err
|
|
}
|
|
|
|
func (r Result[T]) GetUnsafe() T {
|
|
if r.err != nil {
|
|
panic(r.err)
|
|
}
|
|
return *r.value
|
|
}
|
|
|
|
func (r Result[T]) Err() error {
|
|
return r.err
|
|
}
|
|
|
|
func FilterSuccess[T any](source <-chan Result[T]) <-chan T {
|
|
succeeded := Filter(source, Result[T].Success)
|
|
|
|
return MapSuccessive(succeeded, func(r Result[T]) T {
|
|
v, _ := r.Get()
|
|
return v
|
|
})
|
|
}
|
|
|
|
func FilterFail[T any](source <-chan Result[T]) <-chan T {
|
|
failed := Filter(source, Result[T].Fail)
|
|
|
|
return MapSuccessive(failed, func(r Result[T]) T {
|
|
v, _ := r.Get()
|
|
return v
|
|
})
|
|
}
|
|
|
|
func FilterResults[T any](source <-chan Result[T]) (succeeded <-chan T, failed <-chan error) {
|
|
succ := make(chan T, cap(source))
|
|
fail := make(chan error, cap(source))
|
|
|
|
go func() {
|
|
defer close(succ)
|
|
defer close(fail)
|
|
|
|
for r := range source {
|
|
if r.Fail() {
|
|
fail <- r.Err()
|
|
continue
|
|
}
|
|
succ <- r.GetUnsafe()
|
|
}
|
|
}()
|
|
|
|
return succ, fail
|
|
}
|