generic_array/
arr.rs

1//! Implementation for `arr!` macro.
2
3/// Macro allowing for easy construction of Generic Arrays.
4///
5/// Type-inference works similarly to `vec![]`
6///
7/// **`arr!` can be used in `const` expressions.**
8///
9/// Example:
10/// ```
11/// # use generic_array::arr;
12/// use generic_array::typenum::U6;
13///
14/// let test = arr![1, 2, 3]; // implicit length
15/// let test = arr![1; 6];    // explicit length via `Const<N>`
16/// let test = arr![1; U6];   // explicit length via typenum
17/// ```
18///
19/// # NOTES AND LIMITATIONS
20/// * As of `generic-array 1.0`, [`From`]/[`from_array`](crate::GenericArray::from_array) can be used directly for a wide range of regular arrays.
21/// * The `[T; N: ArrayLength]` and `[T; usize]` explicit forms are limited to `Copy` values. Use
22///     [`GenericArray::generate(|| value.clone())`](crate::GenericSequence::generate) for non-`Copy` items.
23/// * The `[T; usize]` explicit and `[0, 1, 2, 3]` implicit forms are limited to lengths supported by [`Const<U>`](typenum::Const)
24#[macro_export]
25macro_rules! arr {
26    ($($x:expr),* $(,)*) => ( $crate::GenericArray::from_array([$($x),*]) );
27    ($x:expr; $N:ty)     => ({
28        // Bypass `from_array` to allow for any Unsigned array length
29        const __INPUT_LENGTH: usize = <$N as $crate::typenum::Unsigned>::USIZE;
30
31        #[inline(always)]
32        const fn __do_transmute<T, N: $crate::ArrayLength>(arr: [T; __INPUT_LENGTH]) -> $crate::GenericArray<T, N> {
33            unsafe { $crate::const_transmute(arr) }
34        }
35
36        __do_transmute::<_, $N>([$x; __INPUT_LENGTH])
37    });
38    ($x:expr; $n:expr) => ( $crate::GenericArray::from_array([$x; $n]) );
39}
40
41/// Like [`arr!`], but returns a `Box<GenericArray<T, N>>`
42///
43/// Unlike [`arr!`], this is not limited by stack size, only the heap.
44///
45/// Example:
46/// ```
47/// # use generic_array::{box_arr, typenum::{self, *}};
48/// // allocate a 16MB Buffer of u128 elements (16 bytes * 10 ^ 6)
49/// # #[cfg(not(miri))]
50/// let test = box_arr![1u128; typenum::Exp<U10, U6>];
51/// //  test: Box<GenericArray<u128, _>>
52/// ```
53///
54/// # NOTES AND LIMITATIONS
55/// * The `[T; usize]` explicit and `[0, 1, 2, 3]` implicit forms are limited to lengths supported by [`Const<U>`](typenum::Const)
56#[cfg(feature = "alloc")]
57#[macro_export]
58macro_rules! box_arr {
59    ($($x:expr),* $(,)*) => ({
60        // deduce length based on a ZST array of units
61        $crate::GenericArray::__from_vec_helper([$($crate::box_arr_helper!(@unit $x)),*], $crate::alloc::vec![$($x),*])
62    });
63    ($x:expr; $N:ty) => ( $crate::GenericArray::<_, $N>::try_from_vec($crate::alloc::vec![$x; <$N as $crate::typenum::Unsigned>::USIZE]).unwrap() );
64    ($x:expr; $n:expr) => ({
65        const __LEN: usize = $n;
66
67        $crate::GenericArray::<_, <$crate::typenum::Const<__LEN> as $crate::IntoArrayLength>::ArrayLength>::try_from_vec($crate::alloc::vec![$x; __LEN]).unwrap()
68    });
69}
70
71#[cfg(feature = "alloc")]
72mod alloc_helper {
73    use crate::{ArrayLength, GenericArray, IntoArrayLength};
74
75    impl<T, N: ArrayLength> GenericArray<T, N> {
76        #[doc(hidden)]
77        #[inline(always)]
78        pub fn __from_vec_helper<const U: usize>(
79            _empty: [(); U],
80            vec: alloc::vec::Vec<T>,
81        ) -> alloc::boxed::Box<GenericArray<T, N>>
82        where
83            typenum::Const<U>: IntoArrayLength<ArrayLength = N>,
84        {
85            unsafe { GenericArray::try_from_vec(vec).unwrap_unchecked() }
86        }
87    }
88}
89
90// TODO: Remove this somehow?
91#[cfg(feature = "alloc")]
92#[doc(hidden)]
93#[macro_export]
94macro_rules! box_arr_helper {
95    (@unit $e:expr) => {
96        ()
97    };
98}
99
100mod doctests_only {
101    ///
102    /// Testing that lifetimes aren't transmuted when they're ellided.
103    ///
104    /// ```compile_fail
105    /// #[macro_use] extern crate generic_array;
106    /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
107    ///     arr![a as &A][0]
108    /// }
109    /// ```
110    ///
111    /// ```rust
112    /// #[macro_use] extern crate generic_array;
113    /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
114    ///     arr![a][0]
115    /// }
116    /// ```
117    #[allow(dead_code)]
118    pub enum DocTests {}
119}