use varihappy_macros::{
repeat, tuple_expr_reverse, tuple_new, tuple_reverse, tuple_trait_def, type_to_field_access,
};
pub trait Tuple {
type AsRef<'a>: Tuple
where
Self: 'a;
type AsMut<'a>: Tuple
where
Self: 'a;
type Reversed: Tuple;
fn as_ref(&self) -> Self::AsRef<'_>;
fn as_mut(&mut self) -> Self::AsMut<'_>;
fn rev(self) -> Self::Reversed;
}
pub trait Tuple1: Tuple {
type Item0;
type Rest: Tuple;
fn into_0(self) -> Self::Item0;
fn split_into(self) -> (Self::Item0, Self::Rest);
fn into_rest(self) -> Self::Rest;
}
impl Tuple for () {
type AsRef<'a>
= ()
where
Self: 'a;
type AsMut<'a>
= ()
where
Self: 'a;
type Reversed = ();
fn as_ref(&self) -> Self::AsRef<'_> {}
fn as_mut(&mut self) -> Self::AsMut<'_> {}
fn rev(self) -> Self::Reversed {}
}
impl<A> Tuple for (A,) {
type AsRef<'a>
= (&'a A,)
where
Self: 'a;
type AsMut<'a>
= (&'a mut A,)
where
Self: 'a;
type Reversed = (A,);
fn as_ref(&self) -> Self::AsRef<'_> {
(&self.0,)
}
fn as_mut(&mut self) -> Self::AsMut<'_> {
(&mut self.0,)
}
fn rev(self) -> Self::Reversed {
(self.0,)
}
}
impl<A> Tuple1 for (A,) {
type Item0 = A;
type Rest = ();
fn into_0(self) -> Self::Item0 {
self.0
}
fn split_into(self) -> (Self::Item0, Self::Rest) {
(self.0, ())
}
fn into_rest(self) -> Self::Rest {}
}
macro_rules! tuple_apply {
(($($letter: ident,)*), $other: ident) => {
$other!(($($letter,)*))
};
}
macro_rules! tuple_rest {
((A, $($letter: ident,)*)) => {
($($letter,)*)
};
}
macro_rules! tuple_expr_apply {
($this: ident, ($($letter: ident,)*), $other: ident) => {
$other!($this, ($($letter,)*))
};
}
macro_rules! tuple_expr_ref {
($this: ident, ($($letter: ident,)*)) => {
{
let this = $this;
($(&type_to_field_access!($letter),)*)
}
}
}
macro_rules! tuple_expr_mut {
($this: ident, ($($letter: ident,)*)) => {
{
let this = $this;
($(&mut type_to_field_access!($letter),)*)
}
}
}
macro_rules! tuple_expr_rest {
($this: ident, (A, $($letter: ident,)*)) => {
{
let this = $this;
($(type_to_field_access!($letter),)*)
}
}
}
macro_rules! tuple_expr_split {
($this: ident, (A, $($letter: ident,)*)) => {
{
let this = $this;
(this.0, ($(type_to_field_access!($letter),)*))
}
}
}
macro_rules! impl_tuple_inner {
(($($letter: ident,)*)) => {
impl<$($letter),*> Tuple for ($($letter,)*) {
type AsRef<'a> = ($(&'a $letter,)*) where Self: 'a;
type AsMut<'a> = ($(&'a mut $letter,)*) where Self: 'a;
type Reversed = tuple_apply!(($($letter,)*), tuple_reverse);
fn as_ref(&self) -> Self::AsRef<'_> {
tuple_expr_apply!(self, ($($letter,)*), tuple_expr_ref)
}
fn as_mut(&mut self) -> Self::AsMut<'_> {
tuple_expr_apply!(self, ($($letter,)*), tuple_expr_mut)
}
fn rev(self) -> Self::Reversed {
tuple_expr_apply!(self, ($($letter,)*), tuple_expr_reverse)
}
}
impl<$($letter),*> Tuple1 for ($($letter,)*) {
type Item0 = A;
type Rest = tuple_apply!(($($letter,)*), tuple_rest);
fn into_0(self) -> Self::Item0 {
self.0
}
fn split_into(self) -> (Self::Item0, Self::Rest) {
tuple_expr_apply!(self, ($($letter,)*), tuple_expr_split)
}
fn into_rest(self) -> Self::Rest {
tuple_expr_apply!(self, ($($letter,)*), tuple_expr_rest)
}
}
};
}
macro_rules! impl_tuple {
($number: literal) => {
tuple_new! { $number, impl_tuple_inner }
};
}
macro_rules! tuple_trait_inner {
(trait $trait_name: ident for $trait_minus1: ident {
type $item_name: ident;
fn $item_getter: ident;
}) => {
pub trait $trait_name: $trait_minus1 {
type $item_name;
type Rest: Tuple;
fn $item_getter(self) -> Self::$item_name;
fn into_rest(self) -> <Self as $trait_name>::Rest;
}
impl<R: Tuple1, T: $trait_minus1<Rest = R>> $trait_name for T {
type $item_name = R::Item0;
type Rest = R::Rest;
fn $item_getter(self) -> Self::$item_name {
$trait_minus1::into_rest(self).into_0()
}
fn into_rest(self) -> <Self as $trait_name>::Rest {
$trait_minus1::into_rest(self).into_rest()
}
}
};
}
macro_rules! tuple_trait {
($number: literal) => {
tuple_trait_def! { $number, tuple_trait_inner }
};
}
repeat!(64, impl_tuple);
repeat!(64, tuple_trait);
|