slim-futures 0.1.0-alpha.0

Asynchronous tools that intends for smaller binary size.
Documentation
use crate::future::map::Map;
use crate::support::fns::TryFromOutputFn;
use crate::support::Try;
use core::future::Future;
use core::pin::Pin;
use core::task::{Context, Poll};
use futures_core::FusedFuture;

pin_project_lite::pin_project! {
    pub struct IntoTryFuture<Fut, T> {
        #[pin]
        inner: Map<Fut, TryFromOutputFn<T>>,
    }
}

impl<Fut, T> IntoTryFuture<Fut, T> {
    pub(crate) fn new(fut: Fut) -> Self {
        Self {
            inner: Map::new(fut, TryFromOutputFn::default()),
        }
    }
}

impl<Fut, T> Clone for IntoTryFuture<Fut, T>
where
    Fut: Clone,
{
    fn clone(&self) -> Self {
        Self {
            inner: self.inner.clone(),
        }
    }
}

impl<Fut, T> Future for IntoTryFuture<Fut, T>
where
    Fut: Future,
    T: Try<Output = Fut::Output>,
{
    type Output = T;

    fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Self::Output> {
        self.project().inner.poll(cx)
    }
}

impl<Fut, T> FusedFuture for IntoTryFuture<Fut, T>
where
    Fut: FusedFuture,
    T: Try<Output = Fut::Output>,
{
    fn is_terminated(&self) -> bool {
        self.inner.is_terminated()
    }
}

#[cfg(test)]
mod tests {
    use super::IntoTryFuture;
    use crate::future::future_ext::FutureExt;
    use crate::support::Never;
    use futures_core::FusedFuture;
    use futures_util::{future, FutureExt as _};
    use std::mem;
    use std::string::String;

    #[tokio::test]
    async fn test_into_try_future() {
        let future: IntoTryFuture<_, Result<_, String>> =
            future::ready(7_u32).slim_into_try_future::<Result<_, String>>();

        let result: Result<u32, String> = future.await;

        assert_eq!(result, Ok(7));
    }

    #[tokio::test]
    async fn test_never_error() {
        let future: IntoTryFuture<_, Result<_, Never>> = future::ready(7).slim_never_error();
        let result: Result<u32, Never> = future.await;

        assert_eq!(result, Ok(7));
    }

    #[tokio::test]
    async fn test_unit_error() {
        let future: IntoTryFuture<_, Result<_, ()>> = future::ready(7).slim_unit_error();
        let result: Result<u32, ()> = future.await;

        assert_eq!(result, Ok(7));
    }

    #[tokio::test]
    async fn test_into_try_future_clone() {
        let future: IntoTryFuture<_, Result<_, String>> = future::ready(7).slim_into_try_future::<Result<_, String>>();
        let future_2 = future.clone();

        assert_eq!(future.await, Ok(7));
        assert_eq!(future_2.await, Ok(7));
    }

    #[tokio::test]
    async fn test_into_try_future_fused_future() {
        let mut future: IntoTryFuture<_, Result<_, String>> =
            future::ready(7).slim_into_try_future::<Result<_, String>>();

        assert!(!future.is_terminated());
        assert_eq!(future.by_ref().await, Ok(7));
        assert!(future.is_terminated());
    }

    #[tokio::test]
    async fn test_into_try_future_is_slim() {
        let make_base_future = || crate::future::ready_by_copy::<u32>(2);
        let base_future = make_base_future();
        let future_1 = make_base_future().slim_unit_error();
        let future_2 = make_base_future().unit_error();

        assert_eq!(mem::size_of_val(&base_future), mem::size_of_val(&future_1));
        assert!(mem::size_of_val(&future_1) < mem::size_of_val(&future_2));
        assert_eq!(base_future.await, 2);
        assert_eq!(future_1.await, Ok(2));
        assert_eq!(future_2.await, Ok(2));
    }
}