#![no_std]
#![deny(missing_docs)]
mod enum_map_impls;
mod internal;
mod iter;
mod serde;
#[doc(hidden)]
pub use core::mem::{ManuallyDrop, MaybeUninit};
#[doc(hidden)]
pub use core::ptr;
pub use enum_map_derive::Enum;
use internal::Array;
pub use internal::Enum;
pub use iter::{IntoIter, Iter, IterMut, Values, ValuesMut};
#[doc(hidden)]
#[non_exhaustive]
pub struct ArrayVec<K, V>
where
K: Enum<V>,
{
pub array: MaybeUninit<K::Array>,
pub length: usize,
}
impl<K, V> ArrayVec<K, V>
where
K: Enum<V>,
{
#[doc(hidden)]
pub unsafe fn new() -> Self {
ArrayVec {
array: MaybeUninit::uninit(),
length: 0,
}
}
#[doc(hidden)]
pub fn storage_length(&self) -> usize {
K::Array::LENGTH
}
#[doc(hidden)]
pub fn get_key(&self) -> K {
K::from_usize(self.length)
}
#[doc(hidden)]
pub unsafe fn push(&mut self, value: V) {
self.array
.as_mut_ptr()
.cast::<V>()
.add(self.length)
.write(value);
self.length += 1;
}
}
impl<K, V> Drop for ArrayVec<K, V>
where
K: Enum<V>,
{
fn drop(&mut self) {
unsafe {
ptr::slice_from_raw_parts_mut(self.array.as_mut_ptr() as *mut V, self.length)
.drop_in_place();
}
}
}
#[doc(hidden)]
pub union TypeEqualizer<K, V>
where
K: Enum<V>,
{
pub init: (),
pub enum_map: ManuallyDrop<EnumMap<K, V>>,
pub array_vec: ManuallyDrop<ArrayVec<K, V>>,
}
#[macro_export]
macro_rules! enum_map {
{$($t:tt)*} => {{
let mut type_equalizer = $crate::TypeEqualizer { init: () };
if false {
unsafe {
type_equalizer.enum_map = $crate::MaybeUninit::assume_init($crate::MaybeUninit::uninit());
$crate::ManuallyDrop::into_inner(type_equalizer.enum_map)
}
} else {
type_equalizer.array_vec = $crate::ManuallyDrop::new(unsafe { $crate::ArrayVec::new() });
let mut vec = $crate::ManuallyDrop::into_inner(unsafe { type_equalizer.array_vec });
for _ in 0..$crate::ArrayVec::storage_length(&vec) {
let _please_do_not_use_continue_without_label;
let value;
struct __PleaseDoNotUseBreakWithoutLabel;
#[allow(unreachable_code)]
loop {
_please_do_not_use_continue_without_label = ();
value = match $crate::ArrayVec::get_key(&vec) { $($t)* };
break __PleaseDoNotUseBreakWithoutLabel;
};
unsafe { $crate::ArrayVec::push(&mut vec, value); }
}
vec.length = 0;
$crate::EnumMap::from_array(unsafe { $crate::ptr::read($crate::MaybeUninit::as_ptr(&vec.array)) })
}
}};
}
pub struct EnumMap<K: Enum<V>, V> {
array: K::Array,
}
impl<K: Enum<V>, V: Default> EnumMap<K, V> {
#[inline]
pub fn clear(&mut self) {
for v in self.as_mut_slice() {
*v = V::default();
}
}
}
#[allow(clippy::len_without_is_empty)]
impl<K: Enum<V>, V> EnumMap<K, V> {
#[inline]
pub fn from_array(array: K::Array) -> EnumMap<K, V> {
EnumMap { array }
}
#[inline]
pub fn iter(&self) -> Iter<K, V> {
self.into_iter()
}
#[inline]
pub fn iter_mut(&mut self) -> IterMut<K, V> {
self.into_iter()
}
#[inline]
pub fn len(&self) -> usize {
self.as_slice().len()
}
#[inline]
pub fn swap(&mut self, a: K, b: K) {
self.as_mut_slice().swap(a.into_usize(), b.into_usize())
}
#[inline]
pub fn as_slice(&self) -> &[V] {
self.array.slice()
}
#[inline]
pub fn as_mut_slice(&mut self) -> &mut [V] {
self.array.slice_mut()
}
}