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,
}
}
}