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