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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//! Implementation for `arr!` macro.

use super::ArrayLength;
use core::ops::Add;
use typenum::U1;

/// Helper trait for `arr!` macro
pub trait AddLength<T, N: ArrayLength>: ArrayLength {
    /// Resulting length
    type Output: ArrayLength;
}

impl<T, N1, N2> AddLength<T, N2> for N1
where
    N1: ArrayLength + Add<N2>,
    N2: ArrayLength,
    <N1 as Add<N2>>::Output: ArrayLength,
{
    type Output = <N1 as Add<N2>>::Output;
}

/// Helper type for `arr!` macro
pub type Inc<T, U> = <U as AddLength<T, U1>>::Output;

#[doc(hidden)]
#[macro_export]
macro_rules! arr_impl {
    (@replace_expr $e:expr) => { 1 };
    (@count_ty) => { $crate::typenum::U0 };
    (@count_ty $val:expr$(, $vals:expr)* $(,)?) => { $crate::typenum::Add1<$crate::arr_impl!(@count_ty $($vals),*)> };
    ($($x:expr),*) => ({
        const __INPUT_LENGTH: usize = 0 $(+ $crate::arr_impl!(@replace_expr $x) )*;
        type __OutputLength = $crate::arr_impl!(@count_ty $($x),*);

        #[inline(always)]
        const fn __do_transmute<T, N: $crate::ArrayLength>(arr: [T; __INPUT_LENGTH]) -> $crate::GenericArray<T, N> {
            unsafe { $crate::transmute(arr) }
        }

        const _: [(); <__OutputLength as $crate::typenum::Unsigned>::USIZE] = [(); __INPUT_LENGTH];

        __do_transmute::<_, __OutputLength>([$($x),*])
    });
    ($x:expr; $N:ty) => ({
        const __INPUT_LENGTH: usize = <$N as $crate::typenum::Unsigned>::USIZE;

        #[inline(always)]
        const fn __do_transmute<T, N: $crate::ArrayLength>(arr: [T; __INPUT_LENGTH]) -> $crate::GenericArray<T, N> {
            unsafe { $crate::transmute(arr) }
        }

        __do_transmute::<_, $N>([$x; __INPUT_LENGTH])
    });
}

/// Macro allowing for easy generation of Generic Arrays.
///
/// Type-inference works similarly to `vec![]`
///
/// Can be used in `const` contexts.
///
/// Example:
/// ```
/// # use generic_array::arr;
/// use generic_array::typenum::U6;
///
/// let test = arr![1, 2, 3]; // implicit length
/// let test = arr![1; U6];   // explicit length
/// ```
///
/// NOTE: As of `generic-array 1.0`, [`From`] can be used for a wide range of regular arrays as well.
#[macro_export]
macro_rules! arr {
    ($($x:expr),* $(,)*) => ( $crate::arr_impl!($($x),*) );
    ($x:expr; $N:ty)     => ( $crate::arr_impl!($x; $N) );
}

/// Like [`arr!`], but returns a `Box<GenericArray<T, N>>`
///
/// Unlike [`arr!`], this is not limited by stack size, only the heap.
///
/// Example:
/// ```
/// # use generic_array::{box_arr, typenum::{self, *}};
/// // allocate a 16MB Buffer of u128 elements (16 bytes * 10 ^ 6)
/// # #[cfg(not(miri))]
/// let test = box_arr![1u128; typenum::Exp<U10, U6>];
/// //  test: Box<GenericArray<u128, _>>
/// ```
#[cfg(feature = "alloc")]
#[macro_export]
macro_rules! box_arr {
    ($($x:expr),* $(,)*) => ({
        type __OutputLength = $crate::arr_impl!(@count_ty $($x),*);
        $crate::GenericArray::<_, __OutputLength>::try_from_vec($crate::alloc::vec![$($x),*]).unwrap()
    });
    ($x:expr; $N:ty) => ( $crate::GenericArray::<_, $N>::try_from_vec($crate::alloc::vec![$x; <$N as $crate::typenum::Unsigned>::USIZE]).unwrap() );
}

mod doctests_only {
    ///
    /// # With ellision
    ///
    /// Testing that lifetimes aren't transmuted when they're ellided.
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///     arr![a as &A][0]
    /// }
    /// ```
    ///
    /// ```rust
    /// #[macro_use] extern crate generic_array;
    /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
    ///     arr![a][0]
    /// }
    /// ```
    ///
    /// # Without ellision
    ///
    /// Testing that lifetimes aren't transmuted when they're specified explicitly.
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///     arr![a][0]
    /// }
    /// ```
    ///
    /// ```compile_fail
    /// #[macro_use] extern crate generic_array;
    /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'static A {
    ///     arr![a][0]
    /// }
    /// ```
    ///
    /// ```rust
    /// #[macro_use] extern crate generic_array;
    /// fn unsound_lifetime_extension<'a, A>(a: &'a A) -> &'a A {
    ///     arr![a][0]
    /// }
    /// ```
    #[allow(dead_code)]
    pub enum DocTests {}
}