tuppipe 0.1.4

A simple pipe operator-like implementation using tuples in Rust.
Documentation
use crate::{MarkerFnPipe, Pipe};

use ghost::phantom;

mod private {
    pub trait Sealed<T, R> {}
}

impl<P: Pipe<T, Output = R>, T, R> private::Sealed<T, R> for P {}

pub trait Voidable<T, R>: private::Sealed<T, R> + Pipe<T, Output = R> + Sized {
    #[inline]
    fn void(self) -> VoidInner<Self, T, R> {
        VoidInner(self, core::marker::PhantomData)
    }
}

impl<P: Pipe<T, Output = R>, T, R> Voidable<T, R> for P {}

pub struct VoidInner<P: Pipe<T, Output = R>, T, R>(P, core::marker::PhantomData<(T, R)>);

#[phantom]
#[allow(non_camel_case_types)]
pub struct void<T, R = ()>;

#[cfg(feature = "fn-pipes")]
impl<T, R> !MarkerFnPipe for void<T, R> {}

impl<T> Pipe<T> for void<T, ()> {
    type Output = ();

    #[inline]
    fn complete(self, _value: T) -> Self::Output {}
}

impl<P: Pipe<T, Output = R>, T, R> FnOnce<(P,)> for void<T, R> {
    type Output = VoidInner<P, T, R>;

    #[inline]
    extern "rust-call" fn call_once(self, args: (P,)) -> Self::Output {
        VoidInner(args.0, core::marker::PhantomData)
    }
}

impl<P: Pipe<T, Output = R>, T, R> Pipe<T> for VoidInner<P, T, R> {
    type Output = ();

    #[inline]
    fn complete(self, value: T) -> Self::Output {
        self.0.complete(value);
    }
}

#[test]
fn it_works() {
    let _it: () = crate::pipe(1) >> void(void).void();
}