vfs/
path_interner.rs

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
3//! not too big.
4use std::hash::BuildHasherDefault;
5
6use indexmap::IndexSet;
7use rustc_hash::FxHasher;
8
9use crate::{FileId, VfsPath};
10
11/// Structure to map between [`VfsPath`] and [`FileId`].
12#[derive(Default)]
13pub(crate) struct PathInterner {
14    map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>,
15}
16
17impl PathInterner {
18    /// Get the id corresponding to `path`.
19    ///
20    /// If `path` does not exists in `self`, returns [`None`].
21    pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> {
22        self.map.get_index_of(path).map(|i| FileId(i as u32))
23    }
24
25    /// Insert `path` in `self`.
26    ///
27    /// - If `path` already exists in `self`, returns its associated id;
28    /// - Else, returns a newly allocated id.
29    pub(crate) fn intern(&mut self, path: VfsPath) -> FileId {
30        let (id, _added) = self.map.insert_full(path);
31        assert!(id < FileId::MAX as usize);
32        FileId(id as u32)
33    }
34
35    /// Returns the path corresponding to `id`.
36    ///
37    /// # Panics
38    ///
39    /// Panics if `id` does not exists in `self`.
40    pub(crate) fn lookup(&self, id: FileId) -> &VfsPath {
41        self.map.get_index(id.0 as usize).unwrap()
42    }
43}