ufotofu 0.12.0

Abstractions for lazily consuming and producing sequences
Documentation
use core::error::Error;
use core::fmt::{self, Debug, Display};

/// Everything that can go wrong when [piping](crate::pipe) a producer into a consumer.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum PipeError<ProducerError, ConsumerError> {
    /// The producer emitted an error.
    Producer(ProducerError),
    /// The consumer emitted an error when consuming an `Item`.
    Consumer(ConsumerError),
}

impl<ProducerError, ConsumerError> Display for PipeError<ProducerError, ConsumerError> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            PipeError::Producer(_) => {
                write!(
                    f,
                    "Failed to pipe a producer into a consumer, because the producer emitted an error",
                )
            }
            PipeError::Consumer(_) => {
                write!(
                    f,
                    "Failed to pipe a producer into a consumer, because the consumer emitted an error",
                )
            }
        }
    }
}

impl<ProducerError, ConsumerError> Error for PipeError<ProducerError, ConsumerError>
where
    ProducerError: 'static + Error,
    ConsumerError: 'static + Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            PipeError::Producer(err) => Some(err),
            PipeError::Consumer(err) => Some(err),
        }
    }
}

/// An error emitted when a consumer is tasked to consume at least some number of items, but it could only consume a lower number of items.
///
/// `E` is the [`Error`](crate::Consumer::Error) type of the consumer.
///
/// <br/>Counterpart: the [`ProduceAtLeastError`] type.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ConsumeAtLeastError<E> {
    /// The number of items that were consumed.
    pub count: usize,
    /// Why did the consumer stop accepting items?
    pub reason: E,
}

#[cfg(feature = "std")]
impl<E> Error for ConsumeAtLeastError<E>
where
    E: 'static + Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        Some(&self.reason)
    }
}

impl<E> Display for ConsumeAtLeastError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "The consumer failed to consume sufficiently many items, it only consumed {} items",
            self.count
        )
    }
}

impl<E> ConsumeAtLeastError<E> {
    /// Consumes `self` and returns `self.reason`, effectively discarding `self.count`.
    pub fn into_reason(self) -> E {
        self.reason
    }
}

/// An error emitted when a producer is tasked to produce at least some number of items, but it could only produce a lower number of items.
///
/// `F` is the [`Final`](crate::Producer::Final) type of the consumer, `E` is the [`Error`](crate::Producer::Error) type of the producer.
///
/// <br/>Counterpart: the [`ConsumeAtLeastError`] type.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ProduceAtLeastError<F, E> {
    /// How many items were produced.
    pub count: usize,
    /// Did producing enough items fail because the producer reached its final value, or because it yielded an error?
    pub reason: Result<F, E>,
}

impl<F, E> Error for ProduceAtLeastError<F, E>
where
    F: Debug,
    E: 'static + Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match &self.reason {
            Ok(_) => None,
            Err(err) => Some(err),
        }
    }
}

impl<F, E> Display for ProduceAtLeastError<F, E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.reason {
            Ok(_) => {
                write!(f, "The producer was unable to produce sufficiently many items due to emitting its final value; it stopped after producing {} items", self.count)
            }
            Err(_) => {
                write!(f, "The producer was unable to produce sufficiently many items due to an error; it stopped after producing {} items", self.count)
            }
        }
    }
}

impl<F, E> ProduceAtLeastError<F, E> {
    /// Consumes `self` and returns `self.reason`, effectively discarding `self.count`.
    pub fn into_reason(self) -> Result<F, E> {
        self.reason
    }
}

/// An error emitted when a consumer has consumed too many items.
///
/// `E` is the [`Error`](crate::Consumer::Error) type of the consumer.
///
/// <br/>Counterpart: the [`ProduceLimitError`] type.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ConsumeLimitError<E> {
    /// Inner Consumer yielded an error.
    Inner(E),
    /// Consumer was fed one item too much.
    LimitReached,
}

impl<E> Error for ConsumeLimitError<E>
where
    E: 'static + Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            ConsumeLimitError::Inner(err) => Some(err),
            ConsumeLimitError::LimitReached => None,
        }
    }
}

impl<E> Display for ConsumeLimitError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ConsumeLimitError::Inner(_) => write!(
                f,
                "Consumer returned an inner error before reaching the limit"
            ),
            ConsumeLimitError::LimitReached => write!(f, "Consumer reached it's limit"),
        }
    }
}

/// An error emitted when a producer is tasked to produce at most some number of items, but instead produces a higher number of items.
///
/// `E` is the [`Error`](crate::Producer::Error) type of the producer
///
/// <br/>Counterpart: the [`ConsumeLimitError`] type.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ProduceLimitError<E> {
    /// Inner producer yielded an error
    Inner(E),
    /// Producer produced too many items
    LimitReached,
}

impl<E> Error for ProduceLimitError<E>
where
    E: 'static + Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            ProduceLimitError::Inner(err) => Some(err),
            ProduceLimitError::LimitReached => None,
        }
    }
}

impl<E> Display for ProduceLimitError<E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ProduceLimitError::Inner(_) => write!(
                f,
                "Producer returned an inner error before reaching the limit"
            ),
            ProduceLimitError::LimitReached => write!(f, "Producer reached it's limit"),
        }
    }
}

/// An error emitted when a function expects a final value, but gets a normal item instead.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ExpectedFinalError<Item, Error> {
    /// Got a normal item instead of a final value.
    Item(Item),
    /// Got an error instead of a final value.
    Error(Error),
}

#[cfg(feature = "std")]
impl<F, E> Error for ExpectedFinalError<F, E>
where
    F: Debug,
    E: 'static + Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            ExpectedFinalError::Item(_) => None,
            ExpectedFinalError::Error(err) => Some(err),
        }
    }
}

impl<F, E> Display for ExpectedFinalError<F, E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ExpectedFinalError::Item(_) => {
                write!(
                    f,
                    "A function expected a final value, but got a regular item instead"
                )
            }
            ExpectedFinalError::Error(_) => {
                write!(
                    f,
                    "A function expected a final value, but got an error instead"
                )
            }
        }
    }
}

/// The type of errors which may be emitted by a [`ProduceWhile`](crate::producer::ProduceWhile) or [`ConsumeWhile`](crate::consumer::ConsumeWhile) processor adaptor.
///
/// The type `T` is the `Item` type of the wrapped processor, while the type `E` is the corresponding `Error` type.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ProcessWhileError<T, E> {
    /// The producer encountered an item for which the predicate returned `false`.
    PredicateFailed(T),
    /// The inner producer reported an error.
    Inner(E),
}

#[cfg(feature = "std")]
impl<T, E> Error for ProcessWhileError<T, E>
where
    T: Debug,
    E: 'static + Error,
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            ProcessWhileError::PredicateFailed(_) => None,
            ProcessWhileError::Inner(err) => Some(err),
        }
    }
}

impl<T, E> Display for ProcessWhileError<T, E> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ProcessWhileError::PredicateFailed(_rejected) => {
                write!(
                    f,
                    "The processor encountered an item which was rejected by the predicate"
                )
            }
            ProcessWhileError::Inner(_err) => {
                write!(
                    f,
                    "The wrapped processor reported an error before any item was rejected by the predicate"
                )
            }
        }
    }
}