1use std::error::Error as StdError;
2use std::fmt;
3
4#[derive(Clone, Debug, PartialEq, Eq)]
9#[non_exhaustive]
10pub struct ParseError {
11 line: usize,
12 column: usize,
13 message: String,
14 source_line: Option<String>,
15}
16
17impl ParseError {
18 pub(crate) fn new(line: usize, column: usize, message: impl Into<String>, source_line: Option<String>) -> Self {
19 Self {
20 line,
21 column,
22 message: message.into(),
23 source_line,
24 }
25 }
26
27 pub fn line(&self) -> usize { self.line }
29 pub fn column(&self) -> usize { self.column }
31 pub fn message(&self) -> &str { &self.message }
33 pub fn source_line(&self) -> Option<&str> { self.source_line.as_deref() }
35}
36
37impl fmt::Display for ParseError {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(f, "line {}, column {}: {}", self.line, self.column, self.message)?;
40 if let Some(src) = &self.source_line {
41 write!(f, "\n {}\n {:>width$}", src, "^", width = self.column)?;
42 }
43 Ok(())
44 }
45}
46
47impl StdError for ParseError {}
48
49#[non_exhaustive]
51#[derive(Debug)]
52pub enum Error {
53 Parse(ParseError),
55 Json(serde_json::Error),
57 Render(String),
59}
60
61impl fmt::Display for Error {
62 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
63 match self {
64 Self::Parse(error) => write!(f, "{error}"),
65 Self::Json(error) => write!(f, "{error}"),
66 Self::Render(message) => write!(f, "{message}"),
67 }
68 }
69}
70
71impl StdError for Error {}
72
73impl From<ParseError> for Error {
74 fn from(error: ParseError) -> Self {
75 Self::Parse(error)
76 }
77}
78
79impl From<serde_json::Error> for Error {
80 fn from(error: serde_json::Error) -> Self {
81 Self::Json(error)
82 }
83}
84
85pub type Result<T, E = Error> = std::result::Result<T, E>;