#[derive(Debug, Default)]
pub struct EOT;
#[macro_export]
macro_rules! nest {
($first:tt, $($tail:tt),* $(,)?) => {
($first, $crate::nest!($($tail,)*))
};
() => { $crate::EOT }
}
macro_rules! tuple_nest {
($first:ident, $($tail:ident,)*) => {
impl <$first,$($tail),*> TupleNest for ($first,$($tail,)*) {
type Nested = $crate::nest!($first,$($tail,)*);
#[inline(always)]
#[allow(non_snake_case)]
fn nest(self) -> Self::Nested {
let ($first,$($tail),*) = self;
$crate::nest!($first, $($tail,)*)
}
}
impl <$first,$($tail),*> TupleUnnest for $crate::nest!($first,$($tail,)*) {
type Unnested = ($first,$($tail,)*);
type Head = $first;
type Tail = $crate::nest!($($tail,)*);
#[inline(always)]
#[allow(non_snake_case)]
fn unnest(self) -> Self::Unnested {
let $crate::nest!($first,$($tail,)*) = self;
($first, $($tail,)*)
}
fn from(head: Self::Head, tail: Self::Tail) -> Self {
(head, tail)
}
fn split(self) -> (Self::Head, Self::Tail) {
(self.0, self.1)
}
}
}
}
pub(crate) use tuple_nest;
pub trait TupleNest {
type Nested: TupleUnnest;
fn nest(self) -> Self::Nested;
}
pub trait TupleUnnest {
type Unnested: TupleNest;
type Head;
type Tail: TupleUnnest;
fn unnest(self) -> Self::Unnested;
fn from(head: Self::Head, tail: Self::Tail) -> Self;
fn split(self) -> (Self::Head, Self::Tail);
fn head(self) -> Self::Head
where
Self: Sized,
{
self.split().0
}
fn tail(self) -> Self::Tail
where
Self: Sized,
{
self.split().1
}
}
impl TupleUnnest for EOT {
type Unnested = ();
type Head = EOT;
type Tail = EOT;
fn unnest(self) -> Self::Unnested {}
fn from(_: Self::Head, _: Self::Tail) -> Self {
EOT
}
fn split(self) -> (Self::Head, Self::Tail) {
(EOT, EOT)
}
}
impl TupleNest for () {
type Nested = EOT;
fn nest(self) -> Self::Nested {
EOT
}
}