use crate::Either;
use crate::arrow::Arrow;
use core::marker::PhantomData;
pub struct Left<F, C>(F, PhantomData<C>);
impl<F, C> Left<F, C> {
#[inline]
pub const fn new(f: F) -> Self {
Left(f, PhantomData)
}
}
impl<F, C> Arrow for Left<F, C>
where
F: Arrow,
{
type In = Either<F::In, C>;
type Out = Either<F::Out, C>;
#[inline]
fn run(&self, input: Either<F::In, C>) -> Either<F::Out, C> {
match input {
Either::Left(a) => Either::Left(self.0.run(a)),
Either::Right(c) => Either::Right(c),
}
}
}
pub struct Right<F, C>(F, PhantomData<C>);
impl<F, C> Right<F, C> {
#[inline]
pub const fn new(f: F) -> Self {
Right(f, PhantomData)
}
}
impl<F, C> Arrow for Right<F, C>
where
F: Arrow,
{
type In = Either<C, F::In>;
type Out = Either<C, F::Out>;
#[inline]
fn run(&self, input: Either<C, F::In>) -> Either<C, F::Out> {
match input {
Either::Left(c) => Either::Left(c),
Either::Right(a) => Either::Right(self.0.run(a)),
}
}
}
pub struct Choice<F, G>(F, G);
impl<F, G> Choice<F, G> {
#[inline]
pub const fn new(f: F, g: G) -> Self {
Choice(f, g)
}
}
impl<F, G> Arrow for Choice<F, G>
where
F: Arrow,
G: Arrow,
{
type In = Either<F::In, G::In>;
type Out = Either<F::Out, G::Out>;
#[inline]
fn run(&self, input: Either<F::In, G::In>) -> Either<F::Out, G::Out> {
match input {
Either::Left(a) => Either::Left(self.0.run(a)),
Either::Right(c) => Either::Right(self.1.run(c)),
}
}
}
pub struct Fanin<F, G>(F, G);
impl<F, G> Fanin<F, G> {
#[inline]
pub const fn new(f: F, g: G) -> Self {
Fanin(f, g)
}
}
impl<F, G> Arrow for Fanin<F, G>
where
F: Arrow,
G: Arrow<Out = F::Out>,
{
type In = Either<F::In, G::In>;
type Out = F::Out;
#[inline]
fn run(&self, input: Either<F::In, G::In>) -> F::Out {
match input {
Either::Left(a) => self.0.run(a),
Either::Right(c) => self.1.run(c),
}
}
}