60 lines
1.3 KiB
Rust
60 lines
1.3 KiB
Rust
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
pub struct SourceFile {
|
|
pub id: usize,
|
|
pub path: PathBuf,
|
|
pub source: Arc<str>,
|
|
}
|
|
|
|
pub struct FileManager {
|
|
files: Vec<SourceFile>,
|
|
}
|
|
|
|
impl FileManager {
|
|
pub fn new() -> Self {
|
|
Self { files: Vec::new() }
|
|
}
|
|
|
|
pub fn add(&mut self, path: PathBuf, source: String) -> usize {
|
|
let id = self.files.len();
|
|
self.files.push(SourceFile {
|
|
id,
|
|
path,
|
|
source: Arc::from(source),
|
|
});
|
|
id
|
|
}
|
|
|
|
pub fn get_file(&self, id: usize) -> Option<&SourceFile> {
|
|
self.files.get(id)
|
|
}
|
|
|
|
pub fn get_path(&self, id: usize) -> Option<PathBuf> {
|
|
self.files.get(id).map(|f| f.path.clone())
|
|
}
|
|
|
|
pub fn lookup_pos(&self, file_id: usize, pos: u32) -> (usize, usize) {
|
|
let file = if let Some(f) = self.files.get(file_id) {
|
|
f
|
|
} else {
|
|
return (0, 0);
|
|
};
|
|
|
|
let mut line = 1;
|
|
let mut col = 1;
|
|
for (i, c) in file.source.char_indices() {
|
|
if i as u32 == pos {
|
|
break;
|
|
}
|
|
if c == '\n' {
|
|
line += 1;
|
|
col = 1;
|
|
} else {
|
|
col += 1;
|
|
}
|
|
}
|
|
(line, col)
|
|
}
|
|
}
|