dcc_lsystem/arena.rs
1use std::slice::{Iter, IterMut};
2
3#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
4pub struct ArenaId(pub usize);
5
6/// A simple arena wrapping around a Vec<T>.
7///
8/// # Examples
9///
10/// ```rust
11/// use dcc_lsystem::Arena;
12///
13/// let mut arena = Arena::new();
14///
15/// let u = arena.push(1);
16/// let v = arena.push(2);
17///
18/// assert_eq!(arena.len(), 2);
19/// assert_eq!(arena.get(u), Some(&1));
20/// ```
21#[derive(Debug, Clone)]
22pub struct Arena<T> {
23 arena: Vec<T>,
24}
25
26impl<T> Arena<T> {
27 /// Creates a new empty arena.
28 ///
29 /// # Example
30 /// ```rust
31 /// use dcc_lsystem::Arena;
32 ///
33 /// let mut arena = Arena::new();
34 ///
35 /// arena.push(1);
36 /// arena.push(3);
37 /// ```
38 pub fn new() -> Self {
39 Self { arena: Vec::new() }
40 }
41
42 /// Returns the length of this arena.
43 ///
44 /// # Example
45 /// ```rust
46 /// use dcc_lsystem::Arena;
47 ///
48 /// let mut arena = Arena::new();
49 ///
50 /// for i in 0..420 {
51 /// arena.push(i);
52 /// }
53 ///
54 /// assert_eq!(arena.len(), 420);
55 /// ```
56 pub fn len(&self) -> usize {
57 self.arena.len()
58 }
59
60 /// Returns `true` if the arena contains no elements.
61 ///
62 /// # Example
63 /// ```rust
64 /// use dcc_lsystem::Arena;
65 ///
66 /// let mut arena = Arena::new();
67 ///
68 /// assert!(arena.is_empty());
69 ///
70 /// arena.push(3);
71 ///
72 /// assert!(!arena.is_empty());
73 /// ```
74 pub fn is_empty(&self) -> bool {
75 self.arena.is_empty()
76 }
77
78 /// Returns a reference to an entry of the arena,
79 /// if the provided ArenaId is valid.
80 ///
81 /// # Example
82 /// ```rust
83 /// use dcc_lsystem::Arena;
84 ///
85 /// let mut arena = Arena::new();
86 ///
87 /// let x = arena.push("x");
88 /// let y = arena.push("y");
89 /// let z = arena.push("z");
90 ///
91 /// assert_eq!(arena.get(y), Some(&"y"));
92 /// ```
93 pub fn get(&self, id: ArenaId) -> Option<&T> {
94 self.arena.get(id.0)
95 }
96
97 /// Returns a mutable reference to the entry corresponding
98 /// to the given index.
99 ///
100 /// # Example
101 /// ```rust
102 /// use dcc_lsystem::Arena;
103 ///
104 /// let mut arena = Arena::new();
105 ///
106 /// let x = arena.push("x");
107 ///
108 /// if let Some(entry) = arena.get_mut(x) {
109 /// *entry = "y";
110 /// }
111 ///
112 /// assert_eq!(arena.get(x), Some(&"y"));
113 /// ```
114 pub fn get_mut(&mut self, id: ArenaId) -> Option<&mut T> {
115 self.arena.get_mut(id.0)
116 }
117
118 /// Returns an iterator over this arena.
119 ///
120 /// # Example
121 /// ```rust
122 /// use dcc_lsystem::Arena;
123 ///
124 /// let mut arena = Arena::new();
125 /// let x = arena.push(3);
126 /// let y = arena.push(5);
127 ///
128 /// let mut iterator = arena.iter();
129 ///
130 /// assert_eq!(iterator.next(), Some(&3));
131 /// assert_eq!(iterator.next(), Some(&5));
132 /// assert_eq!(iterator.next(), None)
133 /// ```
134 pub fn iter(&self) -> Iter<'_, T> {
135 self.arena.iter()
136 }
137
138 /// Returns an iterator that allows modifying each value.
139 ///
140 /// # Example
141 /// ```rust
142 /// use dcc_lsystem::Arena;
143 ///
144 /// let mut arena = Arena::new();
145 /// let x = arena.push(3);
146 /// let y = arena.push(-4);
147 ///
148 /// for entry in arena.iter_mut() {
149 /// *entry = *entry * *entry;
150 /// }
151 ///
152 /// let mut iterator = arena.iter();
153 ///
154 /// assert_eq!(iterator.next(), Some(&9));
155 /// assert_eq!(iterator.next(), Some(&16));
156 /// ```
157 pub fn iter_mut(&mut self) -> IterMut<T> {
158 self.arena.iter_mut()
159 }
160
161 /// Returns true if the provided id corresponds to an element of this arena.
162 ///
163 /// ```rust
164 /// use dcc_lsystem::{Arena, ArenaId};
165 ///
166 /// let mut arena = Arena::new();
167 /// let x = arena.push(17);
168 /// let y = arena.push(21);
169 ///
170 /// assert!(arena.is_valid(x));
171 /// assert!(arena.is_valid(y));
172 ///
173 /// assert!(!arena.is_valid(ArenaId(2)));
174 /// ```
175 pub fn is_valid(&self, id: ArenaId) -> bool {
176 id.0 < self.arena.len()
177 }
178
179 /// Returns `true` if the every id in the provided slice is valid.
180 ///
181 /// # Example
182 /// ```rust
183 /// use dcc_lsystem::{Arena, ArenaId};
184 ///
185 /// let mut arena = Arena::new();
186 /// let x = arena.push(1);
187 /// let y = arena.push(3);
188 /// let z = arena.push(7);
189 ///
190 /// assert!(arena.is_valid_slice(&[x,y]));
191 /// assert!(arena.is_valid_slice(&[x,y,z]));
192 /// assert!(!arena.is_valid_slice(&[x,y,ArenaId(3)]));
193 /// ```
194 pub fn is_valid_slice(&self, slice: &[ArenaId]) -> bool {
195 slice.iter().all(|id| self.is_valid(*id))
196 }
197
198 /// Add a new value to our arena.
199 ///
200 /// Returns an ArenaId which uniquely identifies this element of the arena.
201 ///
202 /// # Example
203 /// use dcc_lsystem::Arena;
204 ///
205 /// let mut arena = Arena::new();
206 /// let x = arena.push(11);
207 /// let y = arena.push(-3);
208 ///
209 /// assert_eq!(x, ArenaId(0));
210 /// assert_eq!(y, ArenaId(1));
211 /// ```
212 pub fn push(&mut self, value: T) -> ArenaId {
213 self.arena.push(value);
214 ArenaId(self.arena.len() - 1)
215 }
216
217 /// Returns an EnumerableArena.
218 ///
219 /// # Example
220 /// ```rust
221 /// use dcc_lsystem::Arena;
222 ///
223 /// let mut arena = Arena::new();
224 /// let x = arena.push(3);
225 /// let y = arena.push(5);
226 /// let z = arena.push(-7);
227 ///
228 /// for (id, entry) in arena.enumerate() {
229 /// /* do some work here */
230 /// }
231 /// ```
232 pub fn enumerate(&self) -> EnumerableArena<'_, T> {
233 EnumerableArena {
234 inner: &self,
235 pos: 0,
236 }
237 }
238}
239
240/// An iterator that yields the current ArenaId and the element during iterator.
241///
242/// # Examples
243///
244/// ```rust
245/// use dcc_lsystem::Arena;
246///
247/// let mut arena = Arena::new();
248///
249/// let x = arena.push(1);
250/// let y = arena.push(2);
251/// let z = arena.push(-3);
252///
253/// let mut enumerable = arena.enumerate();
254///
255/// assert_eq!(enumerable.next(), Some((x, &1)));
256/// assert_eq!(enumerable.next(), Some((y, &2)));
257/// assert_eq!(enumerable.next(), Some((z, &-3)));
258/// assert_eq!(enumerable.next(), None);
259/// ```
260///
261/// This method is prefer over calling enumerate() on arena.iter():
262///
263/// ```rust
264/// use dcc_lsystem::{Arena, ArenaId};
265///
266/// let mut arena = Arena::new();
267/// arena.push(1);
268/// arena.push(-2);
269/// arena.push(17);
270///
271/// // Good:
272/// for (id, entry) in arena.enumerate() {
273/// /* Do some work here */
274/// }
275///
276/// // Less good:
277/// for (index, entry) in arena.iter().enumerate() {
278/// // Convert the raw index to an ArenaId
279/// let id = ArenaId(index);
280///
281/// /* Do some work here */
282/// }
283/// ```
284pub struct EnumerableArena<'a, T: 'a> {
285 inner: &'a Arena<T>,
286
287 // Current position of our iterator
288 pos: usize,
289}
290
291impl<'a, T> Iterator for EnumerableArena<'a, T> {
292 type Item = (ArenaId, &'a T);
293
294 fn next(&mut self) -> Option<Self::Item> {
295 if self.pos >= self.inner.arena.len() {
296 None
297 } else {
298 self.pos += 1;
299 Some((
300 ArenaId(self.pos - 1),
301 self.inner.arena.get(self.pos - 1).unwrap(),
302 ))
303 }
304 }
305}
306
307impl<T> Default for Arena<T> {
308 fn default() -> Self {
309 Self::new()
310 }
311}
312
313#[cfg(test)]
314mod tests {
315 use super::*;
316
317 #[test]
318 fn arena_basic() {
319 let mut arena = Arena::new();
320
321 let a = arena.push("Hello!");
322 let b = arena.push("World");
323
324 assert_eq!(a.0, 0);
325 assert_eq!(b.0, 1);
326 assert_eq!(arena.len(), 2);
327
328 let a_ref = arena.get(a).expect("Failed to get a");
329
330 assert_eq!(*a_ref, "Hello!");
331
332 {
333 let b_ref_mut = arena.get_mut(b).expect("Failed to get b");
334 *b_ref_mut = "Jenkins";
335 }
336
337 assert_eq!(arena.get(b).unwrap(), &"Jenkins");
338 }
339
340 #[test]
341 fn arena_iterator() {
342 let mut arena = Arena::new();
343
344 arena.push("my first entry");
345 arena.push("my second entry");
346 arena.push("my third entry");
347
348 let mut iter = arena.iter();
349
350 assert_eq!(iter.next(), Some(&"my first entry"));
351 assert_eq!(iter.next(), Some(&"my second entry"));
352 assert_eq!(iter.next(), Some(&"my third entry"));
353 assert_eq!(iter.next(), None);
354 }
355
356 #[test]
357 fn arena_iterator_mut() {
358 let mut arena = Arena::new();
359
360 arena.push(1);
361 arena.push(3);
362 arena.push(-5);
363 arena.push(7);
364
365 // Square each entry in our arena
366 for entry in arena.iter_mut() {
367 *entry = *entry * *entry;
368 }
369
370 let mut iter = arena.iter();
371
372 assert_eq!(iter.next(), Some(&1));
373 assert_eq!(iter.next(), Some(&9));
374 assert_eq!(iter.next(), Some(&25));
375 assert_eq!(iter.next(), Some(&49));
376 }
377
378 #[test]
379 fn arena_enumerate() {
380 let mut arena = Arena::new();
381
382 let a = arena.push(1);
383 let b = arena.push(3);
384 let c = arena.push(4);
385 let d = arena.push(8);
386
387 let mut enumerator = arena.enumerate();
388
389 assert_eq!(enumerator.next(), Some((a, &1)));
390 assert_eq!(enumerator.next(), Some((b, &3)));
391 assert_eq!(enumerator.next(), Some((c, &4)));
392 assert_eq!(enumerator.next(), Some((d, &8)));
393 }
394}