summaryrefslogtreecommitdiff
path: root/src/lib.rs
blob: a7146b8adf9522d5a7a1db379d9c9d448d9deb62 (plain)
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;
}

pub trait Tuple2: Tuple1 {
	type Item1;
	type Rest: Tuple;

	fn into_1(self) -> Self::Item1;
	fn into_rest(self) -> <Self as Tuple2>::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, B> Tuple for (A, B) {
	type AsRef<'a>
		= (&'a A, &'a B)
	where
		Self: 'a;
	type AsMut<'a>
		= (&'a mut A, &'a mut B)
	where
		Self: 'a;

	type Reversed = (B, A);

	fn as_ref(&self) -> Self::AsRef<'_> {
		(&self.0, &self.1)
	}

	fn as_mut(&mut self) -> Self::AsMut<'_> {
		(&mut self.0, &mut self.1)
	}

	fn rev(self) -> Self::Reversed {
		(self.1, 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 as Tuple1>::Rest) {
		(self.0, ())
	}

	fn into_rest(self) -> Self::Rest {}
}

impl<A, B> Tuple1 for (A, B) {
	type Item0 = A;

	type Rest = (B,);

	fn into_0(self) -> Self::Item0 {
		self.0
	}

	fn split_into(self) -> (Self::Item0, <Self as Tuple1>::Rest) {
		(self.0, (self.1,))
	}

	fn into_rest(self) -> Self::Rest {
		(self.1,)
	}
}

impl<R: Tuple1, T: Tuple1<Rest = R>> Tuple2 for T {
	type Item1 = R::Item0;
	type Rest = R::Rest;

	fn into_1(self) -> Self::Item1 {
		self.into_rest().into_0()
	}

	fn into_rest(self) -> <Self as Tuple2>::Rest {
		self.into_rest().into_rest()
	}
}