datex_core/utils/
freemap.rs

1use std::collections::HashMap;
2use std::collections::hash_map::{Iter, IterMut};
3
4pub trait NextKey: Copy + Eq + std::hash::Hash + Default {
5    fn next_key(&mut self) -> Self;
6}
7
8/// A HashMap that reuses freed IDs for new entries.
9pub struct FreeHashMap<K: NextKey, T> {
10    entries: HashMap<K, T>,
11    free_list: Vec<K>,
12    next_id: K,
13}
14
15impl<K: NextKey, T> Default for FreeHashMap<K, T> {
16    fn default() -> Self {
17        Self::new()
18    }
19}
20
21impl<K: NextKey, T> FreeHashMap<K, T> {
22    pub fn new() -> Self {
23        Self {
24            entries: HashMap::new(),
25            free_list: Vec::new(),
26            next_id: K::default(),
27        }
28    }
29
30    pub fn clear(&mut self) {
31        self.entries.clear();
32        self.free_list.clear();
33        self.next_id = K::default();
34    }
35
36    /// Adds a new entry and returns its unique ID.
37    pub fn add(&mut self, value: T) -> K {
38        if let Some(id) = self.free_list.pop() {
39            self.entries.insert(id, value);
40            id
41        } else {
42            let id = self.next_id.next_key();
43            self.entries.insert(id, value);
44            id
45        }
46    }
47
48    /// Checks if a value exists in the map.
49    pub fn has_value(&self, value: &T) -> bool
50    where
51        T: PartialEq,
52    {
53        self.entries.values().any(|v| v == value)
54    }
55
56    /// Returns the ID of a given value, if it exists.
57    pub fn get_id(&self, value: &T) -> Option<K>
58    where
59        T: PartialEq,
60    {
61        for (k, v) in &self.entries {
62            if v == value {
63                return Some(*k);
64            }
65        }
66        None
67    }
68
69    /// Returns the number of entries in the map.
70    pub fn len(&self) -> usize {
71        self.entries.len()
72    }
73
74    pub fn is_empty(&self) -> bool {
75        self.entries.is_empty()
76    }
77
78    /// Checks if an entry with the given ID exists.
79    pub fn has(&self, id: &K) -> bool {
80        self.entries.contains_key(id)
81    }
82
83    /// Removes the entry with the given ID, if it exists.
84    pub fn remove(&mut self, id: K) -> Option<T> {
85        let cur = self.entries.remove(&id);
86        if cur.is_some() {
87            self.free_list.push(id);
88        }
89        cur
90    }
91
92    /// Get a reference to an entry.
93    pub fn get(&self, id: &K) -> Option<&T> {
94        self.entries.get(id)
95    }
96
97    /// Get a mutable reference to an entry.
98    pub fn get_mut(&mut self, id: &K) -> Option<&mut T> {
99        self.entries.get_mut(id)
100    }
101
102    pub fn values(&self) -> impl Iterator<Item = &T> {
103        self.entries.values()
104    }
105    pub fn values_mut(&mut self) -> impl Iterator<Item = &mut T> {
106        self.entries.values_mut()
107    }
108    pub fn keys(&self) -> impl Iterator<Item = &K> {
109        self.entries.keys()
110    }
111
112    pub fn iter(&self) -> Iter<'_, K, T> {
113        self.entries.iter()
114    }
115
116    pub fn iter_mut(&mut self) -> IterMut<'_, K, T> {
117        self.entries.iter_mut()
118    }
119}
120
121impl<K: NextKey, T> IntoIterator for FreeHashMap<K, T> {
122    type Item = (K, T);
123    type IntoIter = std::collections::hash_map::IntoIter<K, T>;
124
125    fn into_iter(self) -> Self::IntoIter {
126        self.entries.into_iter()
127    }
128}
129
130impl<'a, K: NextKey, T> IntoIterator for &'a FreeHashMap<K, T> {
131    type Item = (&'a K, &'a T);
132    type IntoIter = Iter<'a, K, T>;
133
134    fn into_iter(self) -> Self::IntoIter {
135        self.entries.iter()
136    }
137}
138
139impl<'a, K: NextKey, T> IntoIterator for &'a mut FreeHashMap<K, T> {
140    type Item = (&'a K, &'a mut T);
141    type IntoIter = IterMut<'a, K, T>;
142
143    fn into_iter(self) -> Self::IntoIter {
144        self.entries.iter_mut()
145    }
146}
147
148impl NextKey for u32 {
149    fn next_key(&mut self) -> Self {
150        let current = *self;
151        *self = self.wrapping_add(1);
152        current
153    }
154}