use sealed::Len;
use seq_macro::seq;
const _TODO: () = ();
mod sealed {
pub trait Len {
const LEN: usize;
}
}
pub struct L<const N: usize>;
impl<const N: usize> Len for L<N> {
const LEN: usize = N;
}
pub trait Length {
type Len: sealed::Len;
fn len() -> usize {
<Self::Len as Len>::LEN
}
}
pub trait InRange<const N: usize, L>: Length {}
pub trait Chain<const N: usize>
where
Self: Length,
Self: InRange<N, <Self as Length>::Len>,
{
type In<'a>;
type Out<'a>;
fn chain(input: Self::In<'_>) -> Self::Out<'_>;
}
pub trait Link<const N: usize> {
type In<'a>;
type Out<'a>;
fn link<'a>(input: Self::In<'a>) -> Self::Out<'a>;
}
impl<T: Chain<0>> Link<1> for T {
type In<'a> = <T as Chain<0>>::In<'a>;
type Out<'a> = <T as Chain<0>>::Out<'a>;
fn link(input: Self::In<'_>) -> Self::Out<'_> {
return <T as Chain<0>>::chain(input);
}
}
seq!(N in 1..=32 {
seq!(I in 0..N {
impl<T: Length<Len = L<N>>> InRange<I, L<N>> for T {}
});
});
seq!(N in 2..=32 {
impl<T> Link<N> for T
where
T: Chain<0>,
for<'a> T: Link<{N - 1}, In<'a> = <T as Chain<0>>::In<'a>>,
for<'a> T: Chain<{N - 1}, In<'a> = <T as Link<{N - 1}>>::Out<'a>>,
{
type In<'a> = <T as Chain<0>>::In<'a>;
type Out<'a> = <T as Chain<{N - 1}>>::Out<'a>;
fn link(input: Self::In<'_>) -> Self::Out<'_> {
let out = <T as Link<{N - 1}>>::link(input);
return <T as Chain<{N - 1}>>::chain(out);
}
}
});
pub trait Cascade {
type In<'a>;
type Out<'a>;
fn cascade(input: Self::In<'_>) -> Self::Out<'_>;
}
impl<const N: usize, T: Link<N> + Length<Len = L<N>>> Cascade for T {
type In<'a> = T::In<'a>;
type Out<'a> = T::Out<'a>;
fn cascade(input: Self::In<'_>) -> Self::Out<'_> {
return <T as Link::<N>>::link(input);
}
}