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;
}
macro_rules! impl_tuple {
(
A, $($letter: ident),* => $($letter_reverse: ident),*;
0, $($number: tt),* => $($number_reverse: tt),*
) => {
impl<A,$($letter),*> Tuple for (A,$($letter,)*) {
type AsRef<'a> = (&'a A,$(&'a $letter,)*) where Self: 'a;
type AsMut<'a> = (&'a mut A,$(&'a mut $letter,)*) where Self: 'a;
type Reversed = ($($letter_reverse,)*);
fn as_ref(&self) -> Self::AsRef<'_> {
(&self.0,$(&self.$number,)*)
}
fn as_mut(&mut self) -> Self::AsMut<'_> {
(&mut self.0,$(&mut self.$number,)*)
}
fn rev(self) -> Self::Reversed {
($(self.$number_reverse,)*)
}
}
impl<A, $($letter),*> Tuple1 for (A, $($letter,)*) {
type Item0 = A;
type Rest = ($($letter,)*);
fn into_0(self) -> Self::Item0 {
self.0
}
fn split_into(self) -> (Self::Item0, Self::Rest) {
(self.0, ($(self.$number,)*))
}
fn into_rest(self) -> Self::Rest {
($(self.$number,)*)
}
}
};
}
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
}
}
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 as Tuple1>::Rest) {
(self.0, ())
}
fn into_rest(self) -> Self::Rest {}
}
impl_tuple!(A, B => B, A; 0, 1 => 1, 0);
impl_tuple!(A, B, C => C, B, A; 0, 1, 2 => 2, 1, 0);
impl_tuple!(A, B, C, D => D, C, B, A; 0, 1, 2, 3 => 3, 2, 1, 0);
impl_tuple!(A, B, C, D, E => E, D, C, B, A; 0, 1, 2, 3, 4 => 4, 3, 2, 1, 0);
macro_rules! tuple_trait {
(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()
}
}
};
}
tuple_trait!(trait Tuple2 for Tuple1 { type Item1; fn into_1; });
tuple_trait!(trait Tuple3 for Tuple2 { type Item2; fn into_2; });
tuple_trait!(trait Tuple4 for Tuple3 { type Item3; fn into_3; });
tuple_trait!(trait Tuple5 for Tuple4 { type Item4; fn into_4; });
|