use thiserror::Error;
use crate::loc::Diagnostic;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, Error)]
pub enum Error {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error(transparent)]
Json(#[from] serde_json::Error),
#[error(transparent)]
Diag(#[from] Diagnostic),
#[error("failed to read `{path}`: {source}")]
Read {
path: String,
#[source]
source: std::io::Error,
},
}
impl Error {
pub fn msg(s: impl Into<String>) -> Self {
Self::Diag(Diagnostic::at_file("<unknown>", s))
}
pub fn at(file: &str, source: &str, needles: &[&str], message: impl Into<String>) -> Self {
Self::Diag(Diagnostic::at(file, source, needles, message))
}
pub fn at_file(file: impl Into<String>, message: impl Into<String>) -> Self {
Self::Diag(Diagnostic::at_file(file, message))
}
#[must_use]
pub fn in_file(self, file: &str, source: &str) -> Self {
self.in_file_at(file, source, &[])
}
#[must_use]
pub fn in_file_at(self, file: &str, source: &str, needles: &[&str]) -> Self {
match self {
Self::Diag(d) => Self::Diag(d),
other => Self::Diag(Diagnostic::at(file, source, needles, other.to_string())),
}
}
pub fn read(path: impl Into<String>, source: std::io::Error) -> Self {
Self::Read {
path: path.into(),
source,
}
}
pub fn invalid_content(path: impl Into<String>, message: impl Into<String>) -> Self {
let path = path.into();
Self::Diag(Diagnostic::at_file(
path,
format!("invalid content: {}", message.into()),
))
}
}