use crate::arrow::{Arrow, Compose, Fanout, Lift, Split};
type ThenFn<S, C, G> = ArrowBuilder<Compose<S, Lift<<S as Arrow>::Out, C, G>>>;
pub struct ArrowBuilder<S>(S);
#[inline]
pub fn arrow<A, B, F>(f: F) -> ArrowBuilder<Lift<A, B, F>>
where
F: Fn(A) -> B,
{
ArrowBuilder(Lift::new(f))
}
impl<S> ArrowBuilder<S>
where
S: Arrow,
{
#[inline]
pub const fn new(arrow: S) -> Self {
ArrowBuilder(arrow)
}
#[inline]
pub fn then<G>(self, g: G) -> ArrowBuilder<Compose<S, G>>
where
G: Arrow<In = S::Out>,
{
ArrowBuilder(self.0.compose(g))
}
#[inline]
pub fn then_fn<C, G>(self, g: G) -> ThenFn<S, C, G>
where
G: Fn(S::Out) -> C,
{
ArrowBuilder(self.0.compose(Lift::new(g)))
}
#[inline]
pub fn par<G>(self, g: G) -> ArrowBuilder<Split<S, G>>
where
G: Arrow,
{
ArrowBuilder(self.0.split(g))
}
#[inline]
pub fn fanout<G>(self, g: G) -> ArrowBuilder<Fanout<S, G>>
where
G: Arrow<In = S::In>,
S::In: Clone,
{
ArrowBuilder(self.0.fanout(g))
}
#[inline]
pub fn build(self) -> S {
self.0
}
#[inline]
pub fn run(&self, input: S::In) -> S::Out {
self.0.run(input)
}
}