Skip to main content

mir_codebase/
file_id.rs

1use rustc_hash::FxHashMap;
2
3/// Stable numeric identity for a source file within one analysis session.
4/// Assigned when the file is first registered; never reused within that session.
5/// Small, `Copy`, and cheap to hash — used as HashMap keys in hot-path structures
6/// (cache entries, reverse-dep graph) instead of heap-allocated path strings.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
8pub struct FileId(u32);
9
10/// Bidirectional mapping between file paths and stable [`FileId`]s.
11///
12/// IDs are assigned sequentially on first contact.  The mapping is append-only
13/// within a session; IDs are never recycled.
14#[derive(Debug, Default)]
15pub struct FileIdMap {
16    path_to_id: FxHashMap<Box<str>, FileId>,
17    id_to_path: Vec<Box<str>>,
18}
19
20impl FileIdMap {
21    pub fn new() -> Self {
22        Self::default()
23    }
24
25    /// Return the [`FileId`] for `path`, assigning a fresh one if not yet seen.
26    pub fn assign_or_get(&mut self, path: &str) -> FileId {
27        if let Some(&id) = self.path_to_id.get(path) {
28            return id;
29        }
30        let id = FileId(self.id_to_path.len() as u32);
31        let key: Box<str> = Box::from(path);
32        self.id_to_path.push(key.clone());
33        self.path_to_id.insert(key, id);
34        id
35    }
36
37    /// Look up the [`FileId`] for `path` without assigning a new one.
38    pub fn get(&self, path: &str) -> Option<FileId> {
39        self.path_to_id.get(path).copied()
40    }
41
42    /// Resolve a [`FileId`] back to its path string.
43    pub fn path(&self, id: FileId) -> Option<&str> {
44        self.id_to_path.get(id.0 as usize).map(|s| s.as_ref())
45    }
46
47    pub fn len(&self) -> usize {
48        self.id_to_path.len()
49    }
50
51    pub fn is_empty(&self) -> bool {
52        self.id_to_path.is_empty()
53    }
54
55    /// Iterate all `(FileId, path)` pairs in assignment order.
56    pub fn iter(&self) -> impl Iterator<Item = (FileId, &str)> {
57        self.id_to_path
58            .iter()
59            .enumerate()
60            .map(|(i, p)| (FileId(i as u32), p.as_ref()))
61    }
62}