| //! 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`]. |
| #[derive(Default)] |
| pub(crate) struct PathInterner { |
| map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>, |
| } |
| |
| 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() |
| } |
| } |