konst_macro_rules/
slice_.rs

1#![allow(non_camel_case_types)]
2
3use core::{
4    fmt::{self, Display},
5    marker::PhantomData,
6};
7
8#[macro_export]
9macro_rules! try_into_array {
10    ($slice:expr, $len:expr$(,)*) => {
11        match $slice {
12            (_x) => unsafe { $crate::__priv_try_into_array!(explicit, _x, $len) },
13        }
14    };
15    ($slice:expr $(,)*) => {
16        match $slice {
17            (_x) => unsafe { $crate::__priv_try_into_array!(infer, _x) },
18        }
19    };
20}
21
22#[macro_export]
23#[cfg(not(feature = "rust_1_51"))]
24macro_rules! __priv_try_into_array {
25    // This implementation is used when const generics are disabled.
26    (explicit, $slice:ident, $len:expr) => {{
27        const __LEN: usize = $len;
28
29        let slice = $crate::slice_::__priv_SliceLifetime($slice, $crate::slice_::Phantom::NEW);
30
31        type __Constrainer<'a, T> = $crate::slice_::__priv_TypeLifetime<'a, [T; __LEN], T>;
32
33        if slice.0.len() == __LEN {
34            let ptr = slice.0.as_ptr() as *const [_; __LEN];
35
36            let ret = __Constrainer {
37                array: $crate::utils::Dereference { ptr }.reff,
38                phantom: slice.1,
39            };
40
41            $crate::__::Ok(ret.array)
42        } else {
43            $crate::__::Err($crate::slice_::TryIntoArrayError::__priv__new())
44        }
45    }};
46    (infer, $slice:ident) => {
47        $crate::__::compile_error!(concat!(
48            "\
49                To infer the length of the returned array,\n\
50                you must enable the  \"rust_1_51\" feature (which requires Rust 1.51.0).\n\
51                \n\
52                Otherwise you need to pass the length explicitly, \
53                eg: try_into_array!(foo, 10)"
54        ))
55    };
56}
57
58#[macro_export]
59#[cfg(feature = "rust_1_51")]
60macro_rules! __priv_try_into_array {
61    // This implementation is used when const generics are enabled,
62    // and should work with arrays like ARR in
63    // ```
64    // impl Foo<T: Trait> {
65    //      const ARR: &'static [u32; T::CONST] = try_into_array!(...);
66    // }
67    // ```
68    // whenever array types like that are allowed.
69    (explicit, $slice:ident, $len:expr) => {{
70        let slice = $crate::slice_::__priv_SliceLifetime($slice, $crate::slice_::Phantom::NEW);
71        let plen = $crate::slice_::PhantomUsize::<{ $len }>;
72
73        $crate::__priv_try_into_array! {inner, slice, plen}
74    }};
75    (infer, $slice:ident) => {
76        loop {
77            let slice = $crate::slice_::__priv_SliceLifetime($slice, $crate::slice_::Phantom::NEW);
78            let plen = $crate::slice_::PhantomUsize;
79
80            if false {
81                break $crate::slice_::get_length(plen);
82            }
83
84            break $crate::__priv_try_into_array! {inner, slice, plen};
85        }
86    };
87    (inner, $slice:ident, $len:ident) => {
88        if let (true, ptr) = $crate::slice_::check_length($slice.0, $len) {
89            let array = $crate::utils::Dereference { ptr }.reff;
90
91            $crate::__::Ok($crate::slice_::__priv_ArrayLifetime(array, $slice.1).0)
92        } else {
93            $crate::__::Err($crate::slice_::TryIntoArrayError::__priv__new())
94        }
95    };
96}
97
98pub struct Phantom<'a, T>(PhantomData<*mut *mut &'a [T]>);
99
100impl<'a, T: 'a> Phantom<'a, T> {
101    pub const NEW: Self = Self(PhantomData);
102}
103
104#[repr(transparent)]
105pub struct __priv_TypeLifetime<'a, T, U> {
106    pub array: &'a T,
107    pub phantom: Phantom<'a, U>,
108}
109
110#[repr(transparent)]
111pub struct __priv_SliceLifetime<'a, T>(pub &'a [T], pub Phantom<'a, T>);
112
113#[cfg(feature = "rust_1_51")]
114#[derive(Copy, Clone)]
115pub struct PhantomUsize<const N: usize>;
116
117#[cfg(feature = "rust_1_51")]
118pub const fn get_length<'a, T, const N: usize>(
119    _: PhantomUsize<N>,
120) -> Result<&'a [T; N], TryIntoArrayError> {
121    loop {}
122}
123
124#[inline(always)]
125#[cfg(feature = "rust_1_51")]
126pub const fn check_length<T, const N: usize>(
127    slice: &[T],
128    _len: PhantomUsize<N>,
129) -> (bool, *const [T; N]) {
130    (N == slice.len(), slice.as_ptr() as *const [T; N])
131}
132
133#[repr(transparent)]
134#[cfg(feature = "rust_1_51")]
135pub struct __priv_ArrayLifetime<'a, T, const N: usize>(pub &'a [T; N], pub Phantom<'a, T>);
136
137////////////////////////////////////////////////////////////////////////////////
138
139#[cfg(feature = "rust_1_56")]
140#[inline]
141pub const fn try_into_array_func<T, const N: usize>(
142    slice: &[T],
143) -> Result<&[T; N], TryIntoArrayError> {
144    if slice.len() == N {
145        let ptr = slice.as_ptr() as *const [T; N];
146        unsafe { Ok(crate::utils::Dereference { ptr }.reff) }
147    } else {
148        Err(TryIntoArrayError { _priv: () })
149    }
150}
151
152////////////////////////////////////////////////////////////////////////////////
153
154#[cfg(feature = "mut_refs")]
155#[inline]
156pub const fn try_into_array_mut_func<T, const N: usize>(
157    slice: &mut [T],
158) -> Result<&mut [T; N], TryIntoArrayError> {
159    if slice.len() == N {
160        let ptr = slice as *mut [T] as *mut [T; N];
161        unsafe { Ok(crate::utils::deref_raw_mut_ptr(ptr)) }
162    } else {
163        Err(TryIntoArrayError { _priv: () })
164    }
165}
166
167////////////////////////////////////////////////////////////////////////////////
168
169#[derive(Debug, PartialEq, Eq, Copy, Clone)]
170pub struct TryIntoArrayError {
171    _priv: (),
172}
173
174impl TryIntoArrayError {
175    #[allow(non_snake_case)]
176    #[doc(hidden)]
177    #[inline]
178    pub const fn __priv__new() -> Self {
179        TryIntoArrayError { _priv: () }
180    }
181
182    /// For erroring with an error message.
183    pub const fn panic(&self) -> ! {
184        let offset = self.number();
185        [/*Could not cast &[T] to &[T; N]*/][offset]
186    }
187
188    const fn number(&self) -> usize {
189        0
190    }
191}
192
193impl Display for TryIntoArrayError {
194    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195        f.write_str("Could not cast slice to array reference")
196    }
197}