Skip to main content

textlane_core/models/
arena.rs

1use std::fmt;
2use std::mem::ManuallyDrop;
3use std::ops::{Deref, DerefMut};
4
5use bumpalo::Bump;
6use bumpalo::collections::Vec as BumpVec;
7
8/// A vector allocated in a document's arena that never drops its items.
9///
10/// Items must own nothing outside the arena: the arena frees everything at once, and
11/// skipping drops keeps freeing a deeply nested tree from recursing once per level.
12pub struct ArenaVec<'a, T>(ManuallyDrop<BumpVec<'a, T>>);
13
14impl<'a, T> ArenaVec<'a, T> {
15    pub fn new_in(alloc: &'a Bump) -> Self {
16        Self(ManuallyDrop::new(BumpVec::new_in(alloc)))
17    }
18
19    pub fn with_capacity_in(capacity: usize, alloc: &'a Bump) -> Self {
20        Self(ManuallyDrop::new(BumpVec::with_capacity_in(
21            capacity, alloc,
22        )))
23    }
24}
25
26impl<'a, T> Deref for ArenaVec<'a, T> {
27    type Target = BumpVec<'a, T>;
28
29    fn deref(&self) -> &Self::Target {
30        &self.0
31    }
32}
33
34impl<T> DerefMut for ArenaVec<'_, T> {
35    fn deref_mut(&mut self) -> &mut Self::Target {
36        &mut self.0
37    }
38}
39
40impl<'a, T> IntoIterator for ArenaVec<'a, T> {
41    type Item = T;
42    type IntoIter = bumpalo::collections::vec::IntoIter<'a, T>;
43
44    fn into_iter(self) -> Self::IntoIter {
45        ManuallyDrop::into_inner(self.0).into_iter()
46    }
47}
48
49impl<'v, T> IntoIterator for &'v ArenaVec<'_, T> {
50    type Item = &'v T;
51    type IntoIter = std::slice::Iter<'v, T>;
52
53    fn into_iter(self) -> Self::IntoIter {
54        self.0.iter()
55    }
56}
57
58impl<'v, T> IntoIterator for &'v mut ArenaVec<'_, T> {
59    type Item = &'v mut T;
60    type IntoIter = std::slice::IterMut<'v, T>;
61
62    fn into_iter(self) -> Self::IntoIter {
63        self.0.iter_mut()
64    }
65}
66
67impl<T: fmt::Debug> fmt::Debug for ArenaVec<'_, T> {
68    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
69        self.0.fmt(formatter)
70    }
71}
72
73impl<T: PartialEq> PartialEq for ArenaVec<'_, T> {
74    fn eq(&self, other: &Self) -> bool {
75        self.0[..] == other.0[..]
76    }
77}