Skip to main content

std_traits/
tuple.rs

1use crate::{array::Array, primitive::Primitive};
2
3pub trait Tuple: Primitive {
4    const N: usize;
5}
6
7pub trait HomogeneousTuple<Item>: Tuple {
8    type Array: Array<Item = Item>;
9
10    #[must_use]
11    fn into_array(self) -> Self::Array
12    where
13        Self: Sized;
14    #[must_use]
15    fn from_array(array: Self::Array) -> Self;
16}
17
18impl Primitive for () {}
19impl Tuple for () {
20    const N: usize = 0;
21}
22impl<T> HomogeneousTuple<T> for () {
23    type Array = [T; 0];
24
25    fn into_array(self) -> Self::Array
26    where
27        Self: Sized,
28    {
29        []
30    }
31
32    fn from_array(_array: Self::Array) -> Self {
33        #[allow(clippy::unused_unit)]
34        ()
35    }
36}
37
38#[cfg_attr(docsrs, doc(fake_variadic))]
39#[cfg_attr(
40    docsrs,
41    doc = "This trait is implemented for tuples up to 12 items long."
42)]
43impl<T1: ?Sized> Primitive for (T1,) {}
44
45#[cfg_attr(docsrs, doc(fake_variadic))]
46#[cfg_attr(
47    docsrs,
48    doc = "This trait is implemented for tuples up to 12 items long."
49)]
50impl<T1: ?Sized> Tuple for (T1,) {
51    const N: usize = 1;
52}
53
54#[cfg_attr(docsrs, doc(fake_variadic))]
55#[cfg_attr(
56    docsrs,
57    doc = "This trait is implemented for tuples up to 12 items long."
58)]
59impl<T> HomogeneousTuple<T> for (T,) {
60    type Array = [T; 1];
61
62    fn into_array(self) -> Self::Array
63    where
64        Self: Sized,
65    {
66        self.into()
67    }
68
69    fn from_array(array: Self::Array) -> Self {
70        array.into()
71    }
72}
73
74macro_rules! replace_expr {
75    ($_t:tt $sub:tt) => {
76        $sub
77    };
78}
79
80macro_rules! homogeneous_tuple {
81    ($($types:tt),*) => {
82        (
83            $(
84                replace_expr!(
85                    ($types)
86                    T
87                ),
88            )*
89        )
90    };
91}
92
93macro_rules! impl_tuple {
94    ($n:expr => $($types:tt $i:tt),*; $last:tt $last_i:tt) => {
95        #[cfg_attr(docsrs, doc(hidden))]
96        impl<$($types,)* $last: ?Sized> Primitive for ($($types,)* $last,) {}
97        #[cfg_attr(docsrs, doc(hidden))]
98        impl<$($types,)* $last: ?Sized> Tuple for ($($types,)* $last,) {
99            const N: usize = $n;
100        }
101        #[cfg_attr(docsrs, doc(hidden))]
102        impl<T> HomogeneousTuple<T> for homogeneous_tuple!($($types,)* $last) {
103            type Array = [T; $n];
104
105            fn into_array(self) -> Self::Array
106            where
107                Self: Sized
108            {
109                self.into()
110            }
111
112            fn from_array(array: Self::Array) -> Self {
113                array.into()
114            }
115        }
116    }
117}
118
119/*
120for n in range(2, 13):
121    print(f"impl_tuple!({n} => {', '.join(f'T{i} {i - 1}' for i in range(1, n))}; T{n} {n - 1});")
122*/
123impl_tuple!(2 => T1 0; T2 1);
124impl_tuple!(3 => T1 0, T2 1; T3 2);
125impl_tuple!(4 => T1 0, T2 1, T3 2; T4 3);
126impl_tuple!(5 => T1 0, T2 1, T3 2, T4 3; T5 4);
127impl_tuple!(6 => T1 0, T2 1, T3 2, T4 3, T5 4; T6 5);
128impl_tuple!(7 => T1 0, T2 1, T3 2, T4 3, T5 4, T6 5; T7 6);
129impl_tuple!(8 => T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6; T8 7);
130impl_tuple!(9 => T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7; T9 8);
131impl_tuple!(10 => T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7, T9 8; T10 9);
132impl_tuple!(11 => T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7, T9 8, T10 9; T11 10);
133impl_tuple!(12 => T1 0, T2 1, T3 2, T4 3, T5 4, T6 5, T7 6, T8 7, T9 8, T10 9, T11 10; T12 11);
134
135#[cfg(test)]
136mod test {
137    use super::*;
138    extern crate std;
139    use std::{format, prelude::rust_2021::*, println};
140
141    macro_rules! test_from_array {
142        ($($types:tt),+) => {
143            let arr  = std::array::from_fn(|i| format!("{i}"));
144            println!("{arr:?}");
145            let tuple = <($($types,)+)>::from_array(arr.clone());
146            let arr2 = tuple.into_array();
147            println!("{arr2:?}");
148            assert_eq!(arr2, arr);
149        }
150    }
151
152    #[test]
153    fn test_from_array_0() {
154        let arr: [String; 0] = [];
155        #[allow(clippy::let_unit_value)]
156        let tuple = <()>::from_array(arr);
157        let _: [String; 0] = tuple.into_array();
158    }
159
160    #[test]
161    fn test_into_array_change_type_0_elements() {
162        let arr: [String; 0] = [];
163        #[allow(clippy::let_unit_value)]
164        let tuple = <()>::from_array(arr);
165        let _: [u8; 0] = tuple.into_array();
166    }
167
168    #[test]
169    fn test_from_array_1() {
170        test_from_array!(String);
171    }
172
173    #[test]
174    fn test_from_array_2() {
175        test_from_array!(String, String);
176    }
177
178    #[test]
179    fn test_from_array_3() {
180        test_from_array!(String, String, String);
181    }
182
183    #[test]
184    fn test_from_array_12() {
185        test_from_array!(
186            String, String, String, String, String, String, String, String, String, String, String,
187            String
188        );
189    }
190}