async_monad 0.2.0

Asynchronous monad for rust
Documentation
use std::future::Future;

#[allow(
    async_fn_in_trait,
    opaque_hidden_inferred_bound,
    clippy::wrong_self_convention
)]
pub trait AsyncOption: Send {
    type Value;

    async fn ais_some(&self) -> bool;

    async fn ais_some_and<F>(self, f: impl FnOnce(Self::Value) -> F) -> bool
    where
        F: Future<Output = bool>;

    async fn ais_none(&self) -> bool;

    async fn ais_none_or<F>(self, f: impl FnOnce(Self::Value) -> F) -> bool
    where
        F: Future<Output = bool>;

    async fn aunwrap_or(self, default: impl Future<Output = Self::Value>) -> Self::Value;

    async fn aunwrap_or_else<F>(self, default: impl FnOnce() -> F) -> Self::Value
    where
        F: Future<Output = Self::Value>;

    async fn ainspect<F>(self, f: impl FnOnce(&Self::Value) -> F) -> Self
    where
        F: Future<Output = ()>;

    async fn ainspect_mut<F>(self, f: impl FnOnce(&mut Self::Value) -> F) -> Self
    where
        F: Future<Output = ()>;

    async fn amap_or<U, F>(
        self,
        default: impl Future<Output = U>,
        f: impl FnOnce(Self::Value) -> F,
    ) -> U
    where
        F: Future<Output = U>;

    async fn amap_or_else<U, D, F>(
        self,
        default: impl FnOnce() -> D,
        f: impl FnOnce(Self::Value) -> F,
    ) -> U
    where
        D: Future<Output = U>,
        F: Future<Output = U>;

    async fn aok_or<E>(self, err: impl Future<Output = E>) -> Result<Self::Value, E>;

    async fn aok_or_else<E, F>(self, err: impl FnOnce() -> F) -> Result<Self::Value, E>
    where
        F: Future<Output = E>;

    async fn aand<U>(self, optb: impl Future<Output = Option<U>>) -> Option<U>;

    async fn aand_then<U, F>(self, f: impl FnOnce(Self::Value) -> F) -> Option<U>
    where
        F: Future<Output = Option<U>>;

    async fn afilter<F>(self, predicate: impl FnOnce(&Self::Value) -> F) -> Self
    where
        F: Future<Output = bool>;

    async fn aor(self, optb: impl Future<Output = Self>) -> Self;

    async fn aor_else<F>(self, f: impl FnOnce() -> F) -> Self
    where
        F: Future<Output = Self>;

    async fn axor(self, optb: impl Future<Output = Self>) -> Self;

    async fn azip<U>(self, other: impl Future<Output = Option<U>>) -> Option<(Self::Value, U)>;

    async fn azip_with<U, F, R>(
        self,
        other: impl Future<Output = Option<U>>,
        f: impl FnOnce(Self::Value, U) -> F,
    ) -> Option<R>
    where
        F: Future<Output = R>;
}

impl<T> AsyncOption for core::option::Option<T>
where
    T: std::marker::Send,
{
    type Value = T;

    async fn ais_some(&self) -> bool {
        self.is_some()
    }

    async fn ais_some_and<F>(self, f: impl FnOnce(Self::Value) -> F) -> bool
    where
        F: Future<Output = bool>,
    {
        match self {
            Self::Some(val) => f(val).await,
            Self::None => false,
        }
    }

    async fn ais_none(&self) -> bool {
        self.is_none()
    }

    async fn ais_none_or<F>(self, f: impl FnOnce(Self::Value) -> F) -> bool
    where
        F: Future<Output = bool>,
    {
        match self {
            Self::Some(val) => f(val).await,
            Self::None => true,
        }
    }

    async fn aunwrap_or(self, default: impl Future<Output = Self::Value>) -> Self::Value {
        self.unwrap_or(default.await)
    }

    async fn aunwrap_or_else<F>(self, default: impl FnOnce() -> F) -> Self::Value
    where
        F: Future<Output = Self::Value>,
    {
        match self {
            Self::Some(val) => val,
            Self::None => default().await,
        }
    }

    async fn ainspect<F>(self, f: impl FnOnce(&Self::Value) -> F) -> Self
    where
        F: Future<Output = ()>,
    {
        match &self {
            Self::Some(val) => f(val).await,
            Self::None => (),
        }
        self
    }

    async fn ainspect_mut<F>(mut self, f: impl FnOnce(&mut Self::Value) -> F) -> Self
    where
        F: Future<Output = ()>,
    {
        match &mut self {
            Self::Some(val) => f(val).await,
            Self::None => (),
        }
        self
    }

    async fn amap_or<U, F>(
        self,
        default: impl Future<Output = U>,
        f: impl FnOnce(Self::Value) -> F,
    ) -> U
    where
        F: Future<Output = U>,
    {
        match self {
            Self::Some(val) => f(val).await,
            Self::None => default.await,
        }
    }

    async fn amap_or_else<U, D, F>(
        self,
        default: impl FnOnce() -> D,
        f: impl FnOnce(Self::Value) -> F,
    ) -> U
    where
        D: Future<Output = U>,
        F: Future<Output = U>,
    {
        match self {
            Self::Some(val) => f(val).await,
            Self::None => default().await,
        }
    }

    async fn aok_or<E>(self, err: impl Future<Output = E>) -> Result<Self::Value, E> {
        match self {
            Self::Some(val) => Ok(val),
            Self::None => Err(err.await),
        }
    }

    async fn aok_or_else<E, F>(self, err: impl FnOnce() -> F) -> Result<Self::Value, E>
    where
        F: Future<Output = E>,
    {
        match self {
            Self::Some(val) => Ok(val),
            Self::None => Err(err().await),
        }
    }

    async fn aand<U>(self, optb: impl Future<Output = Option<U>>) -> Option<U> {
        self.and(optb.await)
    }

    async fn aand_then<U, F>(self, f: impl FnOnce(Self::Value) -> F) -> Option<U>
    where
        F: Future<Output = Option<U>>,
    {
        match self {
            Self::Some(val) => f(val).await,
            Self::None => None,
        }
    }

    async fn afilter<F>(self, predicate: impl FnOnce(&Self::Value) -> F) -> Self
    where
        F: Future<Output = bool>,
    {
        match self {
            Self::Some(val) => {
                if predicate(&val).await {
                    Self::Some(val)
                } else {
                    Self::None
                }
            }
            Self::None => Self::None,
        }
    }

    async fn aor(self, optb: impl Future<Output = Self>) -> Self {
        self.or(optb.await)
    }

    async fn aor_else<F>(self, f: impl FnOnce() -> F) -> Self
    where
        F: Future<Output = Self>,
    {
        match self {
            x @ Some(_) => x,
            None => f().await,
        }
    }

    async fn axor(self, optb: impl Future<Output = Self>) -> Self {
        self.xor(optb.await)
    }

    async fn azip<U>(self, other: impl Future<Output = Option<U>>) -> Option<(Self::Value, U)> {
        self.zip(other.await)
    }

    async fn azip_with<U, F, R>(
        self,
        other: impl Future<Output = Option<U>>,
        f: impl FnOnce(Self::Value, U) -> F,
    ) -> Option<R>
    where
        F: Future<Output = R>,
    {
        match (self, other.await) {
            (Some(a), Some(b)) => Some(f(a, b).await),
            _ => None,
        }
    }
}

#[allow(
    async_fn_in_trait,
    opaque_hidden_inferred_bound,
    clippy::wrong_self_convention
)]
pub trait FutureOption {
    type Value;
    async fn as_future(self) -> Option<Self::Value>;
}

impl<T, F> FutureOption for Option<F>
where
    F: Future<Output = T>,
{
    type Value = T;

    async fn as_future(self) -> Option<Self::Value> {
        match self {
            Self::Some(f) => Some(f.await),
            Self::None => None,
        }
    }
}