summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lib.rs148
1 files changed, 139 insertions, 9 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 1303f3d..a7146b8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,14 +1,144 @@
-pub fn add(left: u64, right: u64) -> u64 {
- left + right
+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,)
+ }
}
-#[cfg(test)]
-mod tests {
- use super::*;
+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()
+ }
- #[test]
- fn it_works() {
- let result = add(2, 2);
- assert_eq!(result, 4);
+ fn into_rest(self) -> <Self as Tuple2>::Rest {
+ self.into_rest().into_rest()
}
}