diff options
Diffstat (limited to 'src/tools/rust-analyzer/crates/vfs/src/path_interner.rs')
-rw-r--r-- | src/tools/rust-analyzer/crates/vfs/src/path_interner.rs | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/src/tools/rust-analyzer/crates/vfs/src/path_interner.rs b/src/tools/rust-analyzer/crates/vfs/src/path_interner.rs new file mode 100644 index 000000000..6e049f0d4 --- /dev/null +++ b/src/tools/rust-analyzer/crates/vfs/src/path_interner.rs @@ -0,0 +1,48 @@ +//! Maps paths to compact integer ids. We don't care about clearings paths which +//! no longer exist -- the assumption is total size of paths we ever look at is +//! not too big. +use std::hash::BuildHasherDefault; + +use indexmap::IndexSet; +use rustc_hash::FxHasher; + +use crate::{FileId, VfsPath}; + +/// Structure to map between [`VfsPath`] and [`FileId`]. +pub(crate) struct PathInterner { + map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>, +} + +impl Default for PathInterner { + fn default() -> Self { + Self { map: IndexSet::default() } + } +} + +impl PathInterner { + /// Get the id corresponding to `path`. + /// + /// If `path` does not exists in `self`, returns [`None`]. + pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { + self.map.get_index_of(path).map(|i| FileId(i as u32)) + } + + /// Insert `path` in `self`. + /// + /// - If `path` already exists in `self`, returns its associated id; + /// - Else, returns a newly allocated id. + pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { + let (id, _added) = self.map.insert_full(path); + assert!(id < u32::MAX as usize); + FileId(id as u32) + } + + /// Returns the path corresponding to `id`. + /// + /// # Panics + /// + /// Panics if `id` does not exists in `self`. + pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { + self.map.get_index(id.0 as usize).unwrap() + } +} |