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) => { 1 };
|
29 | ($T:ty; $N:ty, [$($x:expr),*], []) => ({
|
30 | const __ARR_LENGTH: usize = 0 $(+ $crate::arr_impl!(@replace_expr $x) )*;
|
31 |
|
32 | #[inline(always)]
|
33 | fn __do_transmute<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 as $T),*])
|
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 | $crate::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 | mod doctests_only {
|
70 | ///
|
71 | /// # With ellision
|
72 | ///
|
73 | /// Testing that lifetimes aren't transmuted when they're ellided.
|
74 | ///
|
75 | /// ```compile_fail
|
76 | /// #[macro_use] extern crate generic_array;
|
77 | /// fn main() {
|
78 | /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
|
79 | /// arr![&A; a][0]
|
80 | /// }
|
81 | /// }
|
82 | /// ```
|
83 | ///
|
84 | /// ```rust
|
85 | /// #[macro_use] extern crate generic_array;
|
86 | /// fn main() {
|
87 | /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
|
88 | /// arr![&A; a][0]
|
89 | /// }
|
90 | /// }
|
91 | /// ```
|
92 | ///
|
93 | /// # Without ellision
|
94 | ///
|
95 | /// Testing that lifetimes aren't transmuted when they're specified explicitly.
|
96 | ///
|
97 | /// ```compile_fail
|
98 | /// #[macro_use] extern crate generic_array;
|
99 | /// fn main() {
|
100 | /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
|
101 | /// arr![&'a A; a][0]
|
102 | /// }
|
103 | /// }
|
104 | /// ```
|
105 | ///
|
106 | /// ```compile_fail
|
107 | /// #[macro_use] extern crate generic_array;
|
108 | /// fn main() {
|
109 | /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
|
110 | /// arr![&'static A; a][0]
|
111 | /// }
|
112 | /// }
|
113 | /// ```
|
114 | ///
|
115 | /// ```rust
|
116 | /// #[macro_use] extern crate generic_array;
|
117 | /// fn main() {
|
118 | /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
|
119 | /// arr![&'a A; a][0]
|
120 | /// }
|
121 | /// }
|
122 | /// ```
|
123 | #[allow (dead_code)]
|
124 | pub enum DocTests {}
|
125 | }
|
126 | |