unipipe 0.1.0

A simple Rust pipe abstraction that extends to iterator and stream.
Documentation
#[macro_export]
macro_rules! extend_iterator {
    ($visibility:vis $struct_name:ident) => {
        ::paste::paste! {
            $crate::extend_iterator!($visibility $struct_name, [<$struct_name:snake>]);
        }
    };
    ($visibility:vis $struct_name:ident, $method_name:ident) => {
        ::paste::paste! {
            $visibility trait [<$struct_name UniPipeIteratorExt>]:
                Iterator<Item = <$struct_name as $crate::UniPipe>::Input> + Sized
            {
                fn $method_name(
                    mut self,
                ) -> impl Iterator<Item = <$struct_name as $crate::UniPipe>::Output> {
                    let mut pipe = <$struct_name as Default>::default();
                    let mut completed = false;

                    std::iter::from_fn(move || {
                        if completed {
                            return None;
                        }

                        while let Some(input) = self.next() {
                            if let Some(output) = pipe.next(Some(input)) {
                                return Some(output);
                            }
                        }

                        completed = true;

                        if let Some(output) = pipe.next(None) {
                            return Some(output);
                        }

                        None
                    })
                }
            }

            impl<TIterator> [<$struct_name UniPipeIteratorExt>] for TIterator where
                TIterator: Iterator<Item = <$struct_name as $crate::UniPipe>::Input>
            {}
        }
    };
}

#[macro_export]
macro_rules! extend_try_iterator {
    ($visibility:vis $struct_name:ident) => {
        ::paste::paste! {
            $crate::extend_try_iterator!($visibility $struct_name, [<try_ $struct_name:snake>]);
        }
    };
    ($visibility:vis $struct_name:ident, $method_name:ident) => {
        ::paste::paste! {
            $visibility trait [<$struct_name UniPipeIteratorTryExt>]<TError>:
                Iterator<Item = Result<<$struct_name as $crate::UniPipe>::Input, TError>> + Sized
            {
                fn $method_name(mut self) -> impl Iterator<Item = Result<<$struct_name as $crate::UniPipe>::Output, TError>> {
                    let mut pipe = <$struct_name as Default>::default();
                    let mut completed = false;

                    std::iter::from_fn(move || {
                        if completed {
                            return None;
                        }

                        while let Some(input) = self.next() {
                            match input {
                                Ok(input) => {
                                    if let Some(output) = pipe.next(Some(input)) {
                                        return Some(Ok(output));
                                    }
                                }
                                Err(error) => return Some(Err(error)),
                            }
                        }

                        completed = true;

                        if let Some(output) = pipe.next(None) {
                            return Some(Ok(output));
                        }

                        None
                    })
                }
            }

            impl<TIterator, TError> [<$struct_name UniPipeIteratorTryExt>]<TError> for TIterator where
                TIterator: Iterator<Item = Result<<$struct_name as $crate::UniPipe>::Input, TError>>
            {}
        }
    };
}