use std::hash::{BuildHasherDefault, Hash};
use indexmap::IndexMap;
use reflexo::hash::FxHasher;
use super::FileId;
#[derive(Debug)]
pub(crate) struct PathInterner<P, Ext = ()> {
map: IndexMap<P, Ext, BuildHasherDefault<FxHasher>>,
}
impl<P, Ext> Default for PathInterner<P, Ext> {
fn default() -> Self {
Self {
map: IndexMap::default(),
}
}
}
impl<P: Hash + Eq, Ext> PathInterner<P, Ext> {
#[allow(dead_code)]
pub fn retain(&mut self, keep: impl FnMut(&P, &mut Ext) -> bool) {
self.map.retain(keep)
}
#[inline]
pub(crate) fn intern(&mut self, path: P, ext: Ext) -> (FileId, Option<&mut Ext>) {
let (id, _) = self.map.insert_full(path, ext);
assert!(id < u32::MAX as usize);
(FileId(id as u32), None)
}
#[allow(dead_code)]
pub(crate) fn lookup(&self, id: FileId) -> &P {
self.map.get_index(id.0 as usize).unwrap().0
}
}
#[cfg(test)]
mod tests {
use super::PathInterner;
use std::path::PathBuf;
#[test]
fn test_interner_path_buf() {
let mut interner = PathInterner::<PathBuf>::default();
let (id, ..) = interner.intern(PathBuf::from("foo"), ());
assert_eq!(interner.lookup(id), &PathBuf::from("foo"));
}
}