1 //! Implementation for `arr!` macro.
2 
3 use super::ArrayLength;
4 use core::ops::Add;
5 use typenum::U1;
6 
7 /// Helper trait for `arr!` macro
8 pub trait AddLength<T, N: ArrayLength<T>>: ArrayLength<T> {
9     /// Resulting length
10     type Output: ArrayLength<T>;
11 }
12 
13 impl<T, N1, N2> AddLength<T, N2> for N1
14 where
15     N1: ArrayLength<T> + Add<N2>,
16     N2: ArrayLength<T>,
17     <N1 as Add<N2>>::Output: ArrayLength<T>,
18 {
19     type Output = <N1 as Add<N2>>::Output;
20 }
21 
22 /// Helper type for `arr!` macro
23 pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;
24 
25 #[doc(hidden)]
26 #[macro_export]
27 macro_rules! arr_impl {
28     (@replace_expr $e:expr)=>{
29         1
30     };
31     ($T:ty; $N:ty, [$($x:expr),*], []) => ({
32         const __ARR_LENGTH:usize=0 $(+ $crate::arr_impl!(@replace_expr $x) )*;
33         fn __do_transmute<'a, T, N: $crate::ArrayLength<T>>(arr: [T; __ARR_LENGTH]) -> $crate::GenericArray<T, N> {
34             unsafe { $crate::transmute(arr) }
35         }
36 
37         let _:[();<$N as $crate::typenum::Unsigned>::USIZE]=[();__ARR_LENGTH];
38 
39         __do_transmute::<$T,$N>([$($x),*])
40     });
41     ($T:ty; $N:ty, [], [$x1:expr]) => (
42         $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [])
43     );
44     ($T:ty; $N:ty, [], [$x1:expr, $($x:expr),+]) => (
45         $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$x1], [$($x),+])
46     );
47     ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr]) => (
48         $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [])
49     );
50     ($T:ty; $N:ty, [$($y:expr),+], [$x1:expr, $($x:expr),+]) => (
51         $crate::arr_impl!($T; $crate::arr::Inc<$T, $N>, [$($y),+, $x1], [$($x),+])
52     );
53 }
54 
55 /// Macro allowing for easy generation of Generic Arrays.
56 /// Example: `let test = arr![u32; 1, 2, 3];`
57 #[macro_export]
58 macro_rules! arr {
59     ($T:ty; $(,)*) => ({
60         unsafe { $crate::transmute::<[$T; 0], $crate::GenericArray<$T, $crate::typenum::U0>>([]) }
61     });
62     ($T:ty; $($x:expr),* $(,)*) => (
63         arr_impl!($T; $crate::typenum::U0, [], [$($x),*])
64     );
65     ($($x:expr,)+) => (arr![$($x),*]);
66     () => ("""Macro requires a type, e.g. `let array = arr![u32; 1, 2, 3];`")
67 }
68 
69 
70 mod doctests_only{
71     ///
72     /// # With ellision
73     ///
74     /// Testing that lifetimes aren't transmuted when they're ellided.
75     ///
76     /// ```compile_fail
77     /// #[macro_use] extern crate generic_array;
78     /// fn main() {
79     ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
80     ///        arr![&A; a][0]
81     ///    }
82     /// }
83     /// ```
84     ///
85     /// ```rust
86     /// #[macro_use] extern crate generic_array;
87     /// fn main() {
88     ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
89     ///        arr![&A; a][0]
90     ///    }
91     /// }
92     /// ```
93     ///
94     /// # Without ellision
95     ///
96     /// Testing that lifetimes aren't transmuted when they're specified explicitly.
97     ///
98     /// ```compile_fail
99     /// #[macro_use] extern crate generic_array;
100     /// fn main() {
101     ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
102     ///        arr![&'a A; a][0]
103     ///    }
104     /// }
105     /// ```
106     ///
107     /// ```compile_fail
108     /// #[macro_use] extern crate generic_array;
109     /// fn main() {
110     ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
111     ///        arr![&'static A; a][0]
112     ///    }
113     /// }
114     /// ```
115     ///
116     /// ```rust
117     /// #[macro_use] extern crate generic_array;
118     /// fn main() {
119     ///    fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
120     ///        arr![&'a A; a][0]
121     ///    }
122     /// }
123     /// ```
124     #[allow(dead_code)]
125     pub enum DocTests{}
126 }
127