pub trait HList = HasLength;
#[derive(Debug,Clone,Copy)]
pub struct Nil;
#[derive(Debug,Clone,Copy)]
#[allow(missing_docs)]
pub struct Cons<Head,Tail>(pub Head, pub Tail);
#[macro_export]
macro_rules! new {
($(,)*) => { $crate::Nil };
($t:expr $(,$($ts:expr),*)?) => {
$crate::Cons($t,$crate::new!{$($($ts),*)?})
}
}
#[macro_export]
macro_rules! pat {
($(,)*) => { $crate::Nil };
($t:pat $(,$($ts:pat),*)?) => {
$crate::Cons($t,$crate::pat!{$($($ts),*)?})
}
}
#[macro_export]
macro_rules! ty {
($(,)*) => { $crate::Nil };
($t:ty $(,$($ts:ty),*)?) => {
$crate::Cons<$t,$crate::ty!{$($($ts),*)?}>
}
}
#[allow(missing_docs)]
pub trait HasLength {
const LEN : usize;
fn len() -> usize {
Self::LEN
}
}
pub const fn len<T:HasLength>() -> usize {
<T as HasLength>::LEN
}
impl HasLength for Nil { const LEN : usize = 0; }
impl<H,T:HasLength> HasLength for Cons<H,T> { const LEN : usize = 1 + len::<T>(); }
#[allow(missing_docs)]
pub trait KnownHead {
type Head;
}
pub type Head<T> = <T as KnownHead>::Head;
#[allow(missing_docs)]
pub trait GetHead : KnownHead {
fn head(&self) -> &Self::Head;
}
#[allow(missing_docs)]
pub trait GetHeadMut : KnownHead {
fn head_mut(&mut self) -> &mut Self::Head;
}
#[allow(missing_docs)]
pub trait GetHeadClone : KnownHead {
fn head_clone(&self) -> Self::Head;
}
impl<T> GetHeadClone for T
where T:GetHead, Head<T>:Clone {
default fn head_clone(&self) -> Self::Head {
self.head().clone()
}
}
impl<H,T> KnownHead for Cons<H,T> {
type Head = H;
}
impl<H,T> GetHead for Cons<H,T> {
fn head(&self) -> &Self::Head {
&self.0
}
}
impl<H,T> GetHeadMut for Cons<H,T> {
fn head_mut(&mut self) -> &mut Self::Head {
&mut self.0
}
}
#[allow(missing_docs)]
pub trait KnownTail {
type Tail;
}
pub type Tail<T> = <T as KnownTail>::Tail;
#[allow(missing_docs)]
pub trait GetTail : KnownTail {
fn tail(&self) -> &Self::Tail;
}
#[allow(missing_docs)]
pub trait GetTailMut : KnownTail {
fn tail_mut(&mut self) -> &mut Self::Tail;
}
#[allow(missing_docs)]
pub trait GetTailClone : KnownTail {
fn tail_clone(&self) -> Self::Tail;
}
impl<T> GetTailClone for T
where T:GetTail, Tail<T>:Clone {
default fn tail_clone(&self) -> Self::Tail {
self.tail().clone()
}
}
impl<H,T> KnownTail for Cons<H,T> {
type Tail = T;
}
impl<H,T> GetTail for Cons<H,T> {
fn tail(&self) -> &Self::Tail {
&self.1
}
}
impl<H,T> GetTailMut for Cons<H,T> {
fn tail_mut(&mut self) -> &mut Self::Tail {
&mut self.1
}
}
#[allow(missing_docs)]
pub trait KnownLast {
type Last;
}
pub type Last<T> = <T as KnownLast>::Last;
#[allow(missing_docs)]
pub trait GetLast : KnownLast {
fn last(&self) -> &Self::Last;
}
#[allow(missing_docs)]
pub trait GetLastMut : KnownLast {
fn last_mut(&mut self) -> &mut Self::Last;
}
#[allow(missing_docs)]
pub trait GetLastClone : KnownLast {
fn last_clone(&self) -> Self::Last;
}
impl<T> GetLastClone for T
where T:GetLast, Last<T>:Clone {
default fn last_clone(&self) -> Self::Last {
self.last().clone()
}
}
impl<H> KnownLast for Cons<H,Nil> { type Last = H; }
impl<H,T:KnownLast> KnownLast for Cons<H,T> { type Last = Last<T>; }
impl<H> GetLast for Cons<H,Nil> {
fn last(&self) -> &Self::Last {
&self.0
}
}
impl<H> GetLastMut for Cons<H,Nil> {
fn last_mut(&mut self) -> &mut Self::Last {
&mut self.0
}
}
impl<H,T:GetLast> GetLast for Cons<H,T> {
fn last(&self) -> &Self::Last {
self.tail().last()
}
}
impl<H,T:GetLastMut> GetLastMut for Cons<H,T> {
fn last_mut(&mut self) -> &mut Self::Last {
self.tail_mut().last_mut()
}
}
#[allow(missing_docs)]
pub trait KnownInit {
type Init;
}
pub type Init<T> = <T as KnownInit>::Init;
#[allow(missing_docs)]
pub trait GetInitClone : KnownInit {
fn init_clone(&self) -> Self::Init;
}
impl<H> KnownInit for Cons<H,Nil> { type Init = Nil; }
impl<H,T:KnownInit> KnownInit for Cons<H,T> { type Init = Cons<H,Init<T>>; }
impl<H> GetInitClone for Cons<H,Nil> {
fn init_clone(&self) -> Self::Init {
Nil
}
}
impl<H:Clone,T:GetInitClone> GetInitClone for Cons<H,T> {
fn init_clone(&self) -> Self::Init {
Cons(self.head().clone(),self.tail().init_clone())
}
}
#[allow(missing_docs)]
pub trait PushBack<T> : Sized {
type Output : KnownLast<Last=T> + KnownInit<Init=Self>;
fn push_back(self,t:T) -> Self::Output;
}
impl<X> PushBack<X> for Nil {
type Output = Cons<X,Nil>;
#[inline(always)]
fn push_back(self,x:X) -> Self::Output {
Cons(x,Nil)
}
}
impl<X,H,T> PushBack<X> for Cons<H,T>
where T:PushBack<X> {
type Output = Cons<H,<T as PushBack<X>>::Output>;
#[inline(always)]
fn push_back(self,x:X) -> Self::Output {
let Cons(head,tail) = self;
Cons(head,tail.push_back(x))
}
}
#[allow(missing_docs)]
pub trait PopBack : KnownLast + KnownInit {
fn pop_back(self) -> (Self::Last,Self::Init);
}
impl<H> PopBack for Cons<H,Nil> {
fn pop_back(self) -> (Self::Last,Self::Init) {
(self.0,Nil)
}
}
impl<H,T> PopBack for Cons<H,T>
where T:PopBack {
fn pop_back(self) -> (Self::Last,Self::Init) {
let (last,tail) = self.1.pop_back();
(last,Cons(self.0,tail))
}
}