multiversx_sc/tuple_util/
nested_tuples.rs1pub trait NestedTuple {}
5
6impl NestedTuple for () {}
7
8impl<Head, Tail> NestedTuple for (Head, Tail) where Tail: NestedTuple {}
9
10pub trait NestedTupleAppend<T> {
12 type Output;
13
14 fn append(self, t: T) -> Self::Output;
15}
16
17impl<T> NestedTupleAppend<T> for () {
18 type Output = (T, ());
19
20 fn append(self, t: T) -> Self::Output {
21 (t, ())
22 }
23}
24
25impl<Head, Tail, T> NestedTupleAppend<T> for (Head, Tail)
26where
27 Tail: NestedTupleAppend<T>,
28{
29 type Output = (Head, Tail::Output);
30
31 fn append(self, t: T) -> Self::Output {
32 (self.0, self.1.append(t))
33 }
34}
35
36pub trait NestedTupleFlatten: NestedTuple {
38 type Flattened;
39 type Unpacked;
40
41 fn flatten(self) -> Self::Flattened;
43
44 fn flatten_unpack(self) -> Self::Unpacked;
47}
48
49impl NestedTupleFlatten for () {
50 type Flattened = ();
51 type Unpacked = ();
52
53 fn flatten(self) -> Self::Flattened {}
54 fn flatten_unpack(self) -> Self::Unpacked {}
55}
56
57impl<T> NestedTupleFlatten for (T, ()) {
58 type Flattened = (T,);
59 type Unpacked = T;
60
61 fn flatten(self) -> Self::Flattened {
62 (self.0,)
63 }
64
65 fn flatten_unpack(self) -> Self::Unpacked {
66 self.0
67 }
68}
69
70macro_rules! tuple_list_type {
71 () => ( () );
72 ($i:ty) => ( ($i, ()) );
73 ($i:ty, $($e:ty),*) => ( ($i, tuple_list_type!($($e),*)) );
74}
75
76macro_rules! unnest {
77 (($layer:expr); ($($v:expr),*); ($u:ident, $($us:ident,)*)) => {
78 unnest!(($layer . 1); ($($v,)* $layer . 0); ($($us,)*))
79 };
80 (($layer:expr); ($($v:expr),*); ()) => { ($($v,)*) };
81}
82
83macro_rules! flatten_impl {
84 ($(($t:ident $($ts:ident)+))+) => {
85 $(
86 impl<$t,$($ts),+> NestedTupleFlatten for tuple_list_type!($t,$($ts),+) {
87 type Flattened = ($t,$($ts),+);
88 type Unpacked = ($t,$($ts),+);
89
90 fn flatten(self) -> Self::Flattened {
91 unnest!((self); (); ($t, $($ts,)*))
92 }
93
94 fn flatten_unpack(self) -> Self::Unpacked {
95 self.flatten()
96 }
97 }
98 )+
99 }
100}
101
102flatten_impl! {
103 (T1 T2)
104 (T1 T2 T3)
105 (T1 T2 T3 T4)
106 (T1 T2 T3 T4 T5)
107 (T1 T2 T3 T4 T5 T6)
108 (T1 T2 T3 T4 T5 T6 T7)
109 (T1 T2 T3 T4 T5 T6 T7 T8)
110 (T1 T2 T3 T4 T5 T6 T7 T8 T9)
111 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10)
112 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11)
113 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12)
114 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13)
115 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14)
116 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15)
117 (T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15 T16)
118}
119
120#[cfg(test)]
121mod test {
122 use super::*;
123
124 #[test]
125 fn test_flatten() {
126 let flat2 = (1, (2, ())).flatten();
127 assert_eq!(flat2, (1, 2));
128
129 let n3 = (1u8, (2u16, (3u32, ())));
130 let flat3 = n3.flatten();
131 assert_eq!(flat3, (1u8, 2u16, 3u32));
132
133 let n4 = n3.append(4u64);
134 let flat4 = n4.flatten();
135 assert_eq!(flat4, (1u8, 2u16, 3u32, 4u64));
136 }
137}