typenum/
tuple.rs

1//! [`tuple`] operations.
2//!
3//! # Indexing
4//! `tuple` types (with up to twelve elements) allow access to values by index, because they implement the [`core::ops::Index`] and [`core::ops::IndexMut`] traits:
5//!
6//! ```rust
7//! use std::ops::{Index, IndexMut};
8//! use typenum::{U0, U1, U2, U3, Len};
9//!
10//! let tuple = ("hello", 5, true);
11//!
12//! assert_eq!(tuple[U0::new()], "hello");
13//! assert_eq!(tuple[U1::new()], 5);
14//! assert_eq!(tuple[U2::new()], true);
15//!
16//! assert_eq!(tuple.len(), U3::new());
17//! ```
18//!
19//! Attempting to use an out-of-bounds index is a **compile-time** error.
20//!
21//! ```compile_fail
22//! use std::ops::{Index, IndexMut};
23//! use typenum::{U0, U1, U2};
24//!
25//! let tuple = ("hello", 5, true);
26//!
27//! assert_eq!(tuple[U0::new()], "hello"); // OK, the tuple has 3 elements
28//! assert_eq!(tuple[U3::new()], "this is an error!");
29//! ```
30
31use crate::{Len, U0};
32
33impl Len for () {
34    type Output = U0;
35
36    fn len(&self) -> Self::Output {
37        U0::new()
38    }
39}
40
41macro_rules! generate_tuple_impls {
42    (
43        $( $u:ident ),* ;
44        $( $t:ident ),* ;
45    ) => {
46        generate_tuple_impls!(@__recur__
47             [ ] [ $( $u )* ];
48             [ ] [ $( $t )* ];
49        );
50    };
51
52    (@__recur__
53        [ ] [ ];
54        [ ] [ ];
55    ) => { /* terminal-case */ };
56
57    (@__recur__
58        [ $( $uhead:ident )* ] [ $u:ident $( $utail:ident )+ ];
59        [ $( $thead:ident )* ] [ $t:ident $( $ttail:ident )+ ];
60    ) => {
61        generate_tuple_impls!(@__recur__
62            [ $( $uhead )* $u ] [ $( $utail )* ];
63            [ $( $thead )* $t ] [ $( $ttail )* ];
64        );
65
66        generate_tuple_impls!(@__expand_at__
67            [ $( $uhead )* ] [ $u $( $utail )* ];
68            [ $( $thead )* ] [ $t $( $ttail )* ];
69        );
70    };
71
72    (@__recur__
73        [ $( $uhead:ident )* ] [ $u:ident ];
74        [ $( $thead:ident )* ] [ $t:ident ];
75    ) => {
76
77        impl< $( $thead, )* $t, > $crate::Len   for ( $( $thead, )* $t, ) {
78            type Output = <$crate::$u as core::ops::Add<$crate::B1>>::Output;
79
80            #[inline]
81            fn len(&self) -> Self::Output {
82                Self::Output::new()
83            }
84        }
85
86        generate_tuple_impls!(@__recur__
87            [ ] [ $( $uhead )* ];
88            [ ] [ $( $thead )* ];
89        );
90
91        generate_tuple_impls!(@__expand_at__
92            [ $( $uhead )* ] [ $u ];
93            [ $( $thead )* ] [ $t ];
94        );
95    };
96
97
98    (@__expand_at__
99        [ $( $uhead:ident )* ] [ $u:ident $( $utail:ident )* ];
100        [ $( $thead:ident )* ] [ $t:ident $( $ttail:ident )* ];
101    ) => {
102        impl< $( $thead, )* $t, $( $ttail ),* > core::ops::Index<$crate::$u> for ( $( $thead, )* $t, $( $ttail ),* ) {
103            type Output = $t;
104
105            fn index(&self, _index: $crate::$u) -> &Self::Output {
106                #[allow(unused_variables)]
107                #[allow(non_snake_case)]
108                let ( $( $thead, )* $t, ..) = self;
109
110                $t
111            }
112        }
113
114        impl< $( $thead, )* $t, $( $ttail ),* > core::ops::IndexMut<$crate::$u> for ( $( $thead, )* $t, $( $ttail ),* ) {
115            fn index_mut(&mut self, _index: $crate::$u) -> &mut Self::Output {
116                #[allow(unused_variables)]
117                #[allow(non_snake_case)]
118                let ( $( $thead, )* $t, ..) = self;
119
120                $t
121            }
122        }
123    };
124}
125
126generate_tuple_impls! {
127    U0, U1, U2, U3, U4, U5, U6, U7, U8, U9, U10, U11;
128    T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11;
129}
130
131#[cfg(test)]
132mod test {
133    use crate::{Len, U0, U1, U11, U12, U2};
134
135    #[test]
136    fn tuple_index() {
137        assert_eq!((0,)[U0::new()], 0);
138        assert_eq!((1, 2)[U1::new()], 2);
139        assert_eq!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)[U11::new()], 12);
140    }
141
142    #[test]
143    fn tuple_index_mut() {
144        let mut tuple = (0, 1, 2);
145
146        tuple[U0::new()] = 5;
147
148        assert_eq!(tuple, (5, 1, 2));
149    }
150
151    #[test]
152    fn tuple_len() {
153        assert_eq!(().len(), U0::new());
154        assert_eq!((1,).len(), U1::new());
155        assert_eq!((1, 2).len(), U2::new());
156        assert_eq!((1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12).len(), U12::new());
157    }
158}