use core::marker::PhantomData;
#[macro_export]
macro_rules! cons {
() => { () };
(rev[{$head:pat_param}] $($reversed:tt)*) => {
cons!($head, $($reversed)*)
};
(rev[$head:tt] $($reversed:tt)*) => {
cons!($head, $($reversed)*)
};
(rev[$head:expr] $($reversed:tt)*) => {
cons!($head, $($reversed)*)
};
(rev[{$head:pat_param}, $($rest:tt)*] $($reversed:tt)*) => {
cons!(rev[$($rest)*] $head, $($reversed)*)
};
(rev[$head:tt, $($rest:tt)*] $($reversed:tt)*) => {
cons!(rev[$($rest)*] $head, $($reversed)*)
};
(rev[$head:expr, $($rest:tt)*] $($reversed:tt)*) => {
cons!(rev[$($rest)*] $head, $($reversed)*)
};
(..$rest:tt) => { $rest };
(..$rest:expr) => { $rest };
({$head:pat_param}) => { ($head, ()) };
($head:tt) => { ($head, ()) };
($head:expr) => { ($head, ()) };
({$head:pat_param}, $($tail:tt)*) => {
($head, cons!($($tail)*))
};
($head:tt, $($tail:tt)*) => {
($head, cons!($($tail)*))
};
($head:expr, $($tail:tt)*) => {
($head, cons!($($tail)*))
};
}
#[macro_export]
macro_rules! Cons {
() => { () };
(..$Rest:ty) => { $Rest };
($A:ty) => { ($A, ()) };
($A:ty, $($Tail:tt)*) => {
($A, Cons!($($Tail)*))
};
}
pub trait Cons: Sized {
const LEN: usize;
#[inline]
fn len(&self) -> usize {
Self::LEN
}
#[inline]
fn is_empty(&self) -> bool {
Self::LEN == 0
}
#[inline]
fn get<T, Index>(&self) -> &T
where
Self: ConsGetter<T, Index>,
{
ConsGetter::get(self)
}
#[inline]
fn get_mut<T, Index>(&mut self) -> &mut T
where
Self: ConsGetter<T, Index>,
{
ConsGetter::get_mut(self)
}
#[inline]
fn concat<RHS: Cons>(self, rhs: RHS) -> <Self as Concat<RHS>>::Output
where
Self: Concat<RHS>,
{
Concat::concat(self, rhs)
}
#[inline]
fn rev(self) -> <Self as IntoRev>::Output
where
Self: IntoRev,
{
IntoRev::rev(self)
}
}
impl Cons for () {
const LEN: usize = 0;
}
impl<H, T: Cons> Cons for (H, T) {
const LEN: usize = 1 + T::LEN;
}
pub trait Concat<RHS> {
type Output;
fn concat(self, rhs: RHS) -> Self::Output;
}
impl<RHS> Concat<RHS> for ()
where
RHS: Cons,
{
type Output = RHS;
#[inline(always)]
fn concat(self, rhs: RHS) -> RHS {
rhs
}
}
impl<H, Tail, RHS> Concat<RHS> for (H, Tail)
where
Tail: Concat<RHS>,
RHS: Cons,
{
type Output = (H, <Tail as Concat<RHS>>::Output);
#[inline(always)]
fn concat(self, rhs: RHS) -> Self::Output {
(self.0, self.1.concat(rhs))
}
}
pub trait IntoRev {
type Output;
fn rev(self) -> Self::Output;
}
impl IntoRev for () {
type Output = ();
#[inline(always)]
fn rev(self) -> Self::Output {
self
}
}
impl<T, Tail> IntoRev for (T, Tail)
where
Tail: IntoRev,
<Tail as IntoRev>::Output: Concat<(T, ())>,
{
type Output = <<Tail as IntoRev>::Output as Concat<(T, ())>>::Output;
#[inline(always)]
fn rev(self) -> Self::Output {
self.1.rev().concat((self.0, ()))
}
}
pub trait ConsGetter<T, I> {
fn get(&self) -> &T;
fn get_mut(&mut self) -> &mut T;
}
impl<T, Tail> ConsGetter<T, Here> for (T, Tail) {
#[inline(always)]
fn get(&self) -> &T {
&self.0
}
#[inline(always)]
fn get_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<Head, Tail, FromTail, TailIndex> ConsGetter<FromTail, There<TailIndex>> for (Head, Tail)
where
Tail: ConsGetter<FromTail, TailIndex>,
{
#[inline(always)]
fn get(&self) -> &FromTail {
self.1.get()
}
#[inline(always)]
fn get_mut(&mut self) -> &mut FromTail {
self.1.get_mut()
}
}
pub struct Here;
pub struct There<T> {
marker: PhantomData<T>,
}