diff options
Diffstat (limited to 'crates/ra_analysis/src/loc2id.rs')
-rw-r--r-- | crates/ra_analysis/src/loc2id.rs | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/crates/ra_analysis/src/loc2id.rs b/crates/ra_analysis/src/loc2id.rs new file mode 100644 index 000000000..a53ce8348 --- /dev/null +++ b/crates/ra_analysis/src/loc2id.rs | |||
@@ -0,0 +1,64 @@ | |||
1 | use std::hash::Hash; | ||
2 | |||
3 | use rustc_hash::FxHashMap; | ||
4 | |||
5 | /// There are two principle ways to refer to things: | ||
6 | /// - by their locatinon (module in foo/bar/baz.rs at line 42) | ||
7 | /// - by their numeric id (module `ModuleId(42)`) | ||
8 | /// | ||
9 | /// The first one is more powerful (you can actually find the thing in question | ||
10 | /// by id), but the second one is so much more compact. | ||
11 | /// | ||
12 | /// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a | ||
13 | /// bidirectional mapping between positional and numeric ids, we can use compact | ||
14 | /// representation wich still allows us to get the actual item | ||
15 | #[derive(Debug)] | ||
16 | pub(crate) struct Loc2IdMap<L, ID> | ||
17 | where | ||
18 | ID: NumericId, | ||
19 | L: Clone + Eq + Hash, | ||
20 | { | ||
21 | loc2id: FxHashMap<L, ID>, | ||
22 | id2loc: FxHashMap<ID, L>, | ||
23 | } | ||
24 | |||
25 | impl<L, ID> Default for Loc2IdMap<L, ID> | ||
26 | where | ||
27 | ID: NumericId, | ||
28 | L: Clone + Eq + Hash, | ||
29 | { | ||
30 | fn default() -> Self { | ||
31 | Loc2IdMap { | ||
32 | loc2id: FxHashMap::default(), | ||
33 | id2loc: FxHashMap::default(), | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl<L, ID> Loc2IdMap<L, ID> | ||
39 | where | ||
40 | ID: NumericId, | ||
41 | L: Clone + Eq + Hash, | ||
42 | { | ||
43 | pub fn loc2id(&mut self, loc: &L) -> ID { | ||
44 | match self.loc2id.get(loc) { | ||
45 | Some(id) => return id.clone(), | ||
46 | None => (), | ||
47 | } | ||
48 | let id = self.loc2id.len(); | ||
49 | assert!(id < u32::max_value() as usize); | ||
50 | let id = ID::from_u32(id as u32); | ||
51 | self.loc2id.insert(loc.clone(), id.clone()); | ||
52 | self.id2loc.insert(id.clone(), loc.clone()); | ||
53 | id | ||
54 | } | ||
55 | |||
56 | pub fn id2loc(&self, id: &ID) -> L { | ||
57 | self.id2loc[id].clone() | ||
58 | } | ||
59 | } | ||
60 | |||
61 | pub(crate) trait NumericId: Clone + Eq + Hash { | ||
62 | fn from_u32(id: u32) -> Self; | ||
63 | fn to_u32(self) -> u32; | ||
64 | } | ||