my_ecs/ds/
map.rs

1use crate::ds::vec::OptVec;
2use std::{
3    collections::{hash_map::Entry, HashMap, HashSet},
4    hash::{BuildHasher, Hash},
5};
6
7/// A hash map containing *Group*s and *Item*s.
8///
9/// Conceptually, group contains items in it, and item can belong to multiple
10/// groups. They cannot exist without relationship to each other. In other
11/// words, they must be linked. See a diagram below. In this map, group has an
12/// ordered links to items, while item has an unordered links to groups.
13///
14/// ```text
15/// Groups    G0  G1
16///           /\  /\
17/// Items   I0  I1  I2
18/// ```
19///
20/// The map provides you some ways to access groups and items by their keys and
21/// indices. If possible, prefer to use index to key because it can be faster.
22#[derive(Debug, Clone)]
23pub struct GroupMap<GK, GV, IK, IV, S> {
24    /// Groups that can be accessed by either key or index.
25    ///
26    /// Key: Group key `GK`.
27    /// Value: Group value `GV` and indices to `items`.
28    groups: IndexedMap<GK, (GV, Vec<usize>), S>,
29
30    /// Items that can be accessed by either key or index.
31    ///
32    /// Key: Item key `IK`.
33    /// Value: Item value `IV` and indices to `groups`.
34    items: IndexedMap<IK, (IV, HashSet<usize, S>), S>,
35}
36
37impl<GK, GV, IK, IV, S> GroupMap<GK, GV, IK, IV, S>
38where
39    S: Default,
40{
41    /// Creates a new empty map.
42    pub fn new() -> Self {
43        Self {
44            groups: IndexedMap::new(),
45            items: IndexedMap::new(),
46        }
47    }
48}
49
50impl<GK, GV, IK, IV, S> GroupMap<GK, GV, IK, IV, S>
51where
52    GK: Hash + Eq + Clone,
53    IK: Hash + Eq + Clone,
54    S: BuildHasher,
55{
56    /// Returns true if the map contains a group at the given group index.
57    ///
58    /// Consider using [`GroupMap::contains_group2`] if you need to know whether
59    /// the map contains it or not by a key.
60    pub fn contains_group(&self, index: usize) -> bool {
61        self.groups.contains_index(index)
62    }
63
64    /// Returns true if the map contains a group corresponding to the given
65    /// group key.
66    ///
67    /// Consider using [`GroupMap::contains_group`] if you need to know whether
68    /// the map contains it or not by an index.
69    pub fn contains_group2<Q>(&self, key: &Q) -> bool
70    where
71        GK: std::borrow::Borrow<Q>,
72        Q: Hash + Eq + ?Sized,
73    {
74        self.groups.contains_key(key)
75    }
76
77    /// Retrieves a shared reference to a group and related item indices by the
78    /// given group index.
79    ///
80    /// Consider using [`GroupMap::get_group2`] if you need to get a group by
81    /// a key.
82    pub fn get_group(&self, index: usize) -> Option<(&GV, &Vec<usize>)> {
83        self.groups.get(index).map(|(value, links)| (value, links))
84    }
85
86    /// Retrieves a shared reference to a group and related item indices by the
87    /// given group key.
88    ///
89    /// Consider using [`GroupMap::get_group`] if you need to get a group by
90    /// an index.
91    pub fn get_group2<Q>(&self, key: &Q) -> Option<(&GV, &Vec<usize>)>
92    where
93        GK: std::borrow::Borrow<Q>,
94        Q: Hash + Eq + ?Sized,
95    {
96        self.groups.get2(key).map(|(value, links)| (value, links))
97    }
98
99    /// Retrieves a mutable reference to a group and related item indices by the
100    /// given group index.
101    ///
102    /// Consider using [`GroupMap::get_group_mut2`] if you need to get a group
103    /// by a key.
104    pub fn get_group_mut(&mut self, index: usize) -> Option<(&mut GV, &Vec<usize>)> {
105        self.groups
106            .get_mut(index)
107            .map(|(value, links)| (value, &*links))
108    }
109
110    /// Retrieves a mutable reference to a group and related item indices by the
111    /// given group key.
112    ///
113    /// Consider using [`GroupMap::get_group_mut`] if you need to get a group
114    /// by an index.
115    pub fn get_group_mut2<Q>(&mut self, key: &Q) -> Option<(&mut GV, &Vec<usize>)>
116    where
117        GK: std::borrow::Borrow<Q>,
118        Q: Hash + Eq + ?Sized,
119    {
120        self.groups
121            .get_mut2(key)
122            .map(|(value, links)| (value, &*links))
123    }
124
125    /// Retrieves group key corresponding to the given group index.
126    ///
127    /// You can also get a group index from a key using
128    /// [`GroupMap::get_group_index`].
129    pub fn get_group_key(&self, index: usize) -> Option<&GK> {
130        self.groups.get_key(index)
131    }
132
133    /// Retrieves a group index corresponding to the given group key.
134    ///
135    /// You can also get a group key from an index using
136    /// [`GroupMap::get_group_key`].
137    pub fn get_group_index<Q>(&self, key: &Q) -> Option<usize>
138    where
139        GK: std::borrow::Borrow<Q>,
140        Q: Hash + Eq + ?Sized,
141    {
142        self.groups.get_index(key)
143    }
144
145    /// Returns an iterator visiting all groups.
146    ///
147    /// The iterator yields pairs of group key, group index, and shared
148    /// reference to group value.
149    pub fn iter_group(&self) -> impl Iterator<Item = (&GK, usize, &GV)> {
150        self.groups
151            .iter()
152            .map(|(key, index, (value, _))| (key, index, value))
153    }
154
155    /// Returns true if the map contains an item at the given item index.
156    ///
157    /// Consider using [`GroupMap::contains_item2`] if you need to know whether
158    /// the map contains it or not by a key.
159    pub fn contains_item(&self, index: usize) -> bool {
160        self.items.contains_index(index)
161    }
162
163    /// Returns true if the map contains an item corresponding to the given item
164    /// key.
165    ///
166    /// Consider using [`GroupMap::contains_item`] if you need to know whether
167    /// the map contains it or not by an index.
168    pub fn contains_item2<Q>(&self, key: &Q) -> bool
169    where
170        IK: std::borrow::Borrow<Q>,
171        Q: Hash + Eq + ?Sized,
172    {
173        self.items.contains_key(key)
174    }
175
176    /// Retrieves a shared reference to an item and related group indices by the
177    /// given item index.
178    ///
179    /// Consider using [`GroupMap::get_item2`] if you need to get an item by a
180    /// key.
181    pub fn get_item(&self, index: usize) -> Option<&(IV, HashSet<usize, S>)> {
182        self.items.get(index)
183    }
184
185    /// Retrieves a shared reference to an item and related group indices by the
186    /// given item key.
187    ///
188    /// Consider using [`GroupMap::get_item`] if you need to get an item by an
189    /// index.
190    pub fn get_item2<Q>(&self, key: &Q) -> Option<&(IV, HashSet<usize, S>)>
191    where
192        IK: std::borrow::Borrow<Q>,
193        Q: Hash + Eq + ?Sized,
194    {
195        self.items.get2(key)
196    }
197
198    /// Retrieves a mutable reference to an item and related group indices by
199    /// the given item index.
200    ///
201    /// Consider using [`GroupMap::get_item_mut2`] if you need to get an item by
202    /// a key.
203    pub fn get_item_mut(&mut self, index: usize) -> Option<(&mut IV, &HashSet<usize, S>)> {
204        self.items
205            .get_mut(index)
206            .map(|(value, links)| (value, &*links))
207    }
208
209    /// Retrieves a mutable reference to an item and related group indices by
210    /// the given item key.
211    ///
212    /// Consider using [`GroupMap::get_item_mut`] if you need to get an item by
213    /// an index.
214    pub fn get_item_mut2<Q>(&mut self, key: &Q) -> Option<(&mut IV, &HashSet<usize, S>)>
215    where
216        IK: std::borrow::Borrow<Q>,
217        Q: Hash + Eq + ?Sized,
218    {
219        self.items
220            .get_mut2(key)
221            .map(|(value, links)| (value, &*links))
222    }
223
224    /// Retrieves an item key corresponding to the given item index.
225    ///
226    /// You can also get an item index from a key using
227    /// [`GroupMap::get_item_index`].
228    pub fn get_item_key(&self, index: usize) -> Option<&IK> {
229        self.items.get_key(index)
230    }
231
232    /// Retrieves an item index corresponding to the given item key.
233    ///
234    /// You can also get an item key from an index using
235    /// [`GroupMap::get_item_key`].
236    pub fn get_item_index<Q>(&self, key: &Q) -> Option<usize>
237    where
238        IK: std::borrow::Borrow<Q>,
239        Q: Hash + Eq + ?Sized,
240    {
241        self.items.get_index(key)
242    }
243
244    /// Returns an iterator visiting all items.
245    ///
246    /// The iterator yields pairs of item key, item index, and shared
247    /// reference to item value.
248    pub fn iter_item(&self) -> impl Iterator<Item = (&IK, usize, &IV)> {
249        self.items
250            .iter()
251            .map(|(key, index, (value, _))| (key, index, value))
252    }
253}
254
255impl<GK, GV, IK, IV, S> GroupMap<GK, GV, IK, IV, S>
256where
257    GK: Hash + Eq + Clone,
258    IK: Hash + Eq + Clone,
259    S: BuildHasher + Default,
260{
261    /// Returns the next index that will be returned on the next call to
262    /// either [`GroupMap::add_group`] or [`GroupMap::add_group_from_desc`].
263    pub fn next_index<Q>(&self, key: &Q) -> usize
264    where
265        GK: std::borrow::Borrow<Q>,
266        Q: Hash + Eq + ?Sized,
267    {
268        self.groups.next_index(key)
269    }
270
271    /// Inserts a group and related items into the map from the given group
272    /// descriptor.
273    ///
274    /// This method is a simple wrapper of [`GroupMap::add_group_from_desc`] for
275    /// easy use.
276    pub fn add_group(
277        &mut self,
278        desc: impl DescribeGroup<GK, GV, IK, IV>,
279    ) -> Result<usize, GroupDesc<GK, GV, IK, IV>> {
280        self.add_group_from_desc(desc.into_group_and_items())
281    }
282
283    /// Inserts a group and related items into the map from the given group
284    /// descriptor.
285    ///
286    /// Note that this method doesn't overwrite anything. Therefore, if the map
287    /// already contains the same group key, returns error. With respect to
288    /// item, only relation to the group is adapted and item value is dropped
289    /// if the map already contains the item. If you want replace, remove old
290    /// one first.
291    ///
292    /// # Panics
293    ///
294    /// Panics if the descriptor doesn't contain any items in it. Group cannot
295    /// exist without relationship with items. See [`GroupMap`] documentation
296    /// for more details.
297    pub fn add_group_from_desc(
298        &mut self,
299        desc: GroupDesc<GK, GV, IK, IV>,
300    ) -> Result<usize, GroupDesc<GK, GV, IK, IV>> {
301        // Panics: Group must contain related items.
302        assert!(!desc.items.is_empty());
303
304        // Err: This method doesn't allow overwriting.
305        if self.contains_group2(&desc.group_key) {
306            return Err(desc);
307        }
308
309        let GroupDesc {
310            group_key,
311            group_value,
312            items,
313        } = desc;
314
315        // Adds each item if the map doesn't contain it.
316        let item_indices = items
317            .into_iter()
318            .map(|(key, item)| {
319                if let Some(index) = self.items.get_index(&key) {
320                    index
321                } else {
322                    self.items.insert(key, (item, HashSet::default())).0
323                }
324            })
325            .collect::<Vec<_>>();
326
327        // Adds group.
328        let (group_index, old_group) = self
329            .groups
330            .insert(group_key, (group_value, item_indices.clone()));
331        debug_assert!(old_group.is_none());
332
333        // Updates items by adding new link to the group.
334        for index in item_indices {
335            let (_, links) = self.items.get_mut(index).unwrap();
336            links.insert(group_index);
337        }
338
339        Ok(group_index)
340    }
341
342    /// Removes a group at the given group index from the map.
343    ///
344    /// Related items are automatically removed as well if they don't have
345    /// relationships anymore by the removal of the group.
346    ///
347    /// Consider using [`GroupMap::remove_group2`] if you need to remove a group
348    /// by a key.
349    pub fn remove_group(&mut self, index: usize) -> Option<(GK, GV)> {
350        // Removes group.
351        let group_index = index;
352        let (group_key, (old_group, item_indices)) = self.groups.remove_entry(group_index)?;
353
354        // Removes corresponding items if it's possible.
355        for item_index in item_indices.iter().cloned() {
356            let (_, group_indices) = self.items.get_mut(item_index).unwrap();
357            group_indices.remove(&group_index);
358            if group_indices.is_empty() {
359                self.items.remove(item_index);
360            }
361        }
362
363        Some((group_key, old_group))
364    }
365
366    /// Removes a group corresponding to the given group key from the map.
367    ///
368    /// Related items are automatically removed as well if they don't have
369    /// relationships anymore by the removal of the group.
370    ///
371    /// Consider using [`GroupMap::remove_group`] if you need to remove a group
372    /// by an index.
373    pub fn remove_group2<Q>(&mut self, key: &Q) -> Option<(GK, GV)>
374    where
375        GK: std::borrow::Borrow<Q>,
376        Q: Hash + Eq + ?Sized,
377    {
378        let index = self.groups.get_index(key)?;
379        self.remove_group(index)
380    }
381}
382
383impl<GK, GV, IK, IV, S> Default for GroupMap<GK, GV, IK, IV, S>
384where
385    S: Default,
386{
387    fn default() -> Self {
388        Self::new()
389    }
390}
391
392/// A trait for creating [`GroupDesc`].
393pub trait DescribeGroup<GK, GV, IK, IV> {
394    fn into_group_and_items(self) -> GroupDesc<GK, GV, IK, IV>;
395}
396
397/// A descriptor for [`GroupMap`].
398///
399/// `GroupMap` is a map containing groups and items. This descriptor describes
400/// a group with its key, value, and associated items.
401#[derive(Debug)]
402pub struct GroupDesc<GK, GV, IK, IV> {
403    pub group_key: GK,
404    pub group_value: GV,
405    pub items: Vec<(IK, IV)>,
406}
407
408/// A hash map that you can find a value by an index as well.
409///
410/// It's encouraged to prefer accessing item by an index over using a key
411/// because it is simpler in terms of required operations. Plus, values are laid
412/// on sequential memory block, so that we can expect faster iteration as well.
413/// However, the map allocates more memory than usual hash map.
414///
415/// If you want to use an index as key interchangeably, then set `IMAP` to true.
416/// Then, the map keeps `index->key` relation as well so that the map can find
417/// a corresponding key from an index.
418#[derive(Debug, Clone)]
419pub struct IndexedMap<K, V, S, const IMAP: bool = true> {
420    /// Key -> An index to an item of [`Self::values`].
421    map: HashMap<K, usize, S>,
422
423    /// Index to item of [`Self::values`] -> Key.
424    ///
425    /// This field is used only when `IMAP = true`.
426    imap: OptVec<K, S>,
427
428    /// Values.
429    values: OptVec<V, S>,
430}
431
432impl<K, V, S> IndexedMap<K, V, S, true>
433where
434    S: BuildHasher,
435{
436    /// Retrieves a shared reference to a key corresponding to the given index.
437    ///
438    /// # Examples
439    ///
440    /// ```
441    /// use my_ecs::ds::IndexedMap;
442    /// use std::hash::RandomState;
443    ///
444    /// let mut map = IndexedMap::<_, _, RandomState>::new();
445    /// let (index, _) = map.insert('a', "alpha");
446    /// assert_eq!(map.get_key(index), Some(&'a'));
447    /// ```
448    pub fn get_key(&self, index: usize) -> Option<&K> {
449        self.imap.get(index)
450    }
451}
452
453impl<K, V, S> IndexedMap<K, V, S, true>
454where
455    K: Hash + Eq + Clone,
456    S: BuildHasher,
457{
458    /// Removes a value at the given index then returns it.
459    ///
460    /// Consider using [`IndexedMap::remove2`] if you need to remove a value
461    /// by a key.
462    ///
463    /// # Examples
464    ///
465    /// ```
466    /// use my_ecs::ds::IndexedMap;
467    /// use std::hash::RandomState;
468    ///
469    /// let mut map = IndexedMap::<_, _, RandomState>::new();
470    /// let (index, _) = map.insert('a', "alpha");
471    /// assert_eq!(map.remove(index), Some("alpha"));
472    /// ```
473    pub fn remove(&mut self, index: usize) -> Option<V> {
474        self.remove_entry(index).map(|(_key, value)| value)
475    }
476
477    /// Removes a value at the given index then returns it with the
478    /// corresponding key.
479    ///
480    /// Consider using [`IndexedMap::remove_entry2`] if you need to remove a
481    /// value by a key.
482    ///
483    /// # Examples
484    ///
485    /// ```
486    /// use my_ecs::ds::IndexedMap;
487    /// use std::hash::RandomState;
488    ///
489    /// let mut map = IndexedMap::<_, _, RandomState>::new();
490    /// let (index, _) = map.insert('a', "alpha");
491    /// assert_eq!(map.remove_entry(index), Some(('a', "alpha")));
492    /// ```
493    pub fn remove_entry(&mut self, index: usize) -> Option<(K, V)> {
494        let key = self.imap.get(index)?;
495        let must_some = self.map.remove(key);
496        debug_assert!(must_some.is_some());
497        // Safety: The entry exists, checked by `?` above.
498        unsafe {
499            let key = self.imap.take(index).unwrap_unchecked();
500            let value = self.values.take(index).unwrap_unchecked();
501            Some((key, value))
502        }
503    }
504}
505
506impl<K, V, S, const IMAP: bool> IndexedMap<K, V, S, IMAP>
507where
508    S: Default,
509{
510    /// Creates a new empty map.
511    ///
512    /// # Examples
513    ///
514    /// ```
515    /// use my_ecs::ds::IndexedMap;
516    /// use std::hash::RandomState;
517    ///
518    /// let map = IndexedMap::<char, &'static str, RandomState>::new();
519    /// ```
520    pub fn new() -> Self {
521        Self {
522            map: HashMap::default(),
523            imap: OptVec::new(),
524            values: OptVec::new(),
525        }
526    }
527}
528
529impl<K, V, S, const IMAP: bool> IndexedMap<K, V, S, IMAP>
530where
531    K: Hash + Eq + Clone,
532    S: BuildHasher,
533{
534    /// Returns number of items.
535    ///
536    /// # Examples
537    ///
538    /// ```
539    /// use my_ecs::ds::IndexedMap;
540    /// use std::hash::RandomState;
541    ///
542    /// let mut map = IndexedMap::<_, _, RandomState>::new();
543    /// map.insert('a', "alpha");
544    /// assert_eq!(map.len(), 1);
545    /// ```
546    pub fn len(&self) -> usize {
547        self.values.len()
548    }
549
550    /// Returns true if the map is empty.
551    ///
552    /// # Examples
553    ///
554    /// ```
555    /// use my_ecs::ds::IndexedMap;
556    /// use std::hash::RandomState;
557    ///
558    /// let map = IndexedMap::<char, &'static str, RandomState>::new();
559    /// assert!(map.is_empty());
560    /// ```
561    pub fn is_empty(&self) -> bool {
562        self.len() == 0
563    }
564
565    /// Returns true if the map contains the given key.
566    ///
567    /// # Examples
568    ///
569    /// ```
570    /// use my_ecs::ds::IndexedMap;
571    /// use std::hash::RandomState;
572    ///
573    /// let mut map = IndexedMap::<_, _, RandomState>::new();
574    /// map.insert('a', "alpha");
575    /// assert!(map.contains_key(&'a'));
576    /// ```
577    pub fn contains_key<Q>(&self, key: &Q) -> bool
578    where
579        K: std::borrow::Borrow<Q>,
580        Q: Hash + Eq + ?Sized,
581    {
582        self.map.contains_key(key)
583    }
584
585    /// Returns true if the map contains value corresponding to the given index.
586    ///
587    /// # Examples
588    ///
589    /// ```
590    /// use my_ecs::ds::IndexedMap;
591    /// use std::hash::RandomState;
592    ///
593    /// let mut map = IndexedMap::<_, _, RandomState>::new();
594    /// let (index, _) = map.insert('a', "alpha");
595    /// assert!(map.contains_index(index));
596    /// ```
597    pub fn contains_index(&self, index: usize) -> bool {
598        self.values.get(index).is_some()
599    }
600
601    /// Returns the next index that will be returned on the next call to
602    /// [`IndexedMap::insert`] with the given key.
603    ///
604    /// # Examples
605    ///
606    /// ```
607    /// use my_ecs::ds::IndexedMap;
608    /// use std::hash::RandomState;
609    ///
610    /// let mut map = IndexedMap::<_, _, RandomState>::new();
611    /// let next_index = map.next_index(&'a');
612    /// let (index, _) = map.insert('a', "alpha");
613    /// assert_eq!(next_index, index);
614    /// ```
615    pub fn next_index<Q>(&self, key: &Q) -> usize
616    where
617        K: std::borrow::Borrow<Q>,
618        Q: Hash + Eq + ?Sized,
619    {
620        if let Some(index) = self.map.get(key) {
621            *index
622        } else {
623            self.values.next_index()
624        }
625    }
626
627    /// Inserts the given key-value pair into the map and returns corresponding
628    /// index.
629    ///
630    /// If the map contains the key, then replaces values and returns old value.
631    ///
632    /// # Examples
633    ///
634    /// ```
635    /// use my_ecs::ds::IndexedMap;
636    /// use std::hash::RandomState;
637    ///
638    /// let mut map = IndexedMap::<_, _, RandomState>::new();
639    /// map.insert('a', "alpha");
640    /// let (_, old) = map.insert('a', "ah");
641    /// assert_eq!(old, Some("alpha"));
642    /// ```
643    pub fn insert(&mut self, key: K, value: V) -> (usize, Option<V>) {
644        match self.map.entry(key) {
645            Entry::Occupied(occupied) => {
646                let index = *occupied.get();
647                let old_value = self.values.set(index, Some(value));
648                (index, old_value)
649            }
650            Entry::Vacant(vacant) => {
651                let index = self.values.add(value);
652                if IMAP {
653                    self.imap.extend_set(index, vacant.key().clone());
654                }
655                vacant.insert(index);
656                (index, None)
657            }
658        }
659    }
660
661    /// Removes a value corresponding to the given key then returns it.
662    ///
663    /// Consider using [`IndexedMap::remove`] if you need to remove a value by
664    /// an index.
665    ///
666    /// # Examples
667    ///
668    /// ```
669    /// use my_ecs::ds::IndexedMap;
670    /// use std::hash::RandomState;
671    ///
672    /// let mut map = IndexedMap::<_, _, RandomState>::new();
673    /// map.insert('a', "alpha");
674    /// assert_eq!(map.remove2(&'a'), Some("alpha"));
675    /// ```
676    pub fn remove2<Q>(&mut self, key: &Q) -> Option<V>
677    where
678        K: std::borrow::Borrow<Q>,
679        Q: Hash + Eq + ?Sized,
680    {
681        self.remove_entry2(key).map(|(_key, value)| value)
682    }
683
684    /// Removes a value corresponding to the given key then returns it with the
685    /// key.
686    ///
687    /// Consider using [`IndexedMap::remove_entry`] if you need to remove a
688    /// value by an index.
689    ///
690    /// # Examples
691    ///
692    /// ```
693    /// use my_ecs::ds::IndexedMap;
694    /// use std::hash::RandomState;
695    ///
696    /// let mut map = IndexedMap::<_, _, RandomState>::new();
697    /// map.insert('a', "alpha");
698    /// assert_eq!(map.remove_entry2(&'a'), Some(('a', "alpha")));
699    /// ```
700    pub fn remove_entry2<Q>(&mut self, key: &Q) -> Option<(K, V)>
701    where
702        K: std::borrow::Borrow<Q>,
703        Q: Hash + Eq + ?Sized,
704    {
705        let (key, index) = self.map.remove_entry(key)?;
706        if IMAP {
707            let must_some = self.imap.take(index);
708            debug_assert!(must_some.is_some());
709        }
710        // Safety: We got `index` from `self.map`, which guarantees that the
711        // slot must be occupied.
712        let value = unsafe { self.values.take(index).unwrap_unchecked() };
713        Some((key, value))
714    }
715
716    /// Retrieves an index corresponding to the given key.
717    ///
718    /// # Examples
719    ///
720    /// ```
721    /// use my_ecs::ds::IndexedMap;
722    /// use std::hash::RandomState;
723    ///
724    /// let mut map = IndexedMap::<_, _, RandomState>::new();
725    /// let (index, _) = map.insert('a', "alpha");
726    /// assert_eq!(map.get_index(&'a'), Some(index));
727    /// ```
728    pub fn get_index<Q>(&self, key: &Q) -> Option<usize>
729    where
730        K: std::borrow::Borrow<Q>,
731        Q: Hash + Eq + ?Sized,
732    {
733        self.map.get(key).cloned()
734    }
735
736    /// Retrieves a shared reference to a value at the given index.
737    ///
738    /// Consider using [`IndexedMap::get2`] if you need to get a value by a key.
739    ///
740    /// # Examples
741    ///
742    /// ```
743    /// use my_ecs::ds::IndexedMap;
744    /// use std::hash::RandomState;
745    ///
746    /// let mut map = IndexedMap::<_, _, RandomState>::new();
747    /// let (index, _) = map.insert('a', "alpha");
748    /// assert_eq!(map.get(index), Some(&"alpha"));
749    /// ```
750    pub fn get(&self, index: usize) -> Option<&V> {
751        self.values.get(index)
752    }
753
754    /// Retrieves a shared reference to a value corresponding to the given key.
755    ///
756    /// Consider using [`IndexedMap::get`] if you need to get a value by an
757    /// index.
758    ///
759    /// # Examples
760    ///
761    /// ```
762    /// use my_ecs::ds::IndexedMap;
763    /// use std::hash::RandomState;
764    ///
765    /// let mut map = IndexedMap::<_, _, RandomState>::new();
766    /// let (index, _) = map.insert('a', "alpha");
767    /// assert_eq!(map.get2(&'a'), Some(&"alpha"));
768    /// ```
769    pub fn get2<Q>(&self, key: &Q) -> Option<&V>
770    where
771        K: std::borrow::Borrow<Q>,
772        Q: Hash + Eq + ?Sized,
773    {
774        let index = self.get_index(key)?;
775        self.get(index)
776    }
777
778    /// Retrieves a mutable reference to a value at the given index.
779    ///
780    /// Consider using [`IndexedMap::get_mut2`] if you need to get a value by a
781    /// key.
782    ///
783    /// # Examples
784    ///
785    /// ```
786    /// use my_ecs::ds::IndexedMap;
787    /// use std::hash::RandomState;
788    ///
789    /// let mut map = IndexedMap::<_, _, RandomState>::new();
790    /// let (index, _) = map.insert('a', "alpha");
791    /// assert_eq!(map.get_mut(index), Some(&mut "alpha"));
792    /// ```
793    pub fn get_mut(&mut self, index: usize) -> Option<&mut V> {
794        self.values.get_mut(index)
795    }
796
797    /// Retrieves a mutable reference to a value corresponding to the given key.
798    ///
799    /// Consider using [`IndexedMap::get_mut`] if you need to get a value by an
800    /// index.
801    ///
802    /// # Examples
803    ///
804    /// ```
805    /// use my_ecs::ds::IndexedMap;
806    /// use std::hash::RandomState;
807    ///
808    /// let mut map = IndexedMap::<_, _, RandomState>::new();
809    /// let (index, _) = map.insert('a', "alpha");
810    /// assert_eq!(map.get_mut2(&'a'), Some(&mut "alpha"));
811    /// ```
812    pub fn get_mut2<Q>(&mut self, key: &Q) -> Option<&mut V>
813    where
814        K: std::borrow::Borrow<Q>,
815        Q: Hash + Eq + ?Sized,
816    {
817        let index = self.get_index(key)?;
818        self.get_mut(index)
819    }
820
821    /// Returns an iterator visiting key-index-value pairs in the map in
822    /// arbitrary order.
823    ///
824    /// # Examples
825    ///
826    /// ```
827    /// use my_ecs::ds::IndexedMap;
828    /// use std::hash::RandomState;
829    ///
830    /// let mut map = IndexedMap::<_, _, RandomState>::new();
831    /// map.insert('a', "alpha");
832    /// map.insert('b', "beta");
833    /// for (key, index, value) in map.iter() {
834    ///     println!("{key}, {index}, {value}");
835    /// }
836    /// ```
837    pub fn iter(&self) -> impl Iterator<Item = (&K, usize, &V)> + Clone {
838        self.map.iter().map(|(key, &index)| {
839            let value = self.values.get(index).unwrap();
840            (key, index, value)
841        })
842    }
843
844    /// Returns a mutable iterator visiting key-index-value pairs in the map in
845    /// arbitrary order.
846    ///
847    /// You can modify values only through the iterator.
848    ///
849    /// # Examples
850    ///
851    /// ```
852    /// use my_ecs::ds::IndexedMap;
853    /// use std::hash::RandomState;
854    ///
855    /// let mut map = IndexedMap::<_, _, RandomState>::new();
856    /// map.insert('a', "alpha".to_owned());
857    /// map.insert('b', "beta".to_owned());
858    /// for (key, index, value) in map.iter_mut() {
859    ///     value.push('*');
860    ///     println!("{key}, {index}, {value}");
861    /// }
862    /// ```
863    // pub fn iter_mut(&mut self) -> IndexMapIterMut<K, V, S> {
864    pub fn iter_mut(&mut self) -> impl Iterator<Item = (&K, usize, &mut V)> {
865        self.map.iter().map(|(key, &index)| {
866            // Safety: We're braking borrow rules about `&mut V` by converting
867            // reference to pointer. But it's safe because the container `self`
868            // is still being borrowed.
869            let value = self.values.get_mut(index).unwrap();
870            let value = value as *mut V;
871            let value = unsafe { value.as_mut().unwrap_unchecked() };
872            (key, index, value)
873        })
874    }
875
876    /// Returns an iterator visiting all values.
877    ///
878    /// # Examples
879    ///
880    /// ```
881    /// use my_ecs::ds::IndexedMap;
882    /// use std::hash::RandomState;
883    ///
884    /// let mut map = IndexedMap::<_, _, RandomState>::new();
885    /// map.insert('a', "alpha");
886    /// map.insert('b', "beta");
887    /// for v in map.values() {
888    ///     println!("{v}");
889    /// }
890    /// ```
891    pub fn values(&self) -> impl Iterator<Item = &V> + Clone {
892        self.values.iter()
893    }
894
895    /// Returns a mutable iterator visiting all values.
896    ///
897    /// # Examples
898    ///
899    /// ```
900    /// use my_ecs::ds::IndexedMap;
901    /// use std::hash::RandomState;
902    ///
903    /// let mut map = IndexedMap::<_, _, RandomState>::new();
904    /// map.insert('a', "alpha".to_owned());
905    /// map.insert('b', "beta".to_owned());
906    /// for v in map.values_mut() {
907    ///     v.push('*');
908    ///     println!("{v}");
909    /// }
910    /// ```
911    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
912        self.values.iter_mut()
913    }
914}
915
916impl<K, V, S, const IMAP: bool> Default for IndexedMap<K, V, S, IMAP>
917where
918    S: Default,
919{
920    fn default() -> Self {
921        Self::new()
922    }
923}
924
925// Don't implement From for &mut [Option<V>] because it can break mapping.
926impl<'a, K, V, S, const IMAP: bool> From<&'a IndexedMap<K, V, S, IMAP>> for &'a [Option<V>]
927where
928    S: BuildHasher,
929{
930    fn from(value: &'a IndexedMap<K, V, S, IMAP>) -> Self {
931        value.values.as_slice()
932    }
933}