| 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 | |