use std::error::Error as StdError;
use std::fmt;
#[derive(Clone, Debug, PartialEq, Eq)]
#[non_exhaustive]
pub struct ParseError {
line: usize,
column: usize,
message: String,
source_line: Option<String>,
}
impl ParseError {
pub(crate) fn new(line: usize, column: usize, message: impl Into<String>, source_line: Option<String>) -> Self {
Self {
line,
column,
message: message.into(),
source_line,
}
}
pub fn line(&self) -> usize { self.line }
pub fn column(&self) -> usize { self.column }
pub fn message(&self) -> &str { &self.message }
pub fn source_line(&self) -> Option<&str> { self.source_line.as_deref() }
}
impl fmt::Display for ParseError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "line {}, column {}: {}", self.line, self.column, self.message)?;
if let Some(src) = &self.source_line {
write!(f, "\n {}\n {:>width$}", src, "^", width = self.column)?;
}
Ok(())
}
}
impl StdError for ParseError {}
#[non_exhaustive]
#[derive(Debug)]
pub enum Error {
Parse(ParseError),
Json(serde_json::Error),
Render(String),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Parse(error) => write!(f, "{error}"),
Self::Json(error) => write!(f, "{error}"),
Self::Render(message) => write!(f, "{message}"),
}
}
}
impl StdError for Error {}
impl From<ParseError> for Error {
fn from(error: ParseError) -> Self {
Self::Parse(error)
}
}
impl From<serde_json::Error> for Error {
fn from(error: serde_json::Error) -> Self {
Self::Json(error)
}
}
pub type Result<T, E = Error> = std::result::Result<T, E>;