sexprs_parser/
errors.rs

1use std::fmt::{Debug, Display, Formatter};
2
3pub use sexprs_formatter::Error as FormatterError;
4pub use sexprs_util::{color, with_caller, Caller, Traceback};
5
6use crate::Span;
7
8#[derive(Clone, PartialEq, Eq)]
9pub struct Error<'a> {
10    message: String,
11    info: Option<Span<'a>>,
12    callers: Vec<Caller>,
13}
14impl<'a> Error<'a> {
15    pub fn new<T: Display>(message: T, info: Option<Span<'a>>) -> Self {
16        let message = message.to_string();
17        Error {
18            message: message,
19            info,
20            callers: Vec::new(),
21        }
22    }
23}
24impl std::error::Error for Error<'_> {}
25impl<'a> Traceback for Error<'a> {
26    fn message(&self) -> String {
27        self.message.to_string()
28    }
29
30    fn with(&self, caller: Caller) -> Self {
31        let mut error = self.clone();
32        error.callers.insert(0, caller);
33        error
34    }
35
36    fn callers(&self) -> Vec<Caller> {
37        self.callers.to_vec()
38    }
39}
40impl<'a> Display for Error<'a> {
41    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
42        write!(
43            f,
44            "{}",
45            [
46                color::reset(""),
47                if let Some(info) = &self.info {
48                    color::bg(info.highlight_input(4), 198)
49                } else {
50                    String::new()
51                },
52                color::fg(format!("\n\rreason: {}", self.highlight_message()), 242),
53            ]
54            .join("")
55        )
56    }
57}
58impl<'a> Debug for Error<'a> {
59    fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
60        write!(
61            f,
62            "{}",
63            [
64                color::reset(""),
65                color::fg(format!("in source:\n{}", self.to_string()), 202),
66                if self.callers.is_empty() {
67                    String::new()
68                } else {
69                    [
70                        color::reset("\n\n"),
71                        color::fg(format!("Stacktrace:\n{}\n", self.callers_to_string(4)), 220),
72                    ]
73                    .join("")
74                }
75            ]
76            .join("")
77        )
78    }
79}
80impl<'a> From<FormatterError> for Error<'a> {
81    fn from(e: FormatterError) -> Error<'a> {
82        Error::new(e.to_string(), None)
83    }
84}
85pub type Result<'a, T> = std::result::Result<T, Error<'a>>;