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}