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