use std::future::Future;
use std::pin::Pin;
use super::option::AsyncOption;
pub struct AsyncResult<T: 'static, E: 'static> {
future: Pin<Box<dyn Future<Output = Result<T, E>>>>,
}
impl<T, E> From<Result<T, E>> for AsyncResult<T, E> {
fn from(value: Result<T, E>) -> Self {
Self {
future: Box::pin(async move { value }),
}
}
}
impl<T, E> Future for AsyncResult<T, E> {
type Output = Result<T, E>;
fn poll(
mut self: Pin<&mut Self>,
cx: &mut std::task::Context<'_>,
) -> std::task::Poll<Self::Output> {
Future::poll(self.future.as_mut(), cx)
}
}
impl<T, E> AsyncResult<T, E> {
#[inline]
#[must_use]
pub fn new(value: Result<T, E>) -> AsyncResult<T, E> {
Self {
future: Box::pin(async move { value }),
}
}
#[inline]
#[must_use]
pub fn raw<V: Future<Output = Result<T, E>> + 'static>(value: V) -> AsyncResult<T, E> {
Self {
future: Box::pin(value),
}
}
#[inline]
#[must_use]
pub fn and<U>(self, optb: impl Future<Output = Result<U, E>> + 'static) -> AsyncResult<U, E> {
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(_) => optb.await,
Err(e) => Err(e),
}
}),
}
}
#[inline]
#[must_use]
pub fn and_then<F, V>(self, f: impl FnOnce(T) -> F + 'static) -> AsyncResult<V, E>
where
F: Future<Output = AsyncResult<V, E>> + 'static,
V: 'static,
{
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(val) => f(val).await.await,
Err(err) => Err(err),
}
}),
}
}
#[inline]
#[must_use]
pub fn or<F>(self, res: impl Future<Output = Result<T, F>> + 'static) -> AsyncResult<T, F> {
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(val) => Ok(val),
Err(_) => res.await,
}
}),
}
}
#[inline]
#[must_use]
pub fn or_else<F, V>(self, f: impl FnOnce(E) -> F + 'static) -> AsyncResult<T, V>
where
F: Future<Output = Result<T, V>> + 'static,
V: 'static,
{
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(val) => Ok(val),
Err(err) => f(err).await,
}
}),
}
}
#[inline]
#[must_use]
pub fn map<F, U>(self, f: impl FnOnce(T) -> F + 'static) -> AsyncResult<U, E>
where
F: Future<Output = U> + 'static,
U: 'static,
{
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(v) => Ok(f(v).await),
Err(e) => Err(e),
}
}),
}
}
#[inline]
#[must_use]
pub async fn map_or<U, F>(self, default: F, f: impl FnOnce(T) -> F) -> U
where
F: Future<Output = U> + 'static,
U: 'static,
{
match self.future.await {
Ok(v) => f(v).await,
Err(_) => default.await,
}
}
#[inline]
#[must_use]
pub async fn map_or_else<U, F>(self, default: impl FnOnce() -> F, f: impl FnOnce(T) -> F) -> U
where
F: Future<Output = U> + 'static,
U: 'static,
{
match self.future.await {
Ok(v) => f(v).await,
Err(_) => default().await,
}
}
#[inline]
#[must_use]
pub fn map_err<F, U>(self, f: impl FnOnce(E) -> F + 'static) -> AsyncResult<T, U>
where
F: Future<Output = U> + 'static,
U: 'static,
{
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(v) => Ok(v),
Err(e) => Err(f(e).await),
}
}),
}
}
#[inline]
#[must_use]
pub async fn map_err_or<U, F>(self, default: F, f: impl FnOnce(E) -> F) -> U
where
F: Future<Output = U> + 'static,
U: 'static,
{
match self.future.await {
Err(v) => f(v).await,
Ok(_) => default.await,
}
}
#[inline]
#[must_use]
pub async fn map_err_or_else<U, F>(
self,
default: impl FnOnce() -> F,
f: impl FnOnce(E) -> F,
) -> U
where
F: Future<Output = U> + 'static,
U: 'static,
{
match self.future.await {
Err(v) => f(v).await,
Ok(_) => default().await,
}
}
#[inline]
#[must_use]
pub fn inspect(self, f: impl FnOnce(&T) + 'static) -> Self {
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(val) => {
f(&val);
Ok(val)
}
Err(err) => Err(err),
}
}),
}
}
#[inline]
#[must_use]
pub fn inspect_err(self, f: impl FnOnce(&E) + 'static) -> Self {
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Err(val) => {
f(&val);
Err(val)
}
Ok(err) => Ok(err),
}
}),
}
}
#[inline]
#[must_use]
pub fn ok(self) -> AsyncOption<T> {
AsyncOption::raw(async move { self.future.await.ok() })
}
#[inline]
#[must_use]
pub fn err(self) -> AsyncOption<E> {
AsyncOption::raw(async move { self.future.await.err() })
}
#[inline]
#[must_use]
pub async fn is_ok(self) -> bool {
self.future.await.is_ok()
}
#[inline]
#[must_use]
pub async fn is_ok_and<F>(self, f: impl FnOnce(T) -> F) -> bool
where
F: Future<Output = bool>,
{
if let Ok(val) = self.future.await {
f(val).await
} else {
false
}
}
#[inline]
#[must_use]
pub async fn is_ok_or<F>(self, f: impl FnOnce(E) -> F) -> bool
where
F: Future<Output = bool>,
{
if let Err(err) = self.future.await {
f(err).await
} else {
true
}
}
#[inline]
#[must_use]
pub async fn is_err(self) -> bool {
self.future.await.is_err()
}
#[inline]
#[must_use]
pub async fn is_err_and<F>(self, f: impl FnOnce(E) -> F) -> bool
where
F: Future<Output = bool>,
{
if let Err(err) = self.future.await {
f(err).await
} else {
false
}
}
#[inline]
#[must_use]
pub async fn is_err_or<F>(self, f: impl FnOnce(T) -> F) -> bool
where
F: Future<Output = bool>,
{
if let Ok(val) = self.future.await {
f(val).await
} else {
true
}
}
}
impl<T, E> AsyncResult<AsyncOption<T>, E> {
pub fn transpose(self) -> AsyncOption<Result<T, E>> {
AsyncOption::raw(async move {
match self.future.await {
Ok(val) => val.await.map(Ok),
Err(e) => Some(Err(e)),
}
})
}
}
impl<T, E> AsyncResult<Option<T>, E> {
pub fn transpose(self) -> AsyncOption<Result<T, E>> {
AsyncOption::raw(async move {
match self.future.await {
Ok(val) => val.map(Ok),
Err(e) => Some(Err(e)),
}
})
}
}
impl<T, E> AsyncResult<AsyncResult<T, E>, E> {
pub fn flatten(self) -> AsyncResult<T, E> {
AsyncResult {
future: Box::pin(async move {
match self.future.await {
Ok(val) => val.await,
Err(e) => Err(e),
}
}),
}
}
}
impl<T, E> AsyncResult<Result<T, E>, E> {
pub fn flatten(self) -> AsyncResult<T, E> {
AsyncResult {
future: Box::pin(async move { self.future.await? }),
}
}
}