aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_db/src/loc2id.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_db/src/loc2id.rs')
-rw-r--r--crates/ra_db/src/loc2id.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/crates/ra_db/src/loc2id.rs b/crates/ra_db/src/loc2id.rs
new file mode 100644
index 000000000..69ba43d0f
--- /dev/null
+++ b/crates/ra_db/src/loc2id.rs
@@ -0,0 +1,100 @@
1use parking_lot::Mutex;
2
3use std::hash::Hash;
4
5use rustc_hash::FxHashMap;
6
7/// There are two principle ways to refer to things:
8/// - by their locatinon (module in foo/bar/baz.rs at line 42)
9/// - by their numeric id (module `ModuleId(42)`)
10///
11/// The first one is more powerful (you can actually find the thing in question
12/// by id), but the second one is so much more compact.
13///
14/// `Loc2IdMap` allows us to have a cake an eat it as well: by maintaining a
15/// bidirectional mapping between positional and numeric ids, we can use compact
16/// representation wich still allows us to get the actual item
17#[derive(Debug)]
18struct Loc2IdMap<LOC, ID>
19where
20 ID: NumericId,
21 LOC: Clone + Eq + Hash,
22{
23 loc2id: FxHashMap<LOC, ID>,
24 id2loc: FxHashMap<ID, LOC>,
25}
26
27impl<LOC, ID> Default for Loc2IdMap<LOC, ID>
28where
29 ID: NumericId,
30 LOC: Clone + Eq + Hash,
31{
32 fn default() -> Self {
33 Loc2IdMap {
34 loc2id: FxHashMap::default(),
35 id2loc: FxHashMap::default(),
36 }
37 }
38}
39
40impl<LOC, ID> Loc2IdMap<LOC, ID>
41where
42 ID: NumericId,
43 LOC: Clone + Eq + Hash,
44{
45 pub fn loc2id(&mut self, loc: &LOC) -> ID {
46 match self.loc2id.get(loc) {
47 Some(id) => return id.clone(),
48 None => (),
49 }
50 let id = self.loc2id.len();
51 assert!(id < u32::max_value() as usize);
52 let id = ID::from_u32(id as u32);
53 self.loc2id.insert(loc.clone(), id.clone());
54 self.id2loc.insert(id.clone(), loc.clone());
55 id
56 }
57
58 pub fn id2loc(&self, id: ID) -> LOC {
59 self.id2loc[&id].clone()
60 }
61}
62
63pub trait NumericId: Clone + Eq + Hash {
64 fn from_u32(id: u32) -> Self;
65 fn to_u32(self) -> u32;
66}
67
68#[derive(Debug)]
69pub struct LocationIntener<LOC, ID>
70where
71 ID: NumericId,
72 LOC: Clone + Eq + Hash,
73{
74 map: Mutex<Loc2IdMap<LOC, ID>>,
75}
76
77impl<LOC, ID> Default for LocationIntener<LOC, ID>
78where
79 ID: NumericId,
80 LOC: Clone + Eq + Hash,
81{
82 fn default() -> Self {
83 LocationIntener {
84 map: Default::default(),
85 }
86 }
87}
88
89impl<LOC, ID> LocationIntener<LOC, ID>
90where
91 ID: NumericId,
92 LOC: Clone + Eq + Hash,
93{
94 pub fn loc2id(&self, loc: &LOC) -> ID {
95 self.map.lock().loc2id(loc)
96 }
97 pub fn id2loc(&self, id: ID) -> LOC {
98 self.map.lock().id2loc(id)
99 }
100}