#[cfg(feature = "arbitrary")] mod arbitrary; mod enum_map_impls; mod internal; mod iter; #[cfg(feature = "serde")] mod serde;
#[doc(hidden)] pubuse core::mem::{self, ManuallyDrop, MaybeUninit}; #[doc(hidden)] pubuse core::primitive::usize; use core::slice; #[doc(hidden)] // unreachable needs to be exported for compatibility with older versions of enum-map-derive pubuse core::{panic, ptr, unreachable}; pubuse enum_map_derive::Enum; #[doc(hidden)] pubuse internal::out_of_bounds; use internal::Array; pubuse internal::{Enum, EnumArray}; pubuse iter::{IntoIter, IntoValues, Iter, IterMut, Values, ValuesMut};
// SAFETY: initialized needs to represent number of initialized elements #[doc(hidden)] pubstruct Guard<'a, K, V> where
K: EnumArray<V>,
{
array_mut: &'a mut MaybeUninit<K::Array>,
initialized: usize,
}
impl<K, V> Drop for Guard<'_, K, V> where
K: EnumArray<V>,
{ fn drop(&mutself) { // This is safe as arr[..len] is initialized due to // Guard's type invariant. unsafe {
ptr::slice_from_raw_parts_mut(self.as_mut_ptr(), self.initialized).drop_in_place();
}
}
}
impl<'a, K, V> Guard<'a, K, V> where
K: EnumArray<V>,
{ #[doc(hidden)] pubfn as_mut_ptr(&mutself) -> *mut V { self.array_mut.as_mut_ptr().cast::<V>()
}
#[doc(hidden)] #[must_use] #[allow(clippy::unused_self)] pubfn storage_length(&self) -> usize { // SAFETY: We need to use LENGTH from K::Array, as K::LENGTH is // untrustworthy.
K::Array::LENGTH
}
#[doc(hidden)] #[must_use] pubfn get_key(&self) -> K {
K::from_usize(self.initialized)
}
#[doc(hidden)] // Unsafe as it can write out of bounds. pubunsafefn push(&mutself, value: V) { self.as_mut_ptr().add(self.initialized).write(value); self.initialized += 1;
}
}
/// Enum map constructor. /// /// This macro allows to create a new enum map in a type safe way. It takes /// a list of `,` separated pairs separated by `=>`. Left side is `|` /// separated list of enum keys, or `_` to match all unmatched enum keys, /// while right side is a value. /// /// The iteration order when using this macro is not guaranteed to be /// consistent. Future releases of this crate may change it, and this is not /// considered to be a breaking change. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Enum)] /// enum Example { /// A, /// B, /// C, /// D, /// } /// /// let enum_map = enum_map! { /// Example::A | Example::B => 1, /// Example::C => 2, /// _ => 3, /// }; /// assert_eq!(enum_map[Example::A], 1); /// assert_eq!(enum_map[Example::B], 1); /// assert_eq!(enum_map[Example::C], 2); /// assert_eq!(enum_map[Example::D], 3); /// ``` #[macro_export]
macro_rules! enum_map {
{$($t:tt)*} => {{ letmut uninit = $crate::MaybeUninit::uninit(); letmut eq = $crate::TypeEqualizer {
enum_map: [],
guard: $crate::Guard::new(&mut uninit),
}; iffalse { // Safe because this code is unreachable unsafe { (&mut eq.enum_map).as_mut_ptr().read() }
} else { for _ in0..(&eq.guard).storage_length() { struct __PleaseDoNotUseBreakWithoutLabel; let _please_do_not_use_continue_without_label; let value; #[allow(unreachable_code)] loop {
_please_do_not_use_continue_without_label = ();
value = match (&eq.guard).get_key() { $($t)* }; break __PleaseDoNotUseBreakWithoutLabel;
};
unsafe { (&mut eq.guard).push(value); }
}
$crate::mem::forget(eq); // Safe because the array was fully initialized.
$crate::EnumMap::from_array(unsafe { uninit.assume_init() })
}
}};
}
/// An enum mapping. /// /// This internally uses an array which stores a value for each possible /// enum value. To work, it requires implementation of internal (private, /// although public due to macro limitations) trait which allows extracting /// information about an enum, which can be automatically generated using /// `#[derive(Enum)]` macro. /// /// Additionally, `bool` and `u8` automatically derives from `Enum`. While /// `u8` is not technically an enum, it's convenient to consider it like one. /// In particular, [reverse-complement in benchmark game] could be using `u8` /// as an enum. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum, EnumMap}; /// /// #[derive(Enum)] /// enum Example { /// A, /// B, /// C, /// } /// /// let mut map = EnumMap::default(); /// // new initializes map with default values /// assert_eq!(map[Example::A], 0); /// map[Example::A] = 3; /// assert_eq!(map[Example::A], 3); /// ``` /// /// [reverse-complement in benchmark game]: /// http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2 pubstruct EnumMap<K: EnumArray<V>, V> {
array: K::Array,
}
/// Create an enum map, where each value is the returned value from `cb` /// using provided enum key. /// /// ``` /// # use enum_map_derive::*; /// use enum_map::{enum_map, Enum, EnumMap}; /// /// #[derive(Enum, PartialEq, Debug)] /// enum Example { /// A, /// B, /// } /// /// let map = EnumMap::from_fn(|k| k == Example::A); /// assert_eq!(map, enum_map! { Example::A => true, Example::B => false }) /// ``` pubfn from_fn<F>(mut cb: F) -> Self where
F: FnMut(K) -> V,
{
enum_map! { k => cb(k) }
}
/// Returns an iterator over enum map. /// /// The iteration order is deterministic, and when using [macro@Enum] derive /// it will be the order in which enum variants are declared. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Enum, PartialEq)] /// enum E { /// A, /// B, /// C, /// } /// /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3}; /// assert!(map.iter().eq([(E::A, &1), (E::B, &2), (E::C, &3)])); /// ``` #[inline] pubfn iter(&self) -> Iter<K, V> { self.into_iter()
}
/// Returns a mutable iterator over enum map. #[inline] pubfn iter_mut(&mutself) -> IterMut<K, V> { self.into_iter()
}
/// Returns number of elements in enum map. #[inline] #[allow(clippy::unused_self)] pubconstfn len(&self) -> usize {
K::Array::LENGTH
}
/// Consumes an enum map and returns the underlying array. /// /// The order of elements is deterministic, and when using [macro@Enum] /// derive it will be the order in which enum variants are declared. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Enum, PartialEq)] /// enum E { /// A, /// B, /// C, /// } /// /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3}; /// assert_eq!(map.into_array(), [1, 2, 3]); /// ``` pubfn into_array(self) -> K::Array { self.array
}
/// Returns a reference to the underlying array. /// /// The order of elements is deterministic, and when using [macro@Enum] /// derive it will be the order in which enum variants are declared. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Enum, PartialEq)] /// enum E { /// A, /// B, /// C, /// } /// /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3}; /// assert_eq!(map.as_array(), &[1, 2, 3]); /// ``` pubconstfn as_array(&self) -> &K::Array {
&self.array
}
/// Returns a mutable reference to the underlying array. /// /// The order of elements is deterministic, and when using [macro@Enum] /// derive it will be the order in which enum variants are declared. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Enum, PartialEq)] /// enum E { /// A, /// B, /// C, /// } /// /// let mut map = enum_map! { E::A => 1, E::B => 2, E::C => 3}; /// map.as_mut_array()[1] = 42; /// assert_eq!(map.as_array(), &[1, 42, 3]); /// ``` pubfn as_mut_array(&mutself) -> &mut K::Array {
&mutself.array
}
/// Converts an enum map to a slice representing values. /// /// The order of elements is deterministic, and when using [macro@Enum] /// derive it will be the order in which enum variants are declared. /// /// # Examples /// /// ``` /// use enum_map::{enum_map, Enum}; /// /// #[derive(Enum, PartialEq)] /// enum E { /// A, /// B, /// C, /// } /// /// let map = enum_map! { E::A => 1, E::B => 2, E::C => 3}; /// assert_eq!(map.as_slice(), &[1, 2, 3]); /// ``` #[inline] pubfn as_slice(&self) -> &[V] { unsafe { slice::from_raw_parts(ptr::addr_of!(self.array).cast(), K::Array::LENGTH) }
}
/// Converts a mutable enum map to a mutable slice representing values. #[inline] pubfn as_mut_slice(&mutself) -> &mut [V] { unsafe { slice::from_raw_parts_mut(ptr::addr_of_mut!(self.array).cast(), K::Array::LENGTH) }
}
/// Returns an enum map with function `f` applied to each element in order. /// /// # Examples /// /// ``` /// use enum_map::enum_map; /// /// let a = enum_map! { false => 0, true => 1 }; /// let b = a.map(|_, x| f64::from(x) + 0.5); /// assert_eq!(b, enum_map! { false => 0.5, true => 1.5 }); /// ``` pubfn map<F, T>(self, mut f: F) -> EnumMap<K, T> where
F: FnMut(K, V) -> T,
K: EnumArray<T>,
{ struct DropOnPanic<K, V> where
K: EnumArray<V>,
{
position: usize,
map: ManuallyDrop<EnumMap<K, V>>,
} impl<K, V> Drop for DropOnPanic<K, V> where
K: EnumArray<V>,
{ fn drop(&mutself) { unsafe {
ptr::drop_in_place(&mutself.map.as_mut_slice()[self.position..]);
}
}
} letmut drop_protect = DropOnPanic {
position: 0,
map: ManuallyDrop::new(self),
};
enum_map! {
k => { let value = unsafe { ptr::read(&drop_protect.map.as_slice()[drop_protect.position]) };
drop_protect.position += 1;
f(k, value)
}
}
}
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.13 Sekunden
(vorverarbeitet am 2026-06-18)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.