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}