aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/README.md2
-rw-r--r--lib/arena/Cargo.toml10
-rw-r--r--lib/arena/src/lib.rs231
-rw-r--r--lib/arena/src/map.rs69
4 files changed, 312 insertions, 0 deletions
diff --git a/lib/README.md b/lib/README.md
new file mode 100644
index 000000000..6b2eeac2c
--- /dev/null
+++ b/lib/README.md
@@ -0,0 +1,2 @@
1Crates in this directory are published to crates.io and obey semver.
2They *could* live in a separate repo, but we want to experiment with a monorepo setup.
diff --git a/lib/arena/Cargo.toml b/lib/arena/Cargo.toml
new file mode 100644
index 000000000..f4d2ecb6c
--- /dev/null
+++ b/lib/arena/Cargo.toml
@@ -0,0 +1,10 @@
1[package]
2name = "la-arena"
3version = "0.2.0"
4description = "Simple index-based arena without deletion."
5license = "MIT OR Apache-2.0"
6repository = "https://github.com/rust-analyzer/rust-analyzer"
7documentation = "https://docs.rs/la-arena"
8categories = ["data-structures", "memory-management", "rust-patterns"]
9authors = ["rust-analyzer developers"]
10edition = "2018"
diff --git a/lib/arena/src/lib.rs b/lib/arena/src/lib.rs
new file mode 100644
index 000000000..230a50291
--- /dev/null
+++ b/lib/arena/src/lib.rs
@@ -0,0 +1,231 @@
1//! Yet another index-based arena.
2
3#![warn(missing_docs)]
4
5use std::{
6 fmt,
7 hash::{Hash, Hasher},
8 iter::FromIterator,
9 marker::PhantomData,
10 ops::{Index, IndexMut},
11};
12
13mod map;
14pub use map::ArenaMap;
15
16/// The raw index of a value in an arena.
17#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
18pub struct RawIdx(u32);
19
20impl From<RawIdx> for u32 {
21 fn from(raw: RawIdx) -> u32 {
22 raw.0
23 }
24}
25
26impl From<u32> for RawIdx {
27 fn from(idx: u32) -> RawIdx {
28 RawIdx(idx)
29 }
30}
31
32impl fmt::Debug for RawIdx {
33 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
34 self.0.fmt(f)
35 }
36}
37
38impl fmt::Display for RawIdx {
39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 self.0.fmt(f)
41 }
42}
43
44/// The index of a value allocated in an arena that holds `T`s.
45pub struct Idx<T> {
46 raw: RawIdx,
47 _ty: PhantomData<fn() -> T>,
48}
49
50impl<T> Clone for Idx<T> {
51 fn clone(&self) -> Self {
52 *self
53 }
54}
55impl<T> Copy for Idx<T> {}
56
57impl<T> PartialEq for Idx<T> {
58 fn eq(&self, other: &Idx<T>) -> bool {
59 self.raw == other.raw
60 }
61}
62impl<T> Eq for Idx<T> {}
63
64impl<T> Hash for Idx<T> {
65 fn hash<H: Hasher>(&self, state: &mut H) {
66 self.raw.hash(state)
67 }
68}
69
70impl<T> fmt::Debug for Idx<T> {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 let mut type_name = std::any::type_name::<T>();
73 if let Some(idx) = type_name.rfind(':') {
74 type_name = &type_name[idx + 1..]
75 }
76 write!(f, "Idx::<{}>({})", type_name, self.raw)
77 }
78}
79
80impl<T> Idx<T> {
81 /// Creates a new index from a [`RawIdx`].
82 pub fn from_raw(raw: RawIdx) -> Self {
83 Idx { raw, _ty: PhantomData }
84 }
85
86 /// Converts this index into the underlying [`RawIdx`].
87 pub fn into_raw(self) -> RawIdx {
88 self.raw
89 }
90}
91
92/// Yet another index-based arena.
93#[derive(Clone, PartialEq, Eq)]
94pub struct Arena<T> {
95 data: Vec<T>,
96}
97
98impl<T: fmt::Debug> fmt::Debug for Arena<T> {
99 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
100 fmt.debug_struct("Arena").field("len", &self.len()).field("data", &self.data).finish()
101 }
102}
103
104impl<T> Arena<T> {
105 /// Creates a new empty arena.
106 ///
107 /// ```
108 /// let arena: la_arena::Arena<i32> = la_arena::Arena::new();
109 /// assert!(arena.is_empty());
110 /// ```
111 pub const fn new() -> Arena<T> {
112 Arena { data: Vec::new() }
113 }
114
115 /// Empties the arena, removing all contained values.
116 ///
117 /// ```
118 /// let mut arena = la_arena::Arena::new();
119 ///
120 /// arena.alloc(1);
121 /// arena.alloc(2);
122 /// arena.alloc(3);
123 /// assert_eq!(arena.len(), 3);
124 ///
125 /// arena.clear();
126 /// assert!(arena.is_empty());
127 /// ```
128 pub fn clear(&mut self) {
129 self.data.clear();
130 }
131
132 /// Returns the length of the arena.
133 ///
134 /// ```
135 /// let mut arena = la_arena::Arena::new();
136 /// assert_eq!(arena.len(), 0);
137 ///
138 /// arena.alloc("foo");
139 /// assert_eq!(arena.len(), 1);
140 ///
141 /// arena.alloc("bar");
142 /// assert_eq!(arena.len(), 2);
143 ///
144 /// arena.alloc("baz");
145 /// assert_eq!(arena.len(), 3);
146 /// ```
147 pub fn len(&self) -> usize {
148 self.data.len()
149 }
150
151 /// Returns whether the arena contains no elements.
152 ///
153 /// ```
154 /// let mut arena = la_arena::Arena::new();
155 /// assert!(arena.is_empty());
156 ///
157 /// arena.alloc(0.5);
158 /// assert!(!arena.is_empty());
159 /// ```
160 pub fn is_empty(&self) -> bool {
161 self.data.is_empty()
162 }
163
164 /// Allocates a new value on the arena, returning the value’s index.
165 ///
166 /// ```
167 /// let mut arena = la_arena::Arena::new();
168 /// let idx = arena.alloc(50);
169 ///
170 /// assert_eq!(arena[idx], 50);
171 /// ```
172 pub fn alloc(&mut self, value: T) -> Idx<T> {
173 let idx = RawIdx(self.data.len() as u32);
174 self.data.push(value);
175 Idx::from_raw(idx)
176 }
177
178 /// Returns an iterator over the arena’s elements.
179 ///
180 /// ```
181 /// let mut arena = la_arena::Arena::new();
182 /// let idx1 = arena.alloc(20);
183 /// let idx2 = arena.alloc(40);
184 /// let idx3 = arena.alloc(60);
185 ///
186 /// let mut iterator = arena.iter();
187 /// assert_eq!(iterator.next(), Some((idx1, &20)));
188 /// assert_eq!(iterator.next(), Some((idx2, &40)));
189 /// assert_eq!(iterator.next(), Some((idx3, &60)));
190 /// ```
191 pub fn iter(
192 &self,
193 ) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator {
194 self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value))
195 }
196
197 /// Reallocates the arena to make it take up as little space as possible.
198 pub fn shrink_to_fit(&mut self) {
199 self.data.shrink_to_fit();
200 }
201}
202
203impl<T> Default for Arena<T> {
204 fn default() -> Arena<T> {
205 Arena { data: Vec::new() }
206 }
207}
208
209impl<T> Index<Idx<T>> for Arena<T> {
210 type Output = T;
211 fn index(&self, idx: Idx<T>) -> &T {
212 let idx = idx.into_raw().0 as usize;
213 &self.data[idx]
214 }
215}
216
217impl<T> IndexMut<Idx<T>> for Arena<T> {
218 fn index_mut(&mut self, idx: Idx<T>) -> &mut T {
219 let idx = idx.into_raw().0 as usize;
220 &mut self.data[idx]
221 }
222}
223
224impl<T> FromIterator<T> for Arena<T> {
225 fn from_iter<I>(iter: I) -> Self
226 where
227 I: IntoIterator<Item = T>,
228 {
229 Arena { data: Vec::from_iter(iter) }
230 }
231}
diff --git a/lib/arena/src/map.rs b/lib/arena/src/map.rs
new file mode 100644
index 000000000..d8acfe051
--- /dev/null
+++ b/lib/arena/src/map.rs
@@ -0,0 +1,69 @@
1use std::marker::PhantomData;
2
3use crate::Idx;
4
5/// A map from arena indexes to some other type.
6/// Space requirement is O(highest index).
7#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
8pub struct ArenaMap<IDX, V> {
9 v: Vec<Option<V>>,
10 _ty: PhantomData<IDX>,
11}
12
13impl<T, V> ArenaMap<Idx<T>, V> {
14 /// Inserts a value associated with a given arena index into the map.
15 pub fn insert(&mut self, idx: Idx<T>, t: V) {
16 let idx = Self::to_idx(idx);
17
18 self.v.resize_with((idx + 1).max(self.v.len()), || None);
19 self.v[idx] = Some(t);
20 }
21
22 /// Returns a reference to the value associated with the provided index
23 /// if it is present.
24 pub fn get(&self, idx: Idx<T>) -> Option<&V> {
25 self.v.get(Self::to_idx(idx)).and_then(|it| it.as_ref())
26 }
27
28 /// Returns a mutable reference to the value associated with the provided index
29 /// if it is present.
30 pub fn get_mut(&mut self, idx: Idx<T>) -> Option<&mut V> {
31 self.v.get_mut(Self::to_idx(idx)).and_then(|it| it.as_mut())
32 }
33
34 /// Returns an iterator over the values in the map.
35 pub fn values(&self) -> impl Iterator<Item = &V> {
36 self.v.iter().filter_map(|o| o.as_ref())
37 }
38
39 /// Returns an iterator over mutable references to the values in the map.
40 pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> {
41 self.v.iter_mut().filter_map(|o| o.as_mut())
42 }
43
44 /// Returns an iterator over the arena indexes and values in the map.
45 pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> {
46 self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?)))
47 }
48
49 fn to_idx(idx: Idx<T>) -> usize {
50 u32::from(idx.into_raw()) as usize
51 }
52
53 fn from_idx(idx: usize) -> Idx<T> {
54 Idx::from_raw((idx as u32).into())
55 }
56}
57
58impl<T, V> std::ops::Index<Idx<V>> for ArenaMap<Idx<V>, T> {
59 type Output = T;
60 fn index(&self, idx: Idx<V>) -> &T {
61 self.v[Self::to_idx(idx)].as_ref().unwrap()
62 }
63}
64
65impl<T, V> Default for ArenaMap<Idx<V>, T> {
66 fn default() -> Self {
67 ArenaMap { v: Vec::new(), _ty: PhantomData }
68 }
69}