#[doc = crate::_tags!(init data_structure)]
#[doc = crate::_doc_location!("data/layout/array")]
#[doc = crate::doclink!(custom devela
"[`Box::from_raw`]" "sys/mem/struct.Box.html#method.from_raw")]
#[macro_export]
#[cfg_attr(cargo_primary_package, doc(hidden))]
macro_rules! init_array {
(
/* safe initializations */
// safe array initialization in the stack
safe_init [$T:ty; $LEN:expr], $init:expr) => {{
#[allow(clippy::redundant_closure_call, reason = "macro arg isn't redundant")]
::core::array::from_fn(|i| $init(i))
}};
(
// safe array initialization in the stack, compile-time friendly.
safe_const_fn [$T:ty; $LEN:expr], $const_fn:expr, $copiable:expr) => {{
let mut arr: [$T; $LEN] = [$copiable; $LEN];
let mut i = 0;
while i < $LEN {
arr[i] = $const_fn(i);
i += 1;
}
arr
}};
(
// safe array initialization in the heap
safe_init_heap [$T:ty; $LEN:expr], $init:expr) => {{
let mut v = Vec::<$T>::with_capacity($LEN);
for i in 0..$LEN {
#[allow(clippy::redundant_closure_call, reason = "macro arg isn't redundant")]
v.push($init(i));
}
v.into_boxed_slice().try_into().unwrap_or_else(|_| {
panic!("Can't turn the boxed slice into a boxed array")
})
}};
(
/* unsafe initializations */
// unsafe array initialization in the stack
// TODO:CHECK:AGAIN
unsafe_init [$T:ty; $LEN:expr], $init:expr) => {{
let mut arr: [$crate::MaybeUninit<$T>; $LEN] =
unsafe { $crate::MaybeUninit::uninit().assume_init() };
for (i, e) in &mut arr[..].iter_mut().enumerate() {
#[allow(clippy::redundant_closure_call, reason = "macro arg isn't redundant")]
let _ = e.write($init(i)); }
unsafe { ::core::mem::transmute_copy::<_, [$T; $LEN]>(&arr) }
}};
(
// unsafe array initialization in the stack, compile-time friendly.
unsafe_const_fn [$T:ty; $LEN:expr], $const_fn:expr) => {{
let mut arr: [$crate::MaybeUninit<$T>; $LEN] =
unsafe { $crate::MaybeUninit::uninit().assume_init() };
let mut i = 0;
while i < $LEN {
arr[i] = $crate::MaybeUninit::new($const_fn(i));
i += 1;
}
unsafe { ::core::mem::transmute_copy::<_, [$T; $LEN]>(&arr) }
}};
(
// unsafe array initialization in the heap
unsafe_init_heap [$T:ty; $LEN:expr], $init:expr) => {{
let mut v = Vec::<$T>::with_capacity($LEN);
#[allow(clippy::redundant_closure_call, reason = "macro arg isn't redundant")]
for i in 0..$LEN { v.push($init(i)); }
let slice = v.into_boxed_slice();
let raw_slice = Box::into_raw(slice);
unsafe { Box::from_raw(raw_slice as *mut [$T; $LEN]) }
}};
(
/* safety-agnostic initializations */
// initialize an array in the stack
init [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal, $init:expr) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init [$T; $LEN], $init] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init [$T; $LEN], $init] }
}};
(
// initialize an array the stack, compile-time friendly.
// $copiable is only used by the safe version as temporary placeholder.
const_fn
[$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal, $const_fn:expr, $copiable:expr) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_const_fn [$T; $LEN], $const_fn, $copiable] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_const_fn [$T; $LEN], $const_fn ] }
}};
(
// initialize an array in the heap
init_heap [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal, $init:expr) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init_heap [$T; $LEN], $init] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init_heap [$T; $LEN], $init] }
}};
(
// initialize an array in the stack by cloning $clonable
clone [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal, $clonable:expr) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init [$T; $LEN], |_| $clonable.clone()] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init [$T; $LEN], |_| $clonable.clone()] }
}};
(
// initialize an array in the heap, by cloning $clonable
clone_heap [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal, $clonable:expr) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init_heap [$T; $LEN], |_| $clonable.clone()] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init_heap [$T; $LEN], |_| $clonable.clone()] }
}};
(
// initialize an array in the stack with $T: Default::default()
default [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init [$T; $LEN], |_| <$T>::default()] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init [$T; $LEN], |_| <$T>::default()] }
}};
(
INIT in $trait:path [$T:ty; $LEN:expr]) => {{
[<$T as $trait>::INIT; $LEN]
}};
(
default_heap [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init_heap [$T; $LEN], |_| <$T>::default()] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init_heap [$T; $LEN], |_| <$T>::default()] }
}};
(
iter [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal, $intoiter:expr) => {{
let mut iterator = $intoiter.into_iter();
let mut init_closure = |_| {
if let Some(e) = iterator.next() { e } else { <$T>::default() }
};
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init [$T; $LEN], init_closure] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init [$T; $LEN], init_closure] }
}};
(
iter_heap [$T:ty; $LEN:expr], $fsafe:literal, $funsafe:literal, $intoiter:expr) => {{
let mut iterator = $intoiter.into_iter();
let mut init_closure = |_| {
if let Some(e) = iterator.next() { e } else { <$T>::default() }
};
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{ $crate::init_array![safe_init_heap [$T; $LEN], init_closure] }
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{ $crate::init_array![unsafe_init_heap [$T; $LEN], init_closure] }
}};
(
preop [$T:ty; $LEN:expr]?, $fsafe:literal, $funsafe:literal, $pre:expr, $op:expr) => {{
#[cfg(any(feature = $fsafe, not(feature = $funsafe)))]
{
let init_value = $pre?; let mut arr: [$T; $LEN] = ::core::array::from_fn(|_| init_value.clone());
for (i, data) in $op.enumerate() {
arr[i] = data?;
}
arr
}
#[cfg(all(not(feature = $fsafe), feature = $funsafe))]
{
let mut arr: [$crate::MaybeUninit<$T>; $LEN] =
unsafe { $crate::MaybeUninit::uninit().assume_init() };
for (i, data) in $op.enumerate() {
arr[i].write(data?);
}
unsafe { ::core::mem::transmute_copy::<_, [$T; $LEN]>(&arr) }
}
}};
}
#[doc(inline)]
pub use init_array;