diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/vfs/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/vfs/src/path_interner.rs | 29 |
2 files changed, 17 insertions, 13 deletions
diff --git a/crates/vfs/Cargo.toml b/crates/vfs/Cargo.toml index c318a68f7..894944b18 100644 --- a/crates/vfs/Cargo.toml +++ b/crates/vfs/Cargo.toml | |||
@@ -14,3 +14,4 @@ rustc-hash = "1.0" | |||
14 | fst = "0.4" | 14 | fst = "0.4" |
15 | 15 | ||
16 | paths = { path = "../paths", version = "0.0.0" } | 16 | paths = { path = "../paths", version = "0.0.0" } |
17 | indexmap = "1.6.2" | ||
diff --git a/crates/vfs/src/path_interner.rs b/crates/vfs/src/path_interner.rs index 2189e5e25..6e049f0d4 100644 --- a/crates/vfs/src/path_interner.rs +++ b/crates/vfs/src/path_interner.rs | |||
@@ -1,15 +1,22 @@ | |||
1 | //! Maps paths to compact integer ids. We don't care about clearings paths which | 1 | //! Maps paths to compact integer ids. We don't care about clearings paths which |
2 | //! no longer exist -- the assumption is total size of paths we ever look at is | 2 | //! no longer exist -- the assumption is total size of paths we ever look at is |
3 | //! not too big. | 3 | //! not too big. |
4 | use rustc_hash::FxHashMap; | 4 | use std::hash::BuildHasherDefault; |
5 | |||
6 | use indexmap::IndexSet; | ||
7 | use rustc_hash::FxHasher; | ||
5 | 8 | ||
6 | use crate::{FileId, VfsPath}; | 9 | use crate::{FileId, VfsPath}; |
7 | 10 | ||
8 | /// Structure to map between [`VfsPath`] and [`FileId`]. | 11 | /// Structure to map between [`VfsPath`] and [`FileId`]. |
9 | #[derive(Default)] | ||
10 | pub(crate) struct PathInterner { | 12 | pub(crate) struct PathInterner { |
11 | map: FxHashMap<VfsPath, FileId>, | 13 | map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>, |
12 | vec: Vec<VfsPath>, | 14 | } |
15 | |||
16 | impl Default for PathInterner { | ||
17 | fn default() -> Self { | ||
18 | Self { map: IndexSet::default() } | ||
19 | } | ||
13 | } | 20 | } |
14 | 21 | ||
15 | impl PathInterner { | 22 | impl PathInterner { |
@@ -17,7 +24,7 @@ impl PathInterner { | |||
17 | /// | 24 | /// |
18 | /// If `path` does not exists in `self`, returns [`None`]. | 25 | /// If `path` does not exists in `self`, returns [`None`]. |
19 | pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { | 26 | pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { |
20 | self.map.get(path).copied() | 27 | self.map.get_index_of(path).map(|i| FileId(i as u32)) |
21 | } | 28 | } |
22 | 29 | ||
23 | /// Insert `path` in `self`. | 30 | /// Insert `path` in `self`. |
@@ -25,13 +32,9 @@ impl PathInterner { | |||
25 | /// - If `path` already exists in `self`, returns its associated id; | 32 | /// - If `path` already exists in `self`, returns its associated id; |
26 | /// - Else, returns a newly allocated id. | 33 | /// - Else, returns a newly allocated id. |
27 | pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { | 34 | pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { |
28 | if let Some(id) = self.get(&path) { | 35 | let (id, _added) = self.map.insert_full(path); |
29 | return id; | 36 | assert!(id < u32::MAX as usize); |
30 | } | 37 | FileId(id as u32) |
31 | let id = FileId(self.vec.len() as u32); | ||
32 | self.map.insert(path.clone(), id); | ||
33 | self.vec.push(path); | ||
34 | id | ||
35 | } | 38 | } |
36 | 39 | ||
37 | /// Returns the path corresponding to `id`. | 40 | /// Returns the path corresponding to `id`. |
@@ -40,6 +43,6 @@ impl PathInterner { | |||
40 | /// | 43 | /// |
41 | /// Panics if `id` does not exists in `self`. | 44 | /// Panics if `id` does not exists in `self`. |
42 | pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { | 45 | pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { |
43 | &self.vec[id.0 as usize] | 46 | self.map.get_index(id.0 as usize).unwrap() |
44 | } | 47 | } |
45 | } | 48 | } |