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 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 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) -> ::Rest; } impl> $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) -> ::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);