enum_collections/enummap.rs
1use crate::Enumerated;
2use std::{
3 array,
4 fmt::Debug,
5 marker::PhantomData,
6 ops::{Index, IndexMut},
7};
8
9/// Creates an EnumMap with user-provided values.
10/// ```
11/// use enum_collections::{em, Enumerated, EnumMap};
12/// #[derive(Enumerated)]
13/// enum Letter {
14/// A,
15/// B,
16/// }
17///
18/// let enum_map = em!(Letter, i32, A => 42, B => 24);
19/// assert_eq!(42, enum_map[Letter::A]);
20/// assert_eq!(24, enum_map[Letter::B]);
21/// ```
22///
23#[macro_export]
24macro_rules! em {
25
26 ($ktp:ty, $vtp:ty, $($x:ident=>$y:expr),* ) => {
27 enum_collections::EnumMap::<$ktp, $vtp, {<$ktp>::SIZE}>::new_inspect(|letter| {
28 match letter {
29 $(<$ktp>::$x => $y,)*
30 }
31 })
32 };
33
34}
35
36/// Initializes an EnumMap with default values for all variants not explicitly specified.
37/// ```
38/// use enum_collections::{em_default, Enumerated, EnumMap};
39/// #[derive(Enumerated)]
40/// enum Letter {
41/// A,
42/// B,
43/// }
44///
45/// // One non-default value
46/// let enum_map = em_default!(Letter, i32, A => 42);
47/// assert_eq!(42, enum_map[Letter::A]);
48/// assert_eq!(i32::default(), enum_map[Letter::B]);
49///
50/// // All default
51///
52/// let enum_map = em_default!(Letter, i32,);
53/// assert_eq!(i32::default(), enum_map[Letter::A]);
54/// assert_eq!(i32::default(), enum_map[Letter::B]);
55/// ```
56///
57#[macro_export]
58macro_rules! em_default {
59 ($ktp:ty, $vtp:ty, $($x:ident=>$y:expr),* ) => {
60 EnumMap::<$ktp, $vtp, {<$ktp>::SIZE}>::new_inspect(|letter| {
61 match letter {
62 $(<$ktp>::$x => $y,)*
63 _ => Default::default(),
64 }
65 })
66 };
67}
68
69/// Initializes an EnumMap with `Option::None` for all variants not explicitly specified.
70///
71/// ```
72/// use enum_collections::{em_option, Enumerated, EnumMap};
73/// #[derive(Enumerated)]
74/// enum Letter {
75/// A,
76/// B,
77/// }
78///
79/// let enum_map = em_option!(Letter, i32, A => 42);
80/// assert_eq!(Some(42), enum_map[Letter::A]);
81/// assert_eq!(None, enum_map[Letter::B]);
82/// ```
83#[macro_export]
84macro_rules! em_option {
85 ($ktp:ty, $vtp:ty, $($x:ident=>$y:expr),* ) => {
86 EnumMap::<$ktp, Option<$vtp>, {<$ktp>::SIZE}>::new_inspect(|letter| {
87 match letter {
88 $(<$ktp>::$x => Some($y),)*
89 _ => None,
90 }
91 })
92 };
93}
94
95#[cfg(test)]
96mod macro_test {
97 use crate::{EnumMap, Enumerated};
98
99 #[derive(Enumerated)]
100 enum Letter {
101 A,
102 B,
103 }
104
105 #[test]
106 fn test_macro() {
107 let enum_map = em_default!(Letter, i32, A=>42);
108 assert_eq!(42, enum_map[Letter::A]);
109 assert_eq!(i32::default(), enum_map[Letter::B]);
110 }
111}
112
113/// A map of enum variants to values. EnumMap is a fixed-size map, where each variant of the enum
114/// is mapped to a value. EnumMap is a a zero-cost abstraction over an array, where the index of the array
115/// corresponds to the position of the variant in the enum.
116///
117/// Because it is a thin wrapper of an array, it is stack-allocated by default. Simply [std::boxed::Box]ing it
118/// will move it to the heap, at the caller's discretion.
119///
120/// - Indexed by enum variants.
121/// - IndexMut by enum variants.
122/// - Debug if the enum is Debug.
123/// - PartialEq if the value is PartialEq. Same for Eq.
124///
125/// Debug and Eq are optional features. They are enabled by default.
126///
127/// # Examples
128///
129/// ```
130/// use enum_collections::{EnumMap, Enumerated, em_default, em};
131///
132/// #[derive(Enumerated)]
133/// pub enum Letter {
134/// A,
135/// B,
136/// }
137///
138///
139/// // Indexing and mutation
140/// let mut enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_default();
141/// assert_eq!(0, enum_map[Letter::A]);
142/// enum_map[Letter::A] = 42;
143/// assert_eq!(42, enum_map[Letter::A]);
144///
145/// // Construction using macros
146/// // (Key type, Value type, Key=>Value pairs)
147/// let enum_map = em!(Letter, i32, A=>42, B=>24); // All values set explicitly
148/// assert_eq!(42, enum_map[Letter::A]);
149/// assert_eq!(24, enum_map[Letter::B]);
150///
151/// // (Key type, Value type, optional Key=>Value pairs)
152/// let enum_map = em_default!(Letter, i32, A => 42); // Default used for missing values
153/// assert_eq!(42, enum_map[Letter::A]);
154/// assert_eq!(i32::default(), enum_map[Letter::B]);
155///
156/// let enum_map = em_default!(Letter, i32,); // All default
157/// assert_eq!(i32::default(), enum_map[Letter::A]);
158/// assert_eq!(i32::default(), enum_map[Letter::B]);
159///
160///
161/// // Constructor with default values
162/// let enum_map_default = EnumMap::<Letter, i32, { Letter::SIZE }>::new_default();
163/// assert_eq!(0, enum_map_default[Letter::A]);
164/// assert_eq!(0, enum_map_default[Letter::B]);
165///
166/// // Convenience constructor for optional values
167/// let mut enum_map_option = EnumMap::<Letter, Option<i32>, { Letter::SIZE }>::new_option();
168/// assert_eq!(None, enum_map_option[Letter::A]);
169/// assert_eq!(None, enum_map_option[Letter::B]);
170/// enum_map_option[Letter::A] = Some(42);
171/// assert_eq!(Some(42), enum_map_option[Letter::A]);
172///
173/// // Constructor with custom initialization
174/// #[derive(PartialEq, Eq, Debug)]
175/// struct Custom;
176/// let enum_map = EnumMap::<Letter, Custom, { Letter::SIZE }>::new(|| Custom);
177/// assert_eq!(Custom, enum_map[Letter::A]);
178/// assert_eq!(Custom, enum_map[Letter::B]);
179///
180/// // Custom initialization function with enum variant (key) inspection
181/// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_inspect(|letter| {
182/// match letter {
183/// Letter::A => 42,
184/// Letter::B => 24,
185/// }
186/// });
187/// assert_eq!(42, enum_map[Letter::A]);
188/// assert_eq!(24, enum_map[Letter::B]);
189///
190/// // Debug
191/// #[derive(Enumerated, Debug)]
192/// pub enum LetterDebugDerived {
193/// A,
194/// B,
195/// }
196/// let enum_map_debug =
197/// EnumMap::<LetterDebugDerived, i32, { LetterDebugDerived::SIZE }>::new(|| 42);
198/// assert_eq!("{A: 42, B: 42}", format!("{:?}", enum_map_debug));
199///
200/// ```
201pub struct EnumMap<K: Enumerated, V, const N: usize> {
202 pub(crate) data: [V; N],
203 pub(crate) _key: PhantomData<K>,
204}
205
206impl<K: Enumerated, V: Default, const N: usize> EnumMap<K, V, N> {
207 /// Creates a new EnumMap with type's default values for each variant.
208 ///
209 /// ```
210 /// use enum_collections::{EnumMap, Enumerated};
211 /// #[derive(Enumerated)]
212 /// pub enum Letter {
213 /// A,
214 /// B,
215 /// }
216 ///
217 /// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_default();
218 /// assert_eq!(0, enum_map[Letter::A]);
219 /// assert_eq!(0, enum_map[Letter::B]);
220 /// ```
221 pub fn new_default() -> Self {
222 Self {
223 data: array::from_fn(|_| V::default()),
224 _key: PhantomData,
225 }
226 }
227 /// Sets all values to `V::default()`.
228 ///
229 /// ```
230 /// use enum_collections::{EnumMap, Enumerated};
231 /// #[derive(Enumerated)]
232 /// pub enum Letter {
233 /// A,
234 /// B,
235 /// }
236 /// let mut enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
237 /// enum_map.iter().for_each(|value| assert_eq!(42, *value));
238 /// enum_map.clear_set_default();
239 /// enum_map.iter().for_each(|value| assert_eq!(0, *value));
240 /// ```
241 ///
242 pub fn clear_set_default(&mut self) {
243 for idx in 0..self.data.len() {
244 self.data[idx] = V::default();
245 }
246 }
247}
248
249impl<K: Enumerated, V, const N: usize> EnumMap<K, Option<V>, N> {
250 /// Creates a new EnumMap with `Option::None` set for each variant.
251 /// Convenience constructor over `EnumMap::new` for optional values.
252 ///
253 /// ```
254 /// use enum_collections::{EnumMap, Enumerated};
255 /// #[derive(Enumerated)]
256 /// pub enum Letter {
257 /// A,
258 /// B,
259 /// }
260 ///
261 /// let enum_map = EnumMap::<Letter, Option<i32>, { Letter::SIZE }>::new_option();
262 /// assert_eq!(None, enum_map[Letter::A]);
263 /// assert_eq!(None, enum_map[Letter::B]);
264 /// ```
265 pub fn new_option() -> Self {
266 Self {
267 data: array::from_fn(|_| None),
268 _key: PhantomData,
269 }
270 }
271
272 /// Clears the EnumMap and sets all values to `None`.
273 ///
274 /// This function iterates over each variant of the EnumMap and sets its value to `None`.
275 ///
276 /// # Examples
277 ///
278 /// ```
279 /// use enum_collections::{EnumMap, Enumerated};
280 /// #[derive(Enumerated)]
281 /// pub enum Letter {
282 /// A,
283 /// B,
284 /// }
285 ///
286 /// let mut enum_map = EnumMap::<Letter, Option<i32>, { Letter::SIZE }>::new_option();
287 /// enum_map[Letter::A] = Some(10);
288 /// enum_map[Letter::B] = Some(20);
289 ///
290 /// enum_map.clear_set_none();
291 /// enum_map.iter().for_each(|value| assert_eq!(None, *value));
292 ///
293 /// ```
294 pub fn clear_set_none(&mut self) {
295 for idx in 0..self.data.len() {
296 self.data[idx] = None;
297 }
298 }
299}
300
301impl<K: Enumerated, V, const N: usize> EnumMap<K, V, N> {
302 /// Creates a new EnumMap where value of each variant is produced by the provided function
303 ///
304 /// ```
305 /// use enum_collections::{EnumMap, Enumerated};
306 /// #[derive(Enumerated)]
307 /// pub enum Letter {
308 /// A,
309 /// B,
310 /// }
311 ///
312 /// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
313 /// assert_eq!(42, enum_map[Letter::A]);
314 /// assert_eq!(42, enum_map[Letter::B]);
315 ///
316 /// ```
317 pub fn new(default: fn() -> V) -> Self {
318 Self {
319 data: array::from_fn(|_| default()),
320 _key: PhantomData,
321 }
322 }
323
324 /// Iterates over each variant of the EnumMap and sets its value to the value provided by the `val_provider` function.
325 ///
326 /// Unlike [Self::new], this function does not allocate a new EnumMap.
327 ///
328 /// # Examples
329 ///
330 /// ```
331 /// use enum_collections::{EnumMap, Enumerated};
332 /// #[derive(Enumerated)]
333 /// pub enum Letter {
334 /// A,
335 /// B,
336 /// }
337 ///
338 /// let mut enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
339 /// enum_map.set_all(|| 24);
340 /// enum_map.iter().for_each(|value| assert_eq!(24, *value));
341 /// ```
342 pub fn set_all(&mut self, val_provider: fn() -> V) {
343 for idx in 0..self.data.len() {
344 self.data[idx] = val_provider();
345 }
346 }
347
348 /// Iterates over the EnumMap's key-value pairs.
349 ///
350 /// ```
351 /// use enum_collections::{EnumMap, Enumerated};
352 /// #[derive(Enumerated, Debug)]
353 /// pub enum Letter {
354 /// A,
355 /// B,
356 /// }
357 ///
358 /// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
359 /// for (_letter, value) in enum_map.iter_kv() {
360 /// assert_eq!(42, *value);
361 /// }
362 ///
363 /// ```
364 #[cfg(feature = "variants")]
365 pub fn iter_kv(&self) -> std::iter::Zip<std::slice::Iter<'_, K>, std::slice::Iter<'_, V>> {
366 K::VARIANTS.iter().zip(self.data.iter())
367 }
368
369 /// Mutably iterates over the EnumMap's key-value pairs. Only the values are mutable.
370 ///
371 /// ```
372 /// use std::ops::AddAssign;
373 /// use enum_collections::{EnumMap, Enumerated};
374 /// #[derive(Enumerated, Debug)]
375 /// pub enum Letter {
376 /// A,
377 /// B,
378 /// }
379 ///
380 /// let mut enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
381 /// for (_letter, value) in enum_map.iter_kv_mut() {
382 /// value.add_assign(10);
383 /// assert_eq!(52, *value);
384 /// }
385 ///
386 /// ```
387 #[cfg(feature = "variants")]
388 pub fn iter_kv_mut(
389 &mut self,
390 ) -> std::iter::Zip<std::slice::Iter<'_, K>, std::slice::IterMut<'_, V>> {
391 K::VARIANTS.iter().zip(self.data.iter_mut())
392 }
393
394 /// Iterates over the EnumMap's values.
395 ///
396 /// ```
397 /// use enum_collections::{EnumMap, Enumerated};
398 /// #[derive(Enumerated, Debug)]
399 /// pub enum Letter {
400 /// A,
401 /// B,
402 /// }
403 ///
404 /// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
405 /// for value in enum_map.iter() {
406 /// assert_eq!(42, *value);
407 /// }
408 ///
409 /// ```
410 #[cfg(feature = "variants")]
411 pub fn iter(&self) -> std::slice::Iter<'_, V> {
412 self.data.iter()
413 }
414
415 /// Mutably iterates over the EnumMap's values.
416 ///
417 /// ```
418 /// use std::ops::AddAssign;
419 /// use enum_collections::{EnumMap, Enumerated};
420 /// #[derive(Enumerated, Debug)]
421 /// pub enum Letter {
422 /// A,
423 /// B,
424 /// }
425 ///
426 /// let mut enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
427 /// for value in enum_map.iter_mut() {
428 /// value.add_assign(10);
429 /// assert_eq!(52, *value);
430 /// }
431 ///
432 /// ```
433 #[cfg(feature = "variants")]
434 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, V> {
435 self.data.iter_mut()
436 }
437
438 /// Creates a new EnumMap where value of each variant is produced by the provided function.
439 /// The function receives the enum variant being initialized for inspection.
440 ///
441 /// ```
442 /// use enum_collections::{EnumMap, Enumerated};
443 /// #[derive(Enumerated)]
444 /// pub enum Letter {
445 /// A,
446 /// B,
447 /// }
448 ///
449 /// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_inspect(|letter| {
450 /// match letter {
451 /// Letter::A => 42,
452 /// Letter::B => 24,
453 /// }
454 /// });
455 /// assert_eq!(42, enum_map[Letter::A]);
456 /// assert_eq!(24, enum_map[Letter::B]);
457 ///
458 /// ```
459 #[cfg(feature = "variants")]
460 pub fn new_inspect(mut default: impl FnMut(&K) -> V) -> Self {
461 let init_fn = |index| {
462 // Finds the enum variant by its index, as the array is sorted by discriminants in ascending order.
463 default(&K::VARIANTS[index])
464 };
465 Self {
466 data: array::from_fn(init_fn),
467 _key: PhantomData,
468 }
469 }
470}
471
472impl<K: Enumerated, V: Copy, const N: usize> EnumMap<K, V, N> {
473 /// Creates a new EnumMap where value of each variant is the provided value.
474 ///
475 /// ```
476 /// use enum_collections::{EnumMap, Enumerated};
477 /// #[derive(Enumerated)]
478 /// pub enum Letter {
479 /// A,
480 /// B,
481 /// }
482 ///
483 /// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_with_all(42);
484 /// assert_eq!(42, enum_map[Letter::A]);
485 /// assert_eq!(42, enum_map[Letter::B]);
486 ///
487 /// ```
488 pub const fn new_with_all(value: V) -> Self {
489 Self {
490 data: [value; N],
491 _key: PhantomData,
492 }
493 }
494}
495
496/// Allows indexing of EnumMap.
497///
498/// ```
499/// use enum_collections::{EnumMap, Enumerated};
500///
501/// #[derive(Enumerated)]
502/// pub enum LetterEqDerived {
503/// A,
504/// B,
505/// }
506///
507/// let enum_map = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new(|| 42);
508/// assert_eq!(42, enum_map[LetterEqDerived::A]);
509/// assert_eq!(42, enum_map[LetterEqDerived::B]);
510/// ```
511impl<K: Enumerated, V, const N: usize> Index<K> for EnumMap<K, V, N> {
512 type Output = V;
513
514 fn index(&self, key: K) -> &Self::Output {
515 &self.data[key.position()]
516 }
517}
518
519/// Allows mutable indexing of EnumMap.
520///
521///
522/// ```
523/// use enum_collections::{EnumMap, Enumerated};
524///
525/// #[derive(Enumerated)]
526/// pub enum LetterEqDerived {
527/// A,
528/// B,
529/// }
530///
531/// let mut enum_map = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new_default();
532/// assert_eq!(0, enum_map[LetterEqDerived::A]);
533/// enum_map[LetterEqDerived::A] = 42;
534/// assert_eq!(42, enum_map[LetterEqDerived::A]);
535///
536/// ```
537impl<K: Enumerated, V, const N: usize> IndexMut<K> for EnumMap<K, V, N> {
538 fn index_mut(&mut self, key: K) -> &mut Self::Output {
539 &mut self.data[key.position()]
540 }
541}
542
543/// Implements Debug for EnumMap. EnumMap is printed as a map of enum variants to their values.
544///
545/// ```
546///
547/// use enum_collections::{EnumMap, Enumerated};
548/// #[derive(Enumerated, Debug)]
549/// enum Letter {
550/// A,
551/// B,
552/// }
553///
554/// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
555/// assert_eq!("{A: 42, B: 42}", format!("{:?}", enum_map));
556/// ```
557///
558#[cfg(feature = "debug")]
559impl<K: Enumerated + Debug, V: Debug, const N: usize> std::fmt::Debug for EnumMap<K, V, N> {
560 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
561 f.debug_map()
562 .entries(
563 K::VARIANTS
564 .iter()
565 .enumerate()
566 .map(|(index, variant)| (variant, &self.data[index])),
567 )
568 .finish()
569 }
570}
571
572#[cfg(feature = "eq")]
573mod eq {
574 use super::{EnumMap, Enumerated};
575
576 /// Implements PartialEq for EnumMap. Two enum maps are PartialEq if for each enum variant, the value is the same.
577 ///
578 /// ```
579 /// use enum_collections::{EnumMap, Enumerated};
580 ///
581 /// #[derive(Enumerated, Eq, PartialEq)]
582 /// pub enum LetterEqDerived {
583 /// A,
584 /// B,
585 /// }
586 /// let enum_map = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new(|| 42);
587 /// let same_map = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new(|| 42);
588 /// assert!(enum_map == same_map);
589 ///
590 /// let different_map = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new_default();
591 /// assert!(enum_map != different_map);
592 /// ```
593 impl<K: Enumerated, V: PartialEq, const N: usize> PartialEq for EnumMap<K, V, N> {
594 fn eq(&self, other: &Self) -> bool {
595 self.data == other.data
596 }
597 }
598
599 /// Marks EnumMap as Eq. Two enum maps are Eq if for each enum variant, the value is the same.
600 ///
601 /// ```
602 /// use enum_collections::{EnumMap, Enumerated};
603 ///
604 /// #[derive(Enumerated, Eq, PartialEq)]
605 /// pub enum LetterEqDerived {
606 /// A,
607 /// B,
608 /// }
609 /// let first = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new(|| 42);
610 /// let second = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new(|| 42);
611 /// let third = EnumMap::<LetterEqDerived, i32, { LetterEqDerived::SIZE }>::new(|| 42);
612 /// // Reflexive
613 /// assert!(first == first);
614 /// // Symmetric
615 /// assert!(first == second);
616 /// assert!(second == first);
617 /// // Transitive
618 /// assert!(second == third);
619 /// assert!(first == third);
620 /// ```
621 impl<K: Enumerated, V: Eq, const N: usize> Eq for EnumMap<K, V, N> {}
622}
623
624/// Implements Clone for EnumMap. Clones the EnumMap by cloning each value. Requires the value to be `Clone`.
625///
626/// ```
627/// use enum_collections::{EnumMap, Enumerated};
628///
629/// #[derive(Enumerated, Debug)]
630/// pub enum Letter {
631/// A,
632/// B,
633/// }
634/// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
635/// let cloned = enum_map.clone();
636/// assert_eq!(enum_map, cloned);
637/// ```
638impl<K: Enumerated, V: Clone, const N: usize> Clone for EnumMap<K, V, N> {
639 fn clone(&self) -> Self {
640 Self {
641 data: self.data.clone(),
642 _key: PhantomData,
643 }
644 }
645}
646
647/// Implements Copy for EnumMap, provided the value type `V` also implements `Copy`.
648///
649/// ```
650///
651/// use enum_collections::{EnumMap, Enumerated};
652/// #[derive(Enumerated, Debug)]
653/// pub enum Letter {
654/// A,
655/// B,
656/// }
657/// let enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new(|| 42);
658/// let copied = enum_map;
659/// assert_eq!(enum_map, copied);
660/// ```
661impl<K: Enumerated, V: Copy, const N: usize> Copy for EnumMap<K, V, N> {}
662
663#[cfg(test)]
664mod tests {
665 use crate::Enumerated;
666 use crate::enummap::EnumMap;
667 /// No Debug derived on purpose, the crate must be usable without [std::fmt::Debug] derived
668 /// for the enum.
669 #[derive(Enumerated, Debug)]
670 pub(super) enum Letter {
671 A,
672 B,
673 }
674
675 #[test]
676 fn index() {
677 let mut enum_map = EnumMap::<Letter, i32, { Letter::SIZE }>::new_default();
678 assert_eq!(0, enum_map[Letter::A]);
679 enum_map[Letter::A] = 42;
680 assert_eq!(42, enum_map[Letter::A]);
681 assert_eq!(i32::default(), enum_map[Letter::B]);
682 }
683
684 #[test]
685 fn constructor_option() {
686 let mut enum_map = EnumMap::<Letter, Option<i32>, { Letter::SIZE }>::new_option();
687 assert_eq!(None, enum_map[Letter::A]);
688 assert_eq!(None, enum_map[Letter::B]);
689
690 enum_map[Letter::A] = Some(42);
691 assert_eq!(Some(42), enum_map[Letter::A]);
692 }
693
694 #[test]
695 fn non_default_type() {
696 #[derive(PartialEq, Eq, Debug)]
697 struct NonDefault;
698 let enum_map = EnumMap::<Letter, NonDefault, { Letter::SIZE }>::new(|| NonDefault);
699 assert_eq!(NonDefault, enum_map[Letter::A]);
700 assert_eq!(NonDefault, enum_map[Letter::B]);
701 }
702
703 /// Safeguard test. Nothing inside the EnumMap should prevent from moving it to the heap.
704 #[test]
705 fn heap_allocation() {
706 let boxed_map = Box::new(EnumMap::<Letter, i32, { Letter::SIZE }>::new_default());
707 assert!(EnumMap::<Letter, i32, { Letter::SIZE }>::new_default() == *boxed_map);
708 }
709
710 #[cfg(feature = "variants")]
711 mod variants {
712 use super::*;
713
714 #[test]
715 fn variants() {
716 assert_eq!(2, Letter::VARIANTS.len());
717 Letter::VARIANTS
718 .iter()
719 .for_each(|letter| println!("{:?}", letter));
720 }
721 }
722
723 #[cfg(feature = "debug")]
724 mod debug {
725 use crate::{EnumMap, Enumerated};
726
727 /// A dedicated enum with [std::fmt::Debug] derived, to test compilation and usability both
728 /// with and without `Debug` implemented.
729 #[derive(Enumerated, Debug)]
730 pub(super) enum LetterDebugDerived {
731 A,
732 B,
733 }
734
735 #[test]
736 fn debug() {
737 let enum_map =
738 EnumMap::<LetterDebugDerived, i32, { LetterDebugDerived::SIZE }>::new(|| 42);
739 assert_eq!("{A: 42, B: 42}", format!("{:?}", enum_map));
740 }
741 }
742
743 #[cfg(feature = "serde")]
744 mod serde {
745 use serde::{Deserialize, Serialize};
746
747 use crate::{EnumMap, Enumerated};
748
749 #[derive(Enumerated, Serialize, Deserialize, PartialEq, Debug)]
750 pub(super) enum LetterSerde {
751 A,
752 B,
753 }
754
755 #[test]
756 fn serialize() {
757 let mut enum_map: EnumMap<_, Option<_>, { LetterSerde::SIZE }> = EnumMap::new_option();
758 enum_map[LetterSerde::A] = Some(10);
759 enum_map[LetterSerde::B] = Some(11);
760
761 let serialized = ron::to_string(&enum_map).unwrap();
762 assert_eq!("{A:Some(10),B:Some(11)}", serialized);
763 }
764
765 #[test]
766 fn deserialize() {
767 let str = "{A:Some(10),B:Some(11)}";
768 let enum_map: EnumMap<_, Option<_>, { LetterSerde::SIZE }> =
769 ron::from_str(str).unwrap();
770
771 let mut correct_enum_map: EnumMap<_, Option<_>, { LetterSerde::SIZE }> =
772 EnumMap::new_option();
773 correct_enum_map[LetterSerde::A] = Some(10);
774 correct_enum_map[LetterSerde::B] = Some(11);
775 assert_eq!(enum_map, correct_enum_map);
776 }
777
778 #[test]
779 fn serde() {
780 let mut enum_map: EnumMap<_, Option<_>, { LetterSerde::SIZE }> = EnumMap::new_option();
781 enum_map[LetterSerde::A] = Some(10);
782
783 let serialized = ron::to_string(&enum_map).unwrap();
784 let new_enum_map: EnumMap<_, Option<_>, { LetterSerde::SIZE }> =
785 ron::from_str(&serialized).unwrap();
786 assert_eq!(enum_map, new_enum_map);
787 }
788 }
789}