use std::collections::HashMap;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct FileId(usize);
#[derive(Debug, Clone)]
pub(super) struct FileInfo {
pub(super) path: PathBuf,
pub(super) source: String,
}
pub struct Files {
files: Vec<FileInfo>,
path_to_id: HashMap<PathBuf, FileId>,
}
impl Files {
pub fn new() -> Self {
Self {
files: Vec::new(),
path_to_id: HashMap::new(),
}
}
pub fn add(&mut self, path: impl AsRef<Path>, source: String) -> FileId {
let path = path.as_ref();
let path = if path.is_absolute() {
path.strip_prefix(std::env::current_dir().unwrap_or_else(|_| path.to_path_buf()))
.unwrap_or(path)
.to_path_buf()
} else {
path.to_path_buf()
};
if let Some(&id) = self.path_to_id.get(&path) {
return id;
}
let id = FileId(self.files.len());
let info = FileInfo {
path: path.clone(),
source,
};
self.files.push(info);
self.path_to_id.insert(path, id);
id
}
pub(super) fn get(&self, id: FileId) -> Option<&FileInfo> {
self.files.get(id.0)
}
}
impl Default for Files {
fn default() -> Self {
Self::new()
}
}