use crate::base::FileId;
use indexmap::IndexMap;
use std::sync::Arc;
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct SourceRoot {
files: IndexMap<FileId, Arc<str>>,
}
impl SourceRoot {
pub fn new() -> Self {
Self::default()
}
pub fn insert(&mut self, file: FileId, path: impl Into<Arc<str>>) {
self.files.insert(file, path.into());
}
pub fn remove(&mut self, file: FileId) -> Option<Arc<str>> {
self.files.swap_remove(&file)
}
pub fn path(&self, file: FileId) -> Option<&str> {
self.files.get(&file).map(|s| s.as_ref())
}
pub fn contains(&self, file: FileId) -> bool {
self.files.contains_key(&file)
}
pub fn iter(&self) -> impl Iterator<Item = (FileId, &str)> + '_ {
self.files.iter().map(|(&id, path)| (id, path.as_ref()))
}
pub fn len(&self) -> usize {
self.files.len()
}
pub fn is_empty(&self) -> bool {
self.files.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_source_root_basic() {
let mut root = SourceRoot::new();
let file1 = FileId::new(0);
let file2 = FileId::new(1);
root.insert(file1, "/path/to/a.sysml");
root.insert(file2, "/path/to/b.sysml");
assert_eq!(root.len(), 2);
assert!(root.contains(file1));
assert_eq!(root.path(file1), Some("/path/to/a.sysml"));
}
#[test]
fn test_source_root_remove() {
let mut root = SourceRoot::new();
let file = FileId::new(0);
root.insert(file, "/path/to/a.sysml");
assert!(root.contains(file));
root.remove(file);
assert!(!root.contains(file));
}
}