1#[diagnostic::on_unimplemented(
15 message = "`{Self}` is not a tuple, doesn't have an element #{N}, or is too long",
16 note = "At the moment, the trait is implemented only for tuples up to length 8"
17)]
18pub trait Index<const N: usize>: Tuple {
19 type Nth;
21 type NthMapped<U>;
23
24 fn nth(this: Self) -> Self::Nth;
26
27 fn nth_ref(this: &Self) -> &Self::Nth;
29
30 fn map_nth<U>(this: Self, f: impl FnOnce(Self::Nth) -> U) -> Self::NthMapped<U>;
32}
33
34#[diagnostic::on_unimplemented(
41 message = "`{Self}` is not tuple, has less than {N} elements, or is too long",
42 note = "At the moment, the trait is implemented only for tuples up to length 8"
43)]
44pub trait Slice<const N: usize>: Tuple {
45 type FirstN;
47
48 type FirstNStripped;
50
51 fn first_n(this: Self) -> Self::FirstN;
53
54 fn strip_first_n(this: Self) -> Self::FirstNStripped;
56
57 fn split(this: Self) -> (Self::FirstN, Self::FirstNStripped);
60}
61
62pub trait CloneableRefs: Tuple {
69 type Cloned;
71
72 fn cloned(this: Self) -> Self::Cloned;
74}
75
76pub trait CopiableRefs: Tuple {
83 type Copied;
85
86 fn copied(this: Self) -> Self::Copied;
88}
89
90macro_rules! impl_nth_methods {
91 ($n:literal, $name:ident, $ref_name:ident, $map_name:ident) => {
92 #[doc = concat!("Returns the ", stringify!($name), " element of the tuple.")]
93 #[doc = "For a more generic function, see [`Tuple::nth`]"]
94 fn $name(self) -> Self::Nth
95 where
96 Self: Index<$n>,
97 {
98 Index::nth(self)
99 }
100
101 #[doc = concat!("Returns a reference to the ", stringify!($name), " element of the tuple.")]
102 #[doc = "For a more generic function, see [`Tuple::nth_ref`]"]
103 fn $ref_name(&self) -> &Self::Nth
104 where
105 Self: Index<$n>,
106 {
107 Index::nth_ref(self)
108 }
109
110 #[doc = concat!("Transforms the ", stringify!($name), " element of the tuple with `f`.")]
111 #[doc = "For a more generic function, see [`Tuple::map_nth`]"]
112 fn $map_name<U>(self, f: impl FnOnce(Self::Nth) -> U) -> Self::NthMapped<U>
113 where
114 Self: Index<$n>,
115 {
116 Index::map_nth(self, f)
117 }
118 };
119}
120
121#[diagnostic::on_unimplemented(
123 message = "`{Self}` is not a tuple or is too long",
124 note = "At the moment, the trait is implemented only for tuples up to length 8"
125)]
126pub trait Tuple: Sized {
127 type Appended<NewElement>;
129
130 type Prepended<NewElement>;
132
133 type Reversed;
135
136 fn append<NewElement>(self, new_element: NewElement) -> Self::Appended<NewElement>;
139
140 fn prepend<NewElement>(self, new_element: NewElement) -> Self::Prepended<NewElement>;
143
144 fn rev(self) -> Self::Reversed;
147
148 fn cloned(self) -> Self::Cloned
151 where
152 Self: CloneableRefs,
153 {
154 CloneableRefs::cloned(self)
155 }
156
157 fn copied(self) -> Self::Copied
160 where
161 Self: CopiableRefs,
162 {
163 CopiableRefs::copied(self)
164 }
165
166 fn nth<const N: usize>(self) -> Self::Nth
169 where
170 Self: Index<N>,
171 {
172 Index::nth(self)
173 }
174
175 fn nth_ref<const N: usize>(&self) -> &Self::Nth
178 where
179 Self: Index<N>,
180 {
181 Index::nth_ref(self)
182 }
183
184 fn map_nth<const N: usize, U>(self, f: impl FnOnce(Self::Nth) -> U) -> Self::NthMapped<U>
187 where
188 Self: Index<N>,
189 {
190 Index::map_nth(self, f)
191 }
192
193 impl_nth_methods!(0, first, first_ref, map_first);
194 impl_nth_methods!(1, second, second_ref, map_second);
195 impl_nth_methods!(2, third, third_ref, map_third);
196
197 fn first_n<const N: usize>(self) -> Self::FirstN
200 where
201 Self: Slice<N>,
202 {
203 Slice::first_n(self)
204 }
205
206 fn strip_first_n<const N: usize>(self) -> Self::FirstNStripped
209 where
210 Self: Slice<N>,
211 {
212 Slice::strip_first_n(self)
213 }
214
215 fn split<const N: usize>(self) -> (Self::FirstN, Self::FirstNStripped)
217 where
218 Self: Slice<N>,
219 {
220 Slice::split(self)
221 }
222}
223
224macro_rules! rev {
225 ($($x:ident,)*) => { rev!(| $($x,)* |) };
226 (| $x:ident, $($rest:ident,)* | $($rev:ident,)*) => { rev!(| $($rest,)* | $x, $($rev,)*) };
227 (| | $($rev:ident,)*) => { ($($rev,)*) };
228}
229
230macro_rules! impl_tuple_traits {
231 ($length:literal - $($n:literal : $t:ident),*) => {
232 impl_tuple_traits!([] [$($n:$t,)*] [$($t),*]);
233
234 impl<$($t),*> Slice<$length> for ($($t,)*) {
235 type FirstN = Self;
236 type FirstNStripped = ();
237
238 fn first_n(this: Self) -> Self::FirstN { this }
239 fn strip_first_n(_: Self) -> Self::FirstNStripped {}
240 fn split(this: Self) -> (Self::FirstN, Self::FirstNStripped) { (this, ()) }
241 }
242
243 #[allow(non_snake_case)]
244 impl<$($t: Clone),*> CloneableRefs for ($(&$t,)*) {
245 type Cloned = ($($t,)*);
246
247 #[allow(clippy::unused_unit)]
248 fn cloned(this: Self) -> Self::Cloned {
249 let ($($t,)*) = this;
250 ($($t.clone(),)*)
251 }
252 }
253
254 #[allow(non_snake_case)]
255 impl<$($t: Copy),*> CopiableRefs for ($(&$t,)*) {
256 type Copied = ($($t,)*);
257
258 #[allow(clippy::unused_unit)]
259 fn copied(this: Self) -> Self::Copied {
260 let ($($t,)*) = this;
261 ($(*$t,)*)
262 }
263 }
264
265 #[allow(non_snake_case)]
266 impl<$($t),*> Tuple for ($($t,)*) {
267 type Appended<NewElement> = ($($t,)* NewElement,);
268 type Prepended<NewElement> = (NewElement, $($t,)*);
269 type Reversed = rev!($($t,)*);
270
271 fn append<NewElement>(self, new_element: NewElement) -> Self::Appended<NewElement> {
272 let ($($t,)*) = self;
273 ($($t,)* new_element,)
274 }
275
276 fn prepend<NewElement>(self, new_element: NewElement) -> Self::Prepended<NewElement> {
277 let ($($t,)*) = self;
278 (new_element, $($t,)*)
279 }
280
281 fn rev(self) -> Self::Reversed {
282 let ($($t,)*) = self;
283 rev!($($t,)*)
284 }
285 }
286 };
287
288 ($prev:tt [] $t:tt) => {};
289
290 ([$($prev:ident),*] [$id:literal : $nth:ident, $($next_id:literal : $next:ident,)*] [$($t:ident),+]) => {
291 #[allow(non_snake_case)]
292 impl<$($t),+> Index<$id> for ($($t,)+) {
293 type Nth = $nth;
294 type NthMapped<U> = ($($prev,)* U, $($next,)*);
295
296 #[allow(unused)]
297 fn nth(this: Self) -> Self::Nth {
298 let ($($t,)+) = this;
299 $nth
300 }
301
302 #[allow(unused)]
303 fn nth_ref(this: &Self) -> &Self::Nth {
304 let ($($t,)+) = this;
305 $nth
306 }
307
308 fn map_nth<U>(this: Self, f: impl FnOnce(Self::Nth) -> U) -> Self::NthMapped<U> {
309 let ($($t,)+) = this;
310 ($($prev,)* f($nth), $($next,)*)
311 }
312 }
313
314 #[allow(non_snake_case)]
315 impl<$($t),+> Slice<$id> for ($($t,)+) {
316 type FirstN = ($($prev,)*);
317 type FirstNStripped = ($nth, $($next,)*);
318
319 #[allow(unused, clippy::unused_unit)]
320 fn first_n(this: Self) -> Self::FirstN {
321 let ($($t,)+) = this;
322 ($($prev,)*)
323 }
324
325 #[allow(unused)]
326 fn strip_first_n(this: Self) -> Self::FirstNStripped {
327 let ($($t,)+) = this;
328 ($nth, $($next,)*)
329 }
330
331 fn split(this: Self) -> (Self::FirstN, Self::FirstNStripped) {
332 let ($($t,)+) = this;
333 (($($prev,)*), ($nth, $($next,)*))
334 }
335 }
336
337 impl_tuple_traits!([$($prev,)* $nth] [$($next_id:$next,)*] [$($t),+]);
338 };
339}
340
341impl_tuple_traits!(0 -);
342impl_tuple_traits!(1 - 0: T0);
343impl_tuple_traits!(2 - 0: T0, 1: T1);
344impl_tuple_traits!(3 - 0: T0, 1: T1, 2: T2);
345impl_tuple_traits!(4 - 0: T0, 1: T1, 2: T2, 3: T3);
346impl_tuple_traits!(5 - 0: T0, 1: T1, 2: T2, 3: T3, 4: T4);
347impl_tuple_traits!(6 - 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5);
348impl_tuple_traits!(7 - 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6);
349impl_tuple_traits!(8 - 0: T0, 1: T1, 2: T2, 3: T3, 4: T4, 5: T5, 6: T6, 7: T7);
350
351#[rustfmt::skip]
352macro_rules! impl_nth_fn {
353 ($n:literal, $name:ident, $ref_name:ident, $map_name:ident) => {
354 #[doc = concat!("Returns the ", stringify!($name), " element of the tuple.")]
355 #[doc = "For a more generic function, see [`Tuple::nth`]"]
356 pub fn $name<T: Index<$n>>(tuple: T) -> T::Nth {
357 Index::nth(tuple)
358 }
359
360 #[doc = concat!("Returns a reference to the ", stringify!($name), " element of the tuple.")]
361 #[doc = "For a more generic function, see [`Tuple::nth_ref`]"]
362 pub fn $ref_name<T: Index<$n>>(tuple: &T) -> &T::Nth {
363 Index::nth_ref(tuple)
364 }
365
366 #[doc = concat!("Returns a function that transforms the ", stringify!($name), " element of a tuple with `f`.")]
367 #[doc = "For a more generic function, see [`Tuple::map_nth`]"]
368 pub fn $map_name<T: Index<$n>, U>(
369 mut f: impl FnMut(T::Nth) -> U,
370 ) -> impl FnMut(T) -> T::NthMapped<U> {
371 move |tuple| Index::map_nth(tuple, &mut f)
372 }
373 };
374}
375
376impl_nth_fn!(0, first, first_ref, map_first);
377impl_nth_fn!(1, second, second_ref, map_second);
378impl_nth_fn!(2, third, third_ref, map_third);
379
380pub fn append<T: Tuple, U: Clone>(new_element: U) -> impl Fn(T) -> T::Appended<U> {
382 move |tuple| tuple.append(new_element.clone())
383}
384
385pub fn prepend<U: Clone, T: Tuple>(new_element: U) -> impl Fn(T) -> T::Prepended<U> {
387 move |tuple| tuple.prepend(new_element.clone())
388}
389
390pub const fn tuple<T>(x: T) -> (T,) {
392 (x,)
393}
394
395pub fn rev<T: Tuple>(x: T) -> T::Reversed {
397 x.rev()
398}
399
400pub fn cloned<T: CloneableRefs>(x: T) -> T::Cloned {
402 CloneableRefs::cloned(x)
403}
404
405pub fn copied<T: CopiableRefs>(x: T) -> T::Copied {
407 CopiableRefs::copied(x)
408}
409
410#[macro_export]
428macro_rules! from_tuple {
429 ($name:ident { $($field:ident),* $(,)? }) => { |($($field,)*)| $name { $($field),* } };
430}
431
432#[macro_export]
433#[doc(hidden)]
434macro_rules! last {
435 ($_:tt $($rest:tt)+) => { $($rest)+ };
436 ($last:tt) => { $last };
437}
438
439#[macro_export]
458macro_rules! call {
459 ($($args:tt)*) => { |$crate::last!($($args)*)| $($args)* };
460}