amarok_syntax/
source_map.rs1use std::path::{Path, PathBuf};
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub struct FileId(pub u32);
9
10impl FileId {
11 pub const DUMMY: FileId = FileId(u32::MAX);
12
13 #[must_use]
14 pub fn is_dummy(self) -> bool {
15 self == FileId::DUMMY
16 }
17}
18
19#[derive(Debug, Clone)]
21pub struct SourceFile {
22 pub path: PathBuf,
23 pub source: String,
24}
25
26#[derive(Debug, Default, Clone)]
31pub struct SourceMap {
32 files: Vec<SourceFile>,
33}
34
35impl SourceMap {
36 #[must_use]
37 pub fn new() -> Self {
38 Self { files: Vec::new() }
39 }
40
41 pub fn add_file(&mut self, path: impl Into<PathBuf>, source: impl Into<String>) -> FileId {
47 let id = FileId(u32::try_from(self.files.len()).expect("too many source files"));
48 self.files.push(SourceFile {
49 path: path.into(),
50 source: source.into(),
51 });
52 id
53 }
54
55 #[must_use]
56 pub fn get(&self, file_id: FileId) -> Option<&SourceFile> {
57 if file_id.is_dummy() {
58 return None;
59 }
60 self.files.get(file_id.0 as usize)
61 }
62
63 #[must_use]
64 pub fn path_of(&self, file_id: FileId) -> Option<&Path> {
65 self.get(file_id).map(|f| f.path.as_path())
66 }
67
68 #[must_use]
69 pub fn source_of(&self, file_id: FileId) -> Option<&str> {
70 self.get(file_id).map(|f| f.source.as_str())
71 }
72}