ufotofu 0.10.1

Abstractions for lazily consuming and producing sequences
Documentation
use core::fmt;
use core::marker::PhantomData;

use crate::prelude::*;

/// A (bulk) consumer wrapper which passes final values through a function before forwarding them to the wrapped consumer.
///
/// Use the `AsRef<C>` and `AsMut<C>` impls to access the wrapped consumer.
///
/// Created via [`ConsumerExt::to_map_final`].
///
/// <br/>Counterpart: the [producer::MapFinal] type.
pub struct MapFinal<C, Fun, NewFinal> {
    inner: C,
    fun: Option<Fun>,
    phantom: PhantomData<NewFinal>,
}

impl<C, Fun, NewFinal> fmt::Debug for MapFinal<C, Fun, NewFinal>
where
    C: fmt::Debug,
    Fun: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MapFinal")
            .field("inner", &self.inner)
            .field("fun", &self.fun)
            .finish()
    }
}

impl<C, Fun, NewFinal> MapFinal<C, Fun, NewFinal> {
    pub(crate) fn new(inner: C, fun: Fun) -> Self {
        Self {
            inner,
            fun: Some(fun),
            phantom: PhantomData,
        }
    }

    /// Consumes `self` and returns the wrapped consumer.
    pub fn into_inner(self) -> C {
        self.inner
    }
}

impl<C, Fun, NewFinal> AsRef<C> for MapFinal<C, Fun, NewFinal> {
    fn as_ref(&self) -> &C {
        &self.inner
    }
}

impl<C, Fun, NewFinal> AsMut<C> for MapFinal<C, Fun, NewFinal> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.inner
    }
}

impl<C, Fun, NewFinal> Consumer for MapFinal<C, Fun, NewFinal>
where
    C: Consumer,
    Fun: FnOnce(NewFinal) -> C::Final,
{
    type Item = C::Item;
    type Final = NewFinal;
    type Error = C::Error;

    async fn consume(&mut self, val: Either<Self::Item, Self::Final>) -> Result<(), Self::Error> {
        match val {
            Left(item) => self.inner.consume_item(item).await,
            Right(fin) => {
                self.inner
                    .consume_final((self
                        .fun
                        .take()
                        .expect("Must not use a consumer after writing a final value to it"))(
                        fin,
                    ))
                    .await
            }
        }
    }

    async fn flush(&mut self) -> Result<(), Self::Error> {
        self.inner.flush().await
    }
}

impl<C, Fun, NewFinal> BulkConsumer for MapFinal<C, Fun, NewFinal>
where
    C: BulkConsumer,
    Fun: FnOnce(NewFinal) -> C::Final,
{
    async fn expose_slots_gracefully<F, R>(&mut self, f: F) -> Result<R, (F, Self::Error)>
    where
        F: AsyncFnOnce(&mut [Self::Item]) -> (usize, R),
    {
        self.inner.expose_slots_gracefully(f).await
    }
}

/// A (bulk) consumer wrapper which passes final values through an async function before forwarding them to the wrapped consumer.
///
/// Use the `AsRef<C>` and `AsMut<C>` impls to access the wrapped consumer.
///
/// Created via [`ConsumerExt::to_map_async_final`].
///
/// <br/>Counterpart: the [producer::MapAsyncFinal] type.
pub struct MapAsyncFinal<C, Fun, NewFinal> {
    inner: C,
    fun: Option<Fun>,
    phantom: PhantomData<NewFinal>,
}

impl<C, Fun, NewFinal> fmt::Debug for MapAsyncFinal<C, Fun, NewFinal>
where
    C: fmt::Debug,
    Fun: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MapAsyncFinal")
            .field("inner", &self.inner)
            .field("fun", &self.fun)
            .finish()
    }
}

impl<C, Fun, NewFinal> MapAsyncFinal<C, Fun, NewFinal> {
    pub(crate) fn new(inner: C, fun: Fun) -> Self {
        Self {
            inner,
            fun: Some(fun),
            phantom: PhantomData,
        }
    }

    /// Consumes `self` and returns the wrapped consumer.
    pub fn into_inner(self) -> C {
        self.inner
    }
}

impl<C, Fun, NewFinal> AsRef<C> for MapAsyncFinal<C, Fun, NewFinal> {
    fn as_ref(&self) -> &C {
        &self.inner
    }
}

impl<C, Fun, NewFinal> AsMut<C> for MapAsyncFinal<C, Fun, NewFinal> {
    fn as_mut(&mut self) -> &mut C {
        &mut self.inner
    }
}

impl<C, Fun, NewFinal> Consumer for MapAsyncFinal<C, Fun, NewFinal>
where
    C: Consumer,
    Fun: AsyncFnOnce(NewFinal) -> C::Final,
{
    type Item = C::Item;
    type Final = NewFinal;
    type Error = C::Error;

    async fn consume(&mut self, val: Either<Self::Item, Self::Final>) -> Result<(), Self::Error> {
        match val {
            Left(item) => self.inner.consume_item(item).await,
            Right(fin) => {
                self.inner
                    .consume_final(
                        (self
                            .fun
                            .take()
                            .expect("Must not use a consumer after writing a final value to it"))(
                            fin,
                        )
                        .await,
                    )
                    .await
            }
        }
    }

    async fn flush(&mut self) -> Result<(), Self::Error> {
        self.inner.flush().await
    }
}

impl<C, Fun, NewFinal> BulkConsumer for MapAsyncFinal<C, Fun, NewFinal>
where
    C: BulkConsumer,
    Fun: AsyncFnOnce(NewFinal) -> C::Final,
{
    async fn expose_slots_gracefully<F, R>(&mut self, f: F) -> Result<R, (F, Self::Error)>
    where
        F: AsyncFnOnce(&mut [Self::Item]) -> (usize, R),
    {
        self.inner.expose_slots_gracefully(f).await
    }
}