ufotofu 0.10.1

Abstractions for lazily consuming and producing sequences
Documentation
#[cfg(feature = "alloc")]
extern crate alloc;

#[cfg(feature = "alloc")]
use alloc::{boxed::Box, vec::Vec};

use crate::prelude::*;

/// A trait for types which can be encoded into a sequence of `Symbol`s.
///
/// More precisely, this trait may be implemented by types that belong to an [encoding relation](super). The trait specifies (via the [`Encodable::encode`] method) how to compute the encodings of arbitrary values of the implementing type, by writing a sequence of symbols into a [`BulkConsumer`].
///
/// API contracts:
///
/// - The encoding must not depend on details of the consumer such as when it yields or how many item slots it exposes at a time.
/// - Nonequal values must result in nonequal encodings.
/// - Equal values must (deterministically) result in equal encodings.
/// - No encoding must be a prefix of an encoding of a different value.
/// - For types that also implement [`Decodable`](super::Decodable) and [`Eq`], encoding a value and then decoding it must yield a value equal to the original.
///
/// ```
/// use ufotofu::codec_prelude::*;
/// use ufotofu::codec::endian::U32BE;
///
/// # pollster::block_on(async{
/// let mut buf = [99; 5];
/// let mut con = (&mut buf).into_consumer();
/// U32BE(258).encode(&mut con).await?;
///
/// assert_eq!(buf, [0, 0, 1, 2, 99]);
/// # Result::<(), ()>::Ok(())
/// # });
/// ```
///
/// <br/>Counterpart: the [`Decodable`](super::Decodable) trait.
pub trait Encodable<Symbol = u8> {
    /// Writes an encoding of `&self` into the given bulk consumer.
    ///
    /// <br/>Counterpart: the [`Decodable::decode`](super::Decodable::decode) method.
    async fn encode<C>(&self, consumer: &mut C) -> Result<(), C::Error>
    where
        C: BulkConsumer<Item = Symbol> + ?Sized;
}

impl<T, Symbol> Encodable<Symbol> for &T where T: Encodable<Symbol> {
    async fn encode<C>(&self, consumer: &mut C) -> Result<(), C::Error>
    where
        C: BulkConsumer<Item = Symbol> + ?Sized {
        (*self).encode(consumer).await
    }
}

/// Convenience methods for [`Encodable`] types. This trait is implemented automatically for all types that implement [`Encodable`].
pub trait EncodableExt<Symbol = u8>: Encodable<Symbol> {
    #[cfg(feature = "alloc")]
    /// Returns a [`Vec`] storing the encoding of `self`.
    ///
    /// ```
    /// use ufotofu::codec_prelude::*;
    /// use ufotofu::codec::endian::U32BE;
    ///
    /// # #[cfg(feature = "std")] {
    /// # pollster::block_on(async{
    /// assert_eq!(
    ///     U32BE(258).new_vec_storing_encoding().await,
    ///     vec![0, 0, 1, 2],
    /// );
    /// # });
    /// # }
    /// ```
    async fn new_vec_storing_encoding(&self) -> Vec<Symbol>
    where
        Symbol: Default,
    {
        let mut c = Vec::new().into_consumer();

        match self.encode(&mut c).await {
            Ok(()) => c.into(),
            Err(_) => unreachable!(),
        }
    }
}

impl<T, S> EncodableExt<S> for T where T: Encodable<S> {}

/// An [`Encodable`] type for which every value can precompute the number of symbols in its encoding.
///
/// API contract: a successful call to `self.encode(&mut c)` must write exactly `self.len_of_encoding()` many symbols into `c`.
///
/// ```
/// use ufotofu::codec_prelude::*;
/// use ufotofu::codec::endian::U32BE;
///
/// assert_eq!(U32BE(258).len_of_encoding(), 4);
/// ```
pub trait EncodableKnownLength<Symbol = u8>: Encodable<Symbol> {
    /// Computes the number of symbols of the encoding of `self`. A successful call to [`encode`](Encodable::encode) must feed exactly that many symbols into the bulk consumer.
    fn len_of_encoding(&self) -> usize;
}

impl<T, Symbol> EncodableKnownLength<Symbol> for &T where T: EncodableKnownLength<Symbol> {
    fn len_of_encoding(&self) -> usize {
        (*self).len_of_encoding()
    }
}

/// Convenience methods for [`Encodable`] types. This trait is implemented automatically for all types that implement [`Encodable`].
pub trait EncodableKnownLengthExt<Symbol = u8>: EncodableKnownLength<Symbol> {
    #[cfg(feature = "alloc")]
    /// Returns a [`Box<[Symbol]>`](alloc::boxed::Box) storing the encoding of `self`.
    ///
    /// More efficient than [`EncodableExt::new_vec_storing_encoding`], because the size of the required memory allocation is computed in advance via [`EncodableKnownLength::len_of_encoding`].
    ///
    /// ```
    /// use ufotofu::codec_prelude::*;
    /// use ufotofu::codec::endian::U32BE;
    ///
    /// # #[cfg(feature = "std")] {
    /// # pollster::block_on(async{
    /// assert_eq!(
    ///     U32BE(258).new_boxed_slice_storing_encoding().await,
    ///     vec![0, 0, 1, 2].into_boxed_slice(),
    /// );
    /// # });
    /// # }
    /// ```
    async fn new_boxed_slice_storing_encoding(&self) -> Box<[Symbol]>
    where
        Symbol: Default,
    {
        let mut c = Vec::with_capacity(self.len_of_encoding()).into_consumer();

        match self.encode(&mut c).await {
            Ok(()) => Vec::<Symbol>::from(c).into_boxed_slice(),
            Err(_) => unreachable!(),
        }
    }
}

impl<T, S> EncodableKnownLengthExt<S> for T where T: EncodableKnownLength<S> {}