diff options
Diffstat (limited to 'lib/arena')
-rw-r--r-- | lib/arena/Cargo.toml | 10 | ||||
-rw-r--r-- | lib/arena/src/lib.rs | 80 | ||||
-rw-r--r-- | lib/arena/src/map.rs | 6 |
3 files changed, 90 insertions, 6 deletions
diff --git a/lib/arena/Cargo.toml b/lib/arena/Cargo.toml index 183a5bb6a..b9dbb7ef3 100644 --- a/lib/arena/Cargo.toml +++ b/lib/arena/Cargo.toml | |||
@@ -1,10 +1,10 @@ | |||
1 | [package] | 1 | [package] |
2 | name = "la-arena" | 2 | name = "la-arena" |
3 | version = "0.1.0" | 3 | version = "0.1.1" |
4 | description = "Thy rope of sands..." | 4 | description = "Simple index-based arena without deletion." |
5 | license = "MIT OR Apache-2.0" | 5 | license = "MIT OR Apache-2.0" |
6 | repository = "https://github.com/rust-analyzer/rust-analyzer" | ||
7 | documentation = "https://docs.rs/la-arena" | ||
8 | categories = ["data-structures", "memory-management", "rust-patterns"] | ||
6 | authors = ["rust-analyzer developers"] | 9 | authors = ["rust-analyzer developers"] |
7 | edition = "2018" | 10 | edition = "2018" |
8 | |||
9 | [lib] | ||
10 | doctest = false | ||
diff --git a/lib/arena/src/lib.rs b/lib/arena/src/lib.rs index b15fe941d..1de3a1d2f 100644 --- a/lib/arena/src/lib.rs +++ b/lib/arena/src/lib.rs | |||
@@ -1,4 +1,6 @@ | |||
1 | //! Yet another index-based arena. | 1 | //! Yet another ID-based arena. |
2 | |||
3 | #![warn(missing_docs)] | ||
2 | 4 | ||
3 | use std::{ | 5 | use std::{ |
4 | fmt, | 6 | fmt, |
@@ -11,6 +13,7 @@ use std::{ | |||
11 | mod map; | 13 | mod map; |
12 | pub use map::ArenaMap; | 14 | pub use map::ArenaMap; |
13 | 15 | ||
16 | /// The raw ID of a value in an arena. | ||
14 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] | 17 | #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] |
15 | pub struct RawId(u32); | 18 | pub struct RawId(u32); |
16 | 19 | ||
@@ -38,6 +41,7 @@ impl fmt::Display for RawId { | |||
38 | } | 41 | } |
39 | } | 42 | } |
40 | 43 | ||
44 | /// The ID of a value allocated in an arena that holds `T`s. | ||
41 | pub struct Idx<T> { | 45 | pub struct Idx<T> { |
42 | raw: RawId, | 46 | raw: RawId, |
43 | _ty: PhantomData<fn() -> T>, | 47 | _ty: PhantomData<fn() -> T>, |
@@ -74,14 +78,18 @@ impl<T> fmt::Debug for Idx<T> { | |||
74 | } | 78 | } |
75 | 79 | ||
76 | impl<T> Idx<T> { | 80 | impl<T> Idx<T> { |
81 | /// Creates a new ID from a [`RawId`]. | ||
77 | pub fn from_raw(raw: RawId) -> Self { | 82 | pub fn from_raw(raw: RawId) -> Self { |
78 | Idx { raw, _ty: PhantomData } | 83 | Idx { raw, _ty: PhantomData } |
79 | } | 84 | } |
85 | |||
86 | /// Converts this ID into the underlying [`RawId`]. | ||
80 | pub fn into_raw(self) -> RawId { | 87 | pub fn into_raw(self) -> RawId { |
81 | self.raw | 88 | self.raw |
82 | } | 89 | } |
83 | } | 90 | } |
84 | 91 | ||
92 | /// Yet another ID-based arena. | ||
85 | #[derive(Clone, PartialEq, Eq)] | 93 | #[derive(Clone, PartialEq, Eq)] |
86 | pub struct Arena<T> { | 94 | pub struct Arena<T> { |
87 | data: Vec<T>, | 95 | data: Vec<T>, |
@@ -94,29 +102,99 @@ impl<T: fmt::Debug> fmt::Debug for Arena<T> { | |||
94 | } | 102 | } |
95 | 103 | ||
96 | impl<T> Arena<T> { | 104 | impl<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 | /// ``` | ||
97 | pub const fn new() -> Arena<T> { | 111 | pub const fn new() -> Arena<T> { |
98 | Arena { data: Vec::new() } | 112 | Arena { data: Vec::new() } |
99 | } | 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 | /// ``` | ||
100 | pub fn clear(&mut self) { | 128 | pub fn clear(&mut self) { |
101 | self.data.clear(); | 129 | self.data.clear(); |
102 | } | 130 | } |
103 | 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 | /// ``` | ||
104 | pub fn len(&self) -> usize { | 147 | pub fn len(&self) -> usize { |
105 | self.data.len() | 148 | self.data.len() |
106 | } | 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 | /// ``` | ||
107 | pub fn is_empty(&self) -> bool { | 160 | pub fn is_empty(&self) -> bool { |
108 | self.data.is_empty() | 161 | self.data.is_empty() |
109 | } | 162 | } |
163 | |||
164 | /// Allocates a new value on the arena, returning the value’s ID. | ||
165 | /// | ||
166 | /// ``` | ||
167 | /// let mut arena = la_arena::Arena::new(); | ||
168 | /// let id = arena.alloc(50); | ||
169 | /// | ||
170 | /// assert_eq!(arena[id], 50); | ||
171 | /// ``` | ||
110 | pub fn alloc(&mut self, value: T) -> Idx<T> { | 172 | pub fn alloc(&mut self, value: T) -> Idx<T> { |
111 | let id = RawId(self.data.len() as u32); | 173 | let id = RawId(self.data.len() as u32); |
112 | self.data.push(value); | 174 | self.data.push(value); |
113 | Idx::from_raw(id) | 175 | Idx::from_raw(id) |
114 | } | 176 | } |
177 | |||
178 | /// Returns an iterator over the arena’s elements. | ||
179 | /// | ||
180 | /// ``` | ||
181 | /// let mut arena = la_arena::Arena::new(); | ||
182 | /// let id1 = arena.alloc(20); | ||
183 | /// let id2 = arena.alloc(40); | ||
184 | /// let id3 = arena.alloc(60); | ||
185 | /// | ||
186 | /// let mut iterator = arena.iter(); | ||
187 | /// assert_eq!(iterator.next(), Some((id1, &20))); | ||
188 | /// assert_eq!(iterator.next(), Some((id2, &40))); | ||
189 | /// assert_eq!(iterator.next(), Some((id3, &60))); | ||
190 | /// ``` | ||
115 | pub fn iter( | 191 | pub fn iter( |
116 | &self, | 192 | &self, |
117 | ) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator { | 193 | ) -> impl Iterator<Item = (Idx<T>, &T)> + ExactSizeIterator + DoubleEndedIterator { |
118 | self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawId(idx as u32)), value)) | 194 | self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawId(idx as u32)), value)) |
119 | } | 195 | } |
196 | |||
197 | /// Reallocates the arena to make it take up as little space as possible. | ||
120 | pub fn shrink_to_fit(&mut self) { | 198 | pub fn shrink_to_fit(&mut self) { |
121 | self.data.shrink_to_fit(); | 199 | self.data.shrink_to_fit(); |
122 | } | 200 | } |
diff --git a/lib/arena/src/map.rs b/lib/arena/src/map.rs index 8a8063b7e..5ebaa9b82 100644 --- a/lib/arena/src/map.rs +++ b/lib/arena/src/map.rs | |||
@@ -10,6 +10,7 @@ pub struct ArenaMap<ID, V> { | |||
10 | } | 10 | } |
11 | 11 | ||
12 | impl<T, V> ArenaMap<Idx<T>, V> { | 12 | impl<T, V> ArenaMap<Idx<T>, V> { |
13 | /// Inserts a value associated with a given arena ID into the map. | ||
13 | pub fn insert(&mut self, id: Idx<T>, t: V) { | 14 | pub fn insert(&mut self, id: Idx<T>, t: V) { |
14 | let idx = Self::to_idx(id); | 15 | let idx = Self::to_idx(id); |
15 | 16 | ||
@@ -17,22 +18,27 @@ impl<T, V> ArenaMap<Idx<T>, V> { | |||
17 | self.v[idx] = Some(t); | 18 | self.v[idx] = Some(t); |
18 | } | 19 | } |
19 | 20 | ||
21 | /// Returns a reference to the value associated with the provided ID if it is present. | ||
20 | pub fn get(&self, id: Idx<T>) -> Option<&V> { | 22 | pub fn get(&self, id: Idx<T>) -> Option<&V> { |
21 | self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref()) | 23 | self.v.get(Self::to_idx(id)).and_then(|it| it.as_ref()) |
22 | } | 24 | } |
23 | 25 | ||
26 | /// Returns a mutable reference to the value associated with the provided ID if it is present. | ||
24 | pub fn get_mut(&mut self, id: Idx<T>) -> Option<&mut V> { | 27 | pub fn get_mut(&mut self, id: Idx<T>) -> Option<&mut V> { |
25 | self.v.get_mut(Self::to_idx(id)).and_then(|it| it.as_mut()) | 28 | self.v.get_mut(Self::to_idx(id)).and_then(|it| it.as_mut()) |
26 | } | 29 | } |
27 | 30 | ||
31 | /// Returns an iterator over the values in the map. | ||
28 | pub fn values(&self) -> impl Iterator<Item = &V> { | 32 | pub fn values(&self) -> impl Iterator<Item = &V> { |
29 | self.v.iter().filter_map(|o| o.as_ref()) | 33 | self.v.iter().filter_map(|o| o.as_ref()) |
30 | } | 34 | } |
31 | 35 | ||
36 | /// Returns an iterator over mutable references to the values in the map. | ||
32 | pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> { | 37 | pub fn values_mut(&mut self) -> impl Iterator<Item = &mut V> { |
33 | self.v.iter_mut().filter_map(|o| o.as_mut()) | 38 | self.v.iter_mut().filter_map(|o| o.as_mut()) |
34 | } | 39 | } |
35 | 40 | ||
41 | /// Returns an iterator over the arena IDs and values in the map. | ||
36 | pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> { | 42 | pub fn iter(&self) -> impl Iterator<Item = (Idx<T>, &V)> { |
37 | self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?))) | 43 | self.v.iter().enumerate().filter_map(|(idx, o)| Some((Self::from_idx(idx), o.as_ref()?))) |
38 | } | 44 | } |