aboutsummaryrefslogtreecommitdiff
path: root/lib/arena
diff options
context:
space:
mode:
Diffstat (limited to 'lib/arena')
-rw-r--r--lib/arena/Cargo.toml10
-rw-r--r--lib/arena/src/lib.rs80
-rw-r--r--lib/arena/src/map.rs6
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]
2name = "la-arena" 2name = "la-arena"
3version = "0.1.0" 3version = "0.1.1"
4description = "Thy rope of sands..." 4description = "Simple index-based arena without deletion."
5license = "MIT OR Apache-2.0" 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"]
6authors = ["rust-analyzer developers"] 9authors = ["rust-analyzer developers"]
7edition = "2018" 10edition = "2018"
8
9[lib]
10doctest = 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
3use std::{ 5use std::{
4 fmt, 6 fmt,
@@ -11,6 +13,7 @@ use std::{
11mod map; 13mod map;
12pub use map::ArenaMap; 14pub 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)]
15pub struct RawId(u32); 18pub 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.
41pub struct Idx<T> { 45pub 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
76impl<T> Idx<T> { 80impl<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)]
86pub struct Arena<T> { 94pub 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
96impl<T> Arena<T> { 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 /// ```
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
12impl<T, V> ArenaMap<Idx<T>, V> { 12impl<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 }