Skip to main content

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}