use std::mem::MaybeUninit;
#[macro_export]
macro_rules! const_assert {
($x:expr $(,)?) => {
#[allow(clippy::const_is_empty, clippy::eq_op, unknown_lints)]
const _: [(); 0 - !{
const CONST_ASSERT: bool = $x;
CONST_ASSERT
} as usize] = [];
};
}
#[macro_export]
macro_rules! const_assert_usize_eq {
($x:expr, $y:expr $(,)?) => {
const _: [(); $x] = [(); $y];
};
}
#[macro_export]
macro_rules! const_assert_mem_size {
($type:ty, $size:expr $(,)?) => {
#[cfg(target_pointer_width = "64")]
$crate::const_assert_usize_eq!(::core::mem::size_of::<$type>(), $size);
};
}
pub const fn const_result_unwrap<T: Copy, E: Copy>(result: Result<T, E>) -> T {
match result {
Ok(result) => result,
Err(_) => panic!("unwrap on Err"),
}
}
#[cfg(feature = "ref-cast")]
pub const fn const_ref_cast<T: ref_cast::RefCast>(from: &T::From) -> &T {
unsafe { &*(from as *const T::From as *const T) }
}
#[macro_export]
macro_rules! const_concat_str {
($($s:expr),* $(,)?) => {{
use $crate::std::primitive::{str, u8};
$(const _: &str = $s;)*
const LEN: usize = 0 $(+ $s.len())*;
const ARR: [u8; LEN] = $crate::const_utils::const_concat_inner::<LEN, _>(
&[$($s.as_bytes()),*]
);
unsafe { $crate::std::str::from_utf8_unchecked(&ARR) }
}};
}
#[macro_export]
macro_rules! const_concat_bytes {
($($slice:expr),* $(,)?) => {{
use $crate::std::primitive::u8;
$(const _: &[u8] = $slice;)*
const LEN: usize = 0 $(+ $slice.len())*;
const ARR: [u8; LEN] = $crate::const_utils::const_concat_inner::<LEN, _>(
&[$($slice),*]
);
&ARR
}};
}
#[doc(hidden)]
pub const fn const_concat_inner<const LEN: usize, T: Copy>(
slices: &[&[T]],
) -> [T; LEN] {
let mut arr: [MaybeUninit<T>; LEN] = [MaybeUninit::uninit(); LEN];
let mut base = 0;
let mut i = 0;
while i < slices.len() {
let slice = slices[i];
let mut j = 0;
while j < slice.len() {
arr[base + j] = MaybeUninit::new(slice[j]);
j += 1;
}
base += slice.len();
i += 1;
}
if base != LEN {
panic!("invalid length");
}
unsafe { std::mem::transmute_copy::<[MaybeUninit<T>; LEN], [T; LEN]>(&arr) }
}