diff options
Diffstat (limited to 'crates/ra_analysis/src/arena.rs')
-rw-r--r-- | crates/ra_analysis/src/arena.rs | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/arena.rs b/crates/ra_analysis/src/arena.rs new file mode 100644 index 000000000..98ed89274 --- /dev/null +++ b/crates/ra_analysis/src/arena.rs | |||
@@ -0,0 +1,96 @@ | |||
1 | //! A simple id-based arena, similar to https://github.com/fitzgen/id-arena. | ||
2 | //! We use our own version for more compact id's and to allow inherent impls | ||
3 | //! on Ids. | ||
4 | |||
5 | use std::{ | ||
6 | fmt, | ||
7 | ops::{Index, IndexMut}, | ||
8 | hash::{Hash, Hasher}, | ||
9 | marker::PhantomData, | ||
10 | }; | ||
11 | |||
12 | pub(crate) struct Id<T> { | ||
13 | idx: u32, | ||
14 | _ty: PhantomData<fn() -> T>, | ||
15 | } | ||
16 | |||
17 | impl<T> fmt::Debug for Id<T> { | ||
18 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
19 | f.debug_tuple("Id").field(&self.idx).finish() | ||
20 | } | ||
21 | } | ||
22 | impl<T> Copy for Id<T> {} | ||
23 | impl<T> Clone for Id<T> { | ||
24 | fn clone(&self) -> Id<T> { | ||
25 | *self | ||
26 | } | ||
27 | } | ||
28 | |||
29 | impl<T> PartialEq for Id<T> { | ||
30 | fn eq(&self, other: &Id<T>) -> bool { | ||
31 | self.idx == other.idx | ||
32 | } | ||
33 | } | ||
34 | |||
35 | impl<T> Eq for Id<T> {} | ||
36 | |||
37 | impl<T> Hash for Id<T> { | ||
38 | fn hash<H: Hasher>(&self, h: &mut H) { | ||
39 | self.idx.hash(h); | ||
40 | } | ||
41 | } | ||
42 | |||
43 | #[derive(Debug, PartialEq, Eq)] | ||
44 | pub(crate) struct Arena<T> { | ||
45 | data: Vec<T>, | ||
46 | } | ||
47 | |||
48 | impl<T> Default for Arena<T> { | ||
49 | fn default() -> Arena<T> { | ||
50 | Arena { data: Vec::new() } | ||
51 | } | ||
52 | } | ||
53 | |||
54 | impl<T> Arena<T> { | ||
55 | pub(crate) fn push(&mut self, value: T) -> Id<T> { | ||
56 | let id = self.data.len() as u32; | ||
57 | self.data.push(value); | ||
58 | Id { | ||
59 | idx: id as u32, | ||
60 | _ty: PhantomData, | ||
61 | } | ||
62 | } | ||
63 | |||
64 | pub(crate) fn keys<'a>(&'a self) -> impl Iterator<Item = Id<T>> + 'a { | ||
65 | (0..(self.data.len() as u32)).into_iter().map(|idx| Id { | ||
66 | idx, | ||
67 | _ty: PhantomData, | ||
68 | }) | ||
69 | } | ||
70 | |||
71 | pub(crate) fn items<'a>(&'a self) -> impl Iterator<Item = (Id<T>, &T)> + 'a { | ||
72 | self.data.iter().enumerate().map(|(idx, item)| { | ||
73 | let idx = idx as u32; | ||
74 | ( | ||
75 | Id { | ||
76 | idx, | ||
77 | _ty: PhantomData, | ||
78 | }, | ||
79 | item, | ||
80 | ) | ||
81 | }) | ||
82 | } | ||
83 | } | ||
84 | |||
85 | impl<T> Index<Id<T>> for Arena<T> { | ||
86 | type Output = T; | ||
87 | fn index(&self, id: Id<T>) -> &T { | ||
88 | &self.data[id.idx as usize] | ||
89 | } | ||
90 | } | ||
91 | |||
92 | impl<T> IndexMut<Id<T>> for Arena<T> { | ||
93 | fn index_mut(&mut self, id: Id<T>) -> &mut T { | ||
94 | &mut self.data[id.idx as usize] | ||
95 | } | ||
96 | } | ||