ufotofu 0.10.1

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

use crate::codec_prelude::*;

/// Turns a [`BulkConsumer`] of type `C` into a [`Consumer`] of [`Encodable`] `T`s.
///
/// ```
/// use ufotofu::codec_prelude::*;
/// use codec::endian::U32BE;
///
/// # pollster::block_on(async{
/// let mut buf = [99u8; 8];
/// let byte_consumer = (&mut buf).into_consumer();
/// let mut u32_consumer = codec::encoder::<_, U32BE>(byte_consumer);
///
/// u32_consumer.consume_item(U32BE(258)).await?;
/// u32_consumer.consume_item(U32BE(17)).await?;
///
/// assert_eq!(buf, [0, 0, 1, 2, 0, 0, 0, 17]);
/// # Result::<(), ()>::Ok(())
/// # });
/// ```
///
/// <br/>Counterpart: the [`decoder`](super::decoder) function.
pub fn encoder<C, T>(consumer: C) -> Encoder<C, T> {
    Encoder::new(consumer)
}

/// A [`Consumer`] of [`Encodable`] values of type `T`, encoding consumed values into an underlying [`BulkConsumer`] of type `C`.
///
/// See [`encoder`].
///
/// <br/>Counterpart: the [`Decoder`](super::Decoder) type.
pub struct Encoder<C, T> {
    inner: C,
    phantom: PhantomData<T>,
}

impl<C, T> Encoder<C, T> {
    // Creates a new [`Encoder`], encoding into the given `consumer`.
    fn new(consumer: C) -> Self {
        Self {
            inner: consumer,
            phantom: PhantomData,
        }
    }

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

impl<C, T, Symbol> Consumer for Encoder<C, T>
where
    C: BulkConsumer<Item = Symbol>,
    T: Encodable<Symbol>,
{
    type Item = T;

    type Final = C::Final;

    type Error = C::Error;

    async fn consume(&mut self, value: Either<Self::Item, Self::Final>) -> Result<(), Self::Error> {
        match value {
            Left(item) => self.inner.consume_encoded(&item).await,
            Right(fin) => self.inner.consume_final(fin).await,
        }
    }

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