error2 0.13.2

A simple error handle library for Rust
Documentation
use std::{
    marker::PhantomData,
    pin::Pin,
    task::{Context, Poll},
};

use futures_core::Stream;
use pin_project_lite::pin_project;

use crate::{Attach, Location};

impl<T, W> Attach<AttachStream<Self, W>> for T
where
    T: Stream,
    T::Item: Attach<W>,
{
    #[inline]
    fn attach_location(self, location: Location) -> AttachStream<Self, W> {
        AttachStream {
            inner: self,
            location,
            phantom: PhantomData,
        }
    }
}

pin_project! {
    /// Stream adapter that attaches location to errors.
    ///
    /// # Example
    ///
    /// ```
    /// use error2::prelude::*;
    /// use futures_core::Stream;
    /// use std::pin::Pin;
    /// use std::task::{Context, Poll};
    ///
    /// # struct TestStream;
    /// # impl Stream for TestStream {
    /// #     type Item = Result<i32, BoxedError2>;
    /// #     fn poll_next(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Option<Self::Item>> {
    /// #         Poll::Ready(None)
    /// #     }
    /// # }
    /// # fn some_stream() -> TestStream { TestStream }
    /// #
    /// async fn process_stream() -> Result<(), BoxedError2> {
    ///     let mut stream = some_stream().attach(); // Location recorded here
    ///
    ///     // In a real async runtime:
    ///     // while let Some(item) = stream.next().await {
    ///     //     let value = item?;
    ///     //     // Process value...
    ///     // }
    ///
    ///     Ok(())
    /// }
    /// ```
    #[derive(Debug, Clone, Copy)]
    #[must_use = "streams do nothing unless polled"]
    pub struct AttachStream<S, W> {
        #[pin]
        inner: S,
        location: Location,
        phantom: PhantomData<W>,
    }
}

impl<S, W> Stream for AttachStream<S, W>
where
    S: Stream,
    S::Item: Attach<W>,
{
    type Item = W;

    #[inline]
    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        let this = self.project();

        match this.inner.poll_next(cx) {
            Poll::Ready(Some(item)) => Poll::Ready(Some(item.attach_location(*this.location))),
            Poll::Ready(None) => Poll::Ready(None),
            Poll::Pending => Poll::Pending,
        }
    }
}