#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
pub struct SourceId(pub(crate) u32);
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum SourceKind {
OneLiner,
Stdin,
File(String),
}
impl SourceKind {
pub fn display_name(&self) -> &str {
match self {
SourceKind::OneLiner => "<query>",
SourceKind::Stdin => "<stdin>",
SourceKind::File(path) => path,
}
}
}
#[derive(Clone, Debug)]
pub struct Source<'q> {
pub id: SourceId,
pub kind: &'q SourceKind,
pub content: &'q str,
}
impl<'q> Source<'q> {
pub fn as_str(&self) -> &'q str {
self.content
}
}
#[derive(Clone, Debug)]
struct SourceEntry {
kind: SourceKind,
content: String,
}
#[derive(Clone, Debug, Default)]
pub struct SourceMap {
entries: Vec<SourceEntry>,
}
impl SourceMap {
pub fn new() -> Self {
Self::default()
}
pub fn add_one_liner(&mut self, content: &str) -> SourceId {
self.push_entry(SourceKind::OneLiner, content)
}
pub fn add_stdin(&mut self, content: &str) -> SourceId {
self.push_entry(SourceKind::Stdin, content)
}
pub fn add_file(&mut self, path: &str, content: &str) -> SourceId {
self.push_entry(SourceKind::File(path.to_owned()), content)
}
pub fn one_liner(content: &str) -> Self {
let mut map = Self::new();
map.add_one_liner(content);
map
}
pub fn content(&self, id: SourceId) -> &str {
self.entries
.get(id.0 as usize)
.map(|e| e.content.as_str())
.expect("invalid SourceId")
}
pub fn kind(&self, id: SourceId) -> &SourceKind {
self.entries
.get(id.0 as usize)
.map(|e| &e.kind)
.expect("invalid SourceId")
}
pub fn path(&self, id: SourceId) -> Option<&str> {
let entry = self.entries.get(id.0 as usize).expect("invalid SourceId");
match &entry.kind {
SourceKind::File(path) => Some(path),
_ => None,
}
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn get(&self, id: SourceId) -> Source<'_> {
let entry = self.entries.get(id.0 as usize).expect("invalid SourceId");
Source {
id,
kind: &entry.kind,
content: &entry.content,
}
}
pub fn iter(&self) -> impl Iterator<Item = Source<'_>> {
self.entries.iter().enumerate().map(|(idx, entry)| Source {
id: SourceId(idx as u32),
kind: &entry.kind,
content: &entry.content,
})
}
fn push_entry(&mut self, kind: SourceKind, content: &str) -> SourceId {
let id = SourceId(self.entries.len() as u32);
self.entries.push(SourceEntry {
kind,
content: content.to_owned(),
});
id
}
}