ufotofu 0.10.1

Abstractions for lazily consuming and producing sequences
Documentation
use crate::prelude::*;

/// A (bulk) producer wrapper which changes the final (type) of the wrapped producer, by passing final values through a function.
///
/// Use the `AsRef<P>` and `AsMut<P>` impls to access the wrapped producer.
///
/// Created via [`ProducerExt::to_map_final`].
///
/// <br/>Counterpart: the [consumer::MapError] type.
#[derive(Debug)]

pub struct MapFinal<P, Fun> {
    inner: P,
    fun: Option<Fun>,
}

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

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

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

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

impl<P, Fun, NewFin> Producer for MapFinal<P, Fun>
where
    P: Producer,
    Fun: FnOnce(P::Final) -> NewFin,
{
    type Item = P::Item;
    type Final = NewFin;
    type Error = P::Error;

    async fn produce(&mut self) -> Result<Either<Self::Item, Self::Final>, Self::Error> {
        Ok(self.inner.produce().await?.map_right(|fin| {
            (self
                .fun
                .take()
                .expect("Must not use a producer after it emitted its final value"))(fin)
        }))
    }

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

impl<P, Fun, NewFin> BulkProducer for MapFinal<P, Fun>
where
    P: BulkProducer,
    Fun: FnOnce(P::Final) -> NewFin,
{
    async fn expose_items_gracefully<F, R>(
        &mut self,
        f: F,
    ) -> Result<Either<R, (F, Self::Final)>, (F, Self::Error)>
    where
        F: AsyncFnOnce(&[Self::Item]) -> (usize, R),
    {
        Ok(self
            .inner
            .expose_items_gracefully(f)
            .await?
            .map_right(|(f, fin)| {
                (
                    f,
                    (self
                        .fun
                        .take()
                        .expect("Must not use a producer after it emitted its final value"))(
                        fin
                    ),
                )
            }))
    }
}

/// A (bulk) producer wrapper which changes the final (type) of the wrapped producer, by passing final values through an async function.
///
/// Use the `AsRef<P>` and `AsMut<P>` impls to access the wrapped producer.
///
/// Created via [`ProducerExt::to_map_async_final`].
///
/// <br/>Counterpart: the [consumer::MapAsyncFinal] type.
#[derive(Debug)]

pub struct MapAsyncFinal<P, Fun> {
    inner: P,
    fun: Option<Fun>,
}

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

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

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

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

impl<P, Fun, NewFin> Producer for MapAsyncFinal<P, Fun>
where
    P: Producer,
    Fun: AsyncFnOnce(P::Final) -> NewFin,
{
    type Item = P::Item;
    type Final = NewFin;
    type Error = P::Error;

    async fn produce(&mut self) -> Result<Either<Self::Item, Self::Final>, Self::Error> {
        match self.inner.produce().await? {
            Left(item) => Ok(Left(item)),
            Right(fin) => Ok(Right(
                (self
                    .fun
                    .take()
                    .expect("Must not use a producer after it emitted its final value"))(
                    fin
                )
                .await,
            )),
        }
    }

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

impl<P, Fun, NewFin> BulkProducer for MapAsyncFinal<P, Fun>
where
    P: BulkProducer,
    Fun: AsyncFnOnce(P::Final) -> NewFin,
{
    async fn expose_items_gracefully<F, R>(
        &mut self,
        f: F,
    ) -> Result<Either<R, (F, Self::Final)>, (F, Self::Error)>
    where
        F: AsyncFnOnce(&[Self::Item]) -> (usize, R),
    {
        match self.inner.expose_items_gracefully(f).await? {
            Left(ret) => Ok(Left(ret)),
            Right((f, fin)) => Ok(Right((
                f,
                (self
                    .fun
                    .take()
                    .expect("Must not use a producer after it emitted its final value"))(
                    fin
                )
                .await,
            ))),
        }
    }
}