tuple_len/
lib.rs

1#![warn(warnings)]
2#![no_std]
3#![doc = include_str!("../README.md")]
4
5#[macro_export]
6macro_rules! tuple_len {
7    ( ($($a:expr),+ $(,)?) ) => { $crate::tuple_len!(1usize, $($a,)+) };
8    ( $len:expr, $a:expr, $($rest_a:expr,)+ ) => { $crate::tuple_len!($len + 1usize, $($rest_a,)+) };
9    ( $len:expr, $a:expr, ) => { $len };
10    ( () ) => { 0usize };
11    ( $tuple:ident ) => { $crate::len($tuple) };
12    ( &$tuple:ident ) => { $crate::len(&$tuple) };
13}
14
15#[allow(clippy::len_without_is_empty)]
16pub trait TupleLen {
17    fn len(&self) -> usize;
18}
19
20macro_rules! count {
21    () => (0usize);
22    ( $x:tt $($xs:tt)* ) => (1usize + count!($($xs)*));
23}
24
25macro_rules! tuple_impl {
26    ($( $T:ident ),*) => {
27        impl<$( $T, )*> TupleLen for ($( $T, )*) {
28            #[inline]
29            fn len(&self) -> usize {
30                count!($( $T )*)
31            }
32        }
33
34        impl<$( $T, )*> TupleLen for &($( $T, )*) {
35            #[inline]
36            fn len(&self) -> usize {
37                count!($( $T )*)
38            }
39        }
40    }
41}
42
43tuple_impl!();
44tuple_impl!(A);
45tuple_impl!(A, B);
46tuple_impl!(A, B, C);
47tuple_impl!(A, B, C, D);
48tuple_impl!(A, B, C, D, E);
49tuple_impl!(A, B, C, D, E, F);
50tuple_impl!(A, B, C, D, E, F, G);
51tuple_impl!(A, B, C, D, E, F, G, H);
52tuple_impl!(A, B, C, D, E, F, G, H, I);
53tuple_impl!(A, B, C, D, E, F, G, H, I, J);
54tuple_impl!(A, B, C, D, E, F, G, H, I, J, K);
55tuple_impl!(A, B, C, D, E, F, G, H, I, J, K, L);
56
57#[inline]
58pub fn len(tuple: impl TupleLen) -> usize {
59    tuple.len()
60}
61
62#[cfg(test)]
63mod tests {
64    #[test]
65    fn r#macro() {
66        let _x: u8;
67
68        assert_eq!(tuple_len!(()), 0);
69        assert_eq!(tuple_len!((1)), 1);
70        assert_eq!(tuple_len!((1,)), 1);
71        assert_eq!(tuple_len!(((1, 1))), 1);
72        assert_eq!(tuple_len!((_x, _x)), 2);
73        assert_eq!(tuple_len!((_x, 1, _x)), 3);
74        assert_eq!(tuple_len!((_x, _x, Some("foo"), || {})), 4);
75    }
76
77    #[test]
78    fn macro_ident() {
79        let tuple = ();
80
81        assert_eq!(crate::tuple_len!(tuple), 0);
82        assert_eq!(crate::tuple_len!(&tuple), 0);
83    }
84
85    #[test]
86    fn r#trait() {
87        use crate::TupleLen;
88
89        let _x: u8 = 0;
90
91        assert_eq!(().len(), 0);
92        assert_eq!((1,).len(), 1);
93        assert_eq!((_x, _x).len(), 2);
94        assert_eq!((_x, 1, _x).len(), 3);
95        assert_eq!((_x, _x, Some("foo"), || {}).len(), 4);
96    }
97
98    #[test]
99    fn function() {
100        let _x: u8 = 0;
101
102        assert_eq!(crate::len(()), 0);
103        assert_eq!(crate::len(&()), 0);
104        assert_eq!(crate::len((1,)), 1);
105        assert_eq!(crate::len((_x, _x)), 2);
106        assert_eq!(crate::len((_x, 1, _x)), 3);
107        assert_eq!(crate::len((_x, _x, Some("foo"), || {})), 4);
108    }
109}