Skip to main content

pumpkin_core/containers/
keyed_vec.rs

1use std::marker::PhantomData;
2use std::ops::Index;
3use std::ops::IndexMut;
4
5/// Structure for storing elements of type `Value`, the structure can only be indexed by structures
6/// of type `Key`.
7///
8/// Almost all features of this structure require that `Key` implements the [StorageKey] trait.
9#[derive(Debug, Hash, PartialEq, Eq)]
10pub struct KeyedVec<Key, Value> {
11    /// [PhantomData] to ensure that the [KeyedVec] is bound to the structure
12    key: PhantomData<Key>,
13    /// Storage of the elements of type `Value`
14    elements: Vec<Value>,
15}
16
17impl<Key, Value: Clone> Clone for KeyedVec<Key, Value> {
18    fn clone(&self) -> Self {
19        Self {
20            key: PhantomData,
21            elements: self.elements.clone(),
22        }
23    }
24}
25
26impl<Key, Value> Default for KeyedVec<Key, Value> {
27    fn default() -> Self {
28        Self {
29            key: PhantomData,
30            elements: Vec::default(),
31        }
32    }
33}
34
35impl<Key, Value> KeyedVec<Key, Value> {
36    pub(crate) const fn new() -> Self {
37        Self {
38            key: PhantomData,
39            elements: Vec::new(),
40        }
41    }
42}
43
44impl<Key: StorageKey, Value> KeyedVec<Key, Value> {
45    pub fn get(&self, key: Key) -> Option<&Value> {
46        self.elements.get(key.index())
47    }
48
49    pub fn get_mut(&mut self, key: Key) -> Option<&mut Value> {
50        self.elements.get_mut(key.index())
51    }
52
53    pub fn pop(&mut self) -> Option<(Key, Value)> {
54        self.elements.pop().map(|value| {
55            let key = Key::create_from_index(self.elements.len());
56            (key, value)
57        })
58    }
59
60    pub fn len(&self) -> usize {
61        self.elements.len()
62    }
63
64    pub fn is_empty(&self) -> bool {
65        self.elements.is_empty()
66    }
67
68    /// Add a new value to the vector.
69    ///
70    /// Returns the key for the inserted value.
71    pub fn push(&mut self, value: Value) -> Key {
72        self.elements.push(value);
73
74        Key::create_from_index(self.elements.len() - 1)
75    }
76
77    /// Create a new slot for a value, and populate it using [`Slot::populate()`].
78    ///
79    /// This allows initializing the value with the ID it will have in this vector.
80    ///
81    /// # Example
82    /// ```
83    /// # use pumpkin_core::containers::StorageKey;
84    /// # use pumpkin_core::containers::KeyedVec;
85    /// #[derive(Clone)]
86    /// struct Key(usize);
87    ///
88    /// impl StorageKey for Key {
89    ///     // ...
90    /// #   fn create_from_index(index: usize) -> Self {
91    /// #       Key(index)
92    /// #   }
93    /// #
94    /// #   fn index(&self) -> usize {
95    /// #       self.0
96    /// #   }
97    /// }
98    ///
99    /// struct Value;
100    ///
101    /// /// Create a value based on the specified key.
102    /// fn create_value(key: Key) -> Value {
103    ///     // ...
104    /// #   Value
105    /// }
106    ///
107    /// let mut keyed_vec: KeyedVec<Key, Value> = KeyedVec::default();
108    ///
109    /// // Reserve a slot.
110    /// let slot = keyed_vec.new_slot();
111    /// // Create the value.
112    /// let value = create_value(slot.key());
113    /// // Populate the slot.
114    /// slot.populate(value);
115    /// ```
116    pub fn new_slot(&mut self) -> Slot<'_, Key, Value> {
117        Slot { vec: self }
118    }
119
120    /// Iterate over the values in the vector.
121    pub fn iter(&self) -> impl Iterator<Item = &'_ Value> {
122        self.elements.iter()
123    }
124
125    pub(crate) fn keys(&self) -> impl Iterator<Item = Key> {
126        (0..self.elements.len()).map(Key::create_from_index)
127    }
128
129    pub(crate) fn iter_mut(&mut self) -> impl Iterator<Item = &'_ mut Value> {
130        self.elements.iter_mut()
131    }
132
133    pub(crate) fn swap(&mut self, a: usize, b: usize) {
134        self.elements.swap(a, b)
135    }
136}
137
138impl<Key: StorageKey, Value: Clone> KeyedVec<Key, Value> {
139    pub fn accomodate(&mut self, key: Key, default_value: Value) {
140        if key.index() >= self.elements.len() {
141            self.elements.resize(key.index() + 1, default_value)
142        }
143    }
144
145    pub fn resize(&mut self, new_len: usize, value: Value) {
146        self.elements.resize(new_len, value)
147    }
148
149    pub fn clear(&mut self) {
150        self.elements.clear();
151    }
152}
153
154impl<Key: StorageKey, Value> Index<Key> for KeyedVec<Key, Value> {
155    type Output = Value;
156
157    fn index(&self, index: Key) -> &Self::Output {
158        &self.elements[index.index()]
159    }
160}
161
162impl<Key: StorageKey, Value> Index<&Key> for KeyedVec<Key, Value> {
163    type Output = Value;
164
165    fn index(&self, index: &Key) -> &Self::Output {
166        &self.elements[index.index()]
167    }
168}
169
170impl<Key: StorageKey, Value> IndexMut<Key> for KeyedVec<Key, Value> {
171    fn index_mut(&mut self, index: Key) -> &mut Self::Output {
172        &mut self.elements[index.index()]
173    }
174}
175
176impl StorageKey for usize {
177    fn index(&self) -> usize {
178        *self
179    }
180
181    fn create_from_index(index: usize) -> Self {
182        index
183    }
184}
185
186impl StorageKey for u32 {
187    fn index(&self) -> usize {
188        *self as usize
189    }
190
191    fn create_from_index(index: usize) -> Self {
192        index as u32
193    }
194}
195
196/// A simple trait which requires that the structures implementing this trait can generate an index.
197pub trait StorageKey: Clone {
198    fn index(&self) -> usize;
199
200    fn create_from_index(index: usize) -> Self;
201}
202
203/// A reserved slot for a new value in a [`KeyedVec`].
204#[derive(Debug)]
205pub struct Slot<'a, Key, Value> {
206    vec: &'a mut KeyedVec<Key, Value>,
207}
208
209impl<Key: StorageKey, Value> Slot<'_, Key, Value> {
210    /// The key this slot has.
211    pub fn key(&self) -> Key {
212        Key::create_from_index(self.vec.len())
213    }
214
215    /// Populate the slot with a value.
216    pub fn populate(self, value: Value) -> Key {
217        self.vec.push(value)
218    }
219}