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>>;