use {
crate::{Linearize, StaticMap},
core::{mem::MaybeUninit, ptr},
};
#[doc(hidden)]
#[macro_export]
macro_rules! static_map_internal_wrapper {
($builder_name:ident, $builder_val:expr, $($tt:tt)*) => {{
let mut $builder_name = $builder_val;
if false {
unsafe {
::core::hint::unreachable_unchecked();
#[deny(unfulfilled_lint_expectations)]
#[expect(unreachable_code)]
$builder_name.get()
}
} else {
$($tt)*
}
}};
}
#[doc(hidden)]
#[macro_export]
macro_rules! static_map_internal {
($builder_name:ident, $builder_val:expr, $i:ident, $val:ident, $get_key:expr, $set_value:expr, $($tt:tt)*) => {{
$crate::static_map_internal_wrapper! {
$builder_name,
$builder_val,
let mut $i = 0;
let len = $builder_name.len();
while $i < len {
struct PleaseDoNotUseBreakWithoutLabel;
let please_do_not_use_continue_without_label;
let $val;
loop {
please_do_not_use_continue_without_label = ();
let key = $get_key;
$val = match key {
$($tt)*
};
break PleaseDoNotUseBreakWithoutLabel;
};
let _ = please_do_not_use_continue_without_label;
$set_value;
$i += 1;
}
unsafe {
$builder_name.get()
}
}
}};
}
#[cfg_attr(more_const_functions, doc = " ```rust")]
#[cfg_attr(not(more_const_functions), doc = " ```rust,ignore")]
#[doc = " ```"]
#[cfg_attr(more_const_functions, doc = " ```rust")]
#[cfg_attr(not(more_const_functions), doc = " ```rust,ignore")]
#[doc = " ```"]
#[macro_export]
macro_rules! static_map {
(constants of type $ty:ty: $($key:expr => $val:expr),*$(,)?) => {
$crate::static_map_internal_wrapper! {
builder,
$crate::Builder::<$ty, _>::new(),
const {
let mut init = [false; <$ty as $crate::Linearize>::LENGTH];
$(
let i = <$ty>::__linearize_d66aa8fa_6974_4651_b2b7_75291a9e7105(&$key);
init[i] = true;
)*
let mut i = 0;
while i < <$ty as $crate::Linearize>::LENGTH {
if !init[i] {
core::panic!("Not all keys are initialized");
}
i += 1;
}
}
const fn write<T>(builder: &mut $crate::Builder<$ty, T>, i: usize, v: T) {
unsafe {
core::ptr::write(builder.0.as_mut_ptr().cast::<T>().add(i), v);
}
}
$(
let i = <$ty>::__linearize_d66aa8fa_6974_4651_b2b7_75291a9e7105(&$key);
write(&mut builder, i, $val);
)*
unsafe {
builder.get()
}
}
};
(of type $ty:ty: $($tt:tt)*) => {
$crate::static_map_internal! {
builder,
$crate::Builder::<$ty, _>::new(),
i,
val,
unsafe {
<$ty>::__from_linear_unchecked_fb2f0b31_5b5a_48b4_9264_39d0bdf94f1d(i)
},
{
const fn write<T>(builder: &mut $crate::Builder<$ty, T>, i: usize, v: T) {
unsafe {
core::ptr::write(builder.0.as_mut_ptr().cast::<T>().add(i), v);
}
}
write(&mut builder, i, val);
},
$($tt)*
}
};
($($tt:tt)*) => {
$crate::static_map_internal! {
builder,
$crate::Builder::new(),
i,
val,
unsafe {
builder.key(i)
},
unsafe {
builder.set(i, val);
},
$($tt)*
}
};
}
#[macro_export]
macro_rules! static_copy_map {
(constants of type $ty:ty: $($key:expr => $val:expr),*$(,)?) => {
$crate::StaticCopyMap($crate::static_map!(constants of type $ty: $($key => $val,)*).0)
};
(of type $ty:ty: $($tt:tt)*) => {
$crate::StaticCopyMap($crate::static_map!(of type $ty: $($tt)*).0)
};
($($tt:tt)*) => {
$crate::StaticCopyMap::from_static_map($crate::static_map!($($tt)*))
};
}
pub struct Builder<L, T>(pub MaybeUninit<StaticMap<L, T>>)
where
L: Linearize;
impl<L, T> Builder<L, T>
where
L: Linearize,
{
#[allow(clippy::new_without_default)]
#[inline]
pub const fn new() -> Self {
Self(MaybeUninit::uninit())
}
#[allow(clippy::len_without_is_empty)]
#[inline]
pub const fn len(&self) -> usize {
L::LENGTH
}
#[inline]
pub unsafe fn key(&self, i: usize) -> L {
unsafe {
L::from_linear_unchecked(i)
}
}
#[inline]
pub unsafe fn set(&mut self, i: usize, v: T) {
unsafe {
ptr::write(self.0.as_mut_ptr().cast::<T>().add(i), v);
}
}
#[inline]
pub const unsafe fn get(self) -> StaticMap<L, T> {
unsafe {
self.0.assume_init()
}
}
pub fn init_map(&self) -> StaticMap<L, bool> {
StaticMap::default()
}
}