1pub trait Append<T> {
5 type Output;
6 fn append(self, other: T) -> Self::Output;
9}
10
11pub trait PluckTail {
15 type Head;
16 type Tail;
17 fn pluck_tail(self) -> (Self::Head, Self::Tail);
19}
20
21pub trait Prepend<T> {
23 type Output;
24 fn prepend(self, other: T) -> Self::Output;
28}
29
30pub trait Pluck {
34 type Head;
35 type Tail;
36 fn pluck(self) -> (Self::Head, Self::Tail);
38}
39
40macro_rules! tuple_impl {
41 ($($from:ident,)*) => {
43 impl<$($from,)* T> Append<T> for ( $( $from ,)* ) {
45 type Output = ( $( $from ,)* T);
46
47 #[inline]
48 #[allow(non_snake_case)]
49 fn append(self, x: T) -> ( $( $from ,)* T) {
50 match self {
51 ($($from,)*) => ($($from,)* x)
52 }
53 }
54 }
55
56 impl<$($from,)* T> PluckTail for ($($from,)* T,) {
57 type Head = ($($from,)*);
58 type Tail = T;
59
60 #[inline]
61 #[allow(non_snake_case)]
62 fn pluck_tail(self) -> (Self::Head, Self::Tail) {
63 match self {
64 ($($from,)* x,) => (($($from,)*), x)
65 }
66 }
67 }
68
69 impl<$($from,)* T> Prepend<T> for ( $( $from ,)* ) {
71 type Output = (T, $( $from ,)*);
72
73 #[inline]
74 #[allow(non_snake_case)]
75 fn prepend(self, x: T) -> (T, $( $from ,)*) {
76 match self {
77 ($($from,)*) => (x, $($from,)*)
78 }
79 }
80 }
81
82 impl<$($from,)* T> Pluck for (T, $($from,)*) {
83 type Head = T;
84 type Tail = ($($from,)*);
85
86 #[inline]
87 #[allow(non_snake_case)]
88 fn pluck(self) -> (Self::Head, Self::Tail) {
89 match self {
90 (x, $($from,)*) => (x, ($($from,)*))
91 }
92 }
93 }
94 }
95}
96
97macro_rules! for_each_prefix (
98 ($m:ident, [$(($arg:tt),)*]) => {
99 for_each_prefix!($m, [], [$(($arg),)*]);
100 };
101 ($m:ident, [$(($acc:tt),)*], []) => {
102 $m!($($acc,)*);
103 };
104 ($m:ident, [$(($acc:tt),)*], [($arg0:tt), $(($arg:tt),)*]) => {
105 $m!($($acc,)*);
106 for_each_prefix!($m, [$(($acc),)* ($arg0),], [$(($arg),)*]);
107 };
108);
109
110for_each_prefix! {
111 tuple_impl,
112 [(T0), (T1), (T2), (T3), (T4), (T5), (T6), (T7), (T8), (T9), (T10), (T11), (T12), (T13), (T14), (T15),]
113}
114
115macro_rules! merge_impl {
116 ([$($a:ident,)*], [$($b:ident,)*]) => {
117 impl<$($a,)* $($b,)*> Merge<($($b,)*)> for ( $($a,)* ) {
119 type Output = ($($a,)* $($b,)*);
120
121 #[inline]
122 #[allow(non_snake_case)]
123 fn merge(self, x: ($($b,)*)) -> ($($a,)* $($b,)*) {
124 match (self, x) {
125 (($($a,)*), ($($b,)*)) => ($($a,)* $($b,)*)
126 }
127 }
128 }
129 };
130}
131
132pub trait Merge<T> {
134 type Output;
135 fn merge(self, other: T) -> Self::Output;
140}
141
142macro_rules! for_each_prefix_suffix (
143 ($m:ident, [$(($acc:tt),)*], []) => {
144 $m!([$($acc,)*], []);
145 };
146 ($m:ident, [$(($acc:tt),)*], [($arg0:tt), $(($arg:tt),)*]) => {
147 $m!([$($acc,)*], [$arg0, $($arg,)*]);
148 for_each_prefix_suffix!($m, [$(($acc),)* ($arg0),], [$(($arg),)*]);
149 };
150);
151
152macro_rules! merge_impl2(
153 ($($a: ident,)*) => (
154 for_each_prefix_suffix!(
155 merge_impl,
156 [],
157 [$(($a),)*]
158 );
159 );
160);
161
162for_each_prefix! {
163 merge_impl2,
164 [(T0), (T1), (T2), (T3), (T4), (T5), (T6), (T7), (T8), (T9), (T10), (T11), (T12), (T13), (T14), (T15),]
165}
166
167pub trait Split {
171 type Left;
172 type Right;
173
174 fn split(self) -> (Self::Left, Self::Right);
175}
176
177macro_rules! split_impl (
178 ($(($a:ident, $b:ident),)*) => (
179 impl<$($a,)* $($b,)*> Split for ($($a,)* $($b,)*) {
180 type Left = ($($a,)*);
181 type Right = ($($b,)*);
182 #[allow(non_snake_case)]
183 fn split(self) -> (Self::Left, Self::Right) {
184 match self {
185 ($($a,)* $($b,)*) => (($($a,)*), ($($b,)*))
186 }
187 }
188 }
189 impl<$($a,)* $($b,)* TLast> Split for ($($a,)* $($b,)* TLast,) {
190 type Left = ($($a,)*);
191 type Right = ($($b,)* TLast,);
192 #[allow(non_snake_case)]
193 fn split(self) -> (Self::Left, Self::Right) {
194 match self {
195 ($($a,)* $($b,)* t_last,) => (($($a,)*), ($($b,)* t_last,))
196 }
197 }
198 }
199 );
200);
201
202for_each_prefix! {
203 split_impl,
204 [((T0, T1)), ((T2, T3)), ((T4, T5)), ((T6, T7)), ((T8, T9)), ((T10, T11)), ((T12, T13)), ((T14, T15)),]
205}
206
207#[cfg(test)]
208mod test {
209 use {Append, Merge, Pluck, PluckTail, Prepend, Split};
210
211 #[test]
212 fn append() {
213 let out = (0,).append(1);
214 assert_eq!(out.0, 0);
215 assert_eq!(out.1, 1);
216 let out = out.append(2);
217 assert_eq!(out.0, 0);
218 assert_eq!(out.1, 1);
219 assert_eq!(out.2, 2);
220 let out = out.append(3);
221 assert_eq!(out.0, 0);
222 assert_eq!(out.1, 1);
223 assert_eq!(out.2, 2);
224 assert_eq!(out.3, 3);
225 let out = out.append("foo");
226 assert_eq!(out.0, 0);
227 assert_eq!(out.1, 1);
228 assert_eq!(out.2, 2);
229 assert_eq!(out.3, 3);
230 assert_eq!(out.4, "foo");
231
232 let (head, tail) = out.pluck_tail();
233 assert_eq!((head, tail), ((0, 1, 2, 3), "foo"));
234 let (head, tail) = head.pluck_tail();
235 assert_eq!((head, tail), ((0, 1, 2), 3));
236 }
237
238 #[test]
239 fn prepend() {
240 let out = (0,).prepend(1);
241 assert_eq!(out.0, 1);
242 assert_eq!(out.1, 0);
243 let out = out.prepend(2);
244 assert_eq!(out.0, 2);
245 assert_eq!(out.1, 1);
246 assert_eq!(out.2, 0);
247 let out = out.prepend(3);
248 assert_eq!(out.0, 3);
249 assert_eq!(out.1, 2);
250 assert_eq!(out.2, 1);
251 assert_eq!(out.3, 0);
252 let out = out.prepend("foo");
253 assert_eq!(out.0, "foo");
254 assert_eq!(out.1, 3);
255 assert_eq!(out.2, 2);
256 assert_eq!(out.3, 1);
257 assert_eq!(out.4, 0);
258
259 let (head, tail) = out.pluck();
260 assert_eq!((head, tail), ("foo", (3, 2, 1, 0)));
261 let (head, tail) = tail.pluck();
262 assert_eq!((head, tail), (3, (2, 1, 0)));
263 }
264
265 #[test]
266 fn merge() {
267 let a = (1, 2, 3);
268 let b = ("foo", "bar");
269 let c = a.merge(b);
270 assert_eq!(c.0, 1);
271 assert_eq!(c.1, 2);
272 assert_eq!(c.2, 3);
273 assert_eq!(c.3, "foo");
274 assert_eq!(c.4, "bar");
275
276 let a = ("test",);
279 let out = a.merge(());
280 assert_eq!(out.0, "test");
281
282 let a = ("test",);
283 let out = ().merge(a);
284 assert_eq!(out.0, "test");
285 assert_eq!(().merge(()), ());
286 assert_eq!(().merge((1,)), (1,));
287 assert_eq!((1,).merge(()), (1,));
288 }
289
290 #[test]
291 fn split() {
292 let a = (1, 2, 3);
293 let (b, c) = a.split();
294 assert_eq!(b.0, 1);
295 assert_eq!(c.0, 2);
296 assert_eq!(c.1, 3);
297 assert_eq!(().split(), ((), ()));
298 assert_eq!((1,).split(), ((), (1,)));
299 assert_eq!((1, 2).split(), ((1,), (2,)));
300 assert_eq!((1, 2, 3).split(), ((1,), (2, 3)));
301 }
302}