use std::{
fmt::Display,
path::{Path, PathBuf},
};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RawLoc {
pub filename: PathBuf,
pub lines: Vec<u32>, }
impl RawLoc {
pub fn new(filename: PathBuf, lines: Vec<u32>) -> Self {
Self { filename, lines }
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Loc(PathBuf, String);
impl Loc {
pub fn path(&self) -> &PathBuf {
&self.0
}
pub fn fn_name(&self) -> &str {
self.1.split("::").last().unwrap_or("")
}
pub fn full_fn_name(&self) -> &str {
&self.1
}
pub fn file_name(&self) -> String {
let split_str = self.1.split("::");
let mut split_as_vec = split_str.collect::<Vec<&str>>();
split_as_vec.pop();
split_as_vec.join("::")
}
pub fn read_source<S: FileSystem>(&self, fs: &S) -> Result<String, S::FSError> {
fs.read(&self.0)
}
pub fn write_source<S: FileSystem>(&self, fs: &S, str: &str) -> Result<(), S::FSError> {
fs.write(&self.0, str.as_bytes())
}
}
impl Display for Loc {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}:{}", self.0.to_str().unwrap_or(""), self.1)
}
}
impl From<(RawLoc, String)> for Loc {
fn from((loc, name): (RawLoc, String)) -> Self {
Loc(loc.filename, name)
}
}
pub trait FileSystem: Clone {
type FSError: std::fmt::Debug;
fn exists<P: AsRef<Path>>(&self, path: P) -> Result<bool, Self::FSError>;
fn read<P: AsRef<Path>>(&self, filename: P) -> Result<String, Self::FSError>;
fn write<P: AsRef<Path>, C: AsRef<[u8]>>(
&self,
filename: P,
contents: C,
) -> Result<(), Self::FSError>;
}