1use core::fmt;
2
3use annotate_snippets::{Level, Renderer, Snippet};
4use pest::{error::InputLocation, RuleType};
5
6pub struct FilterError<R> {
7 parsing_error: pest::error::Error<R>,
8}
9
10impl<R> fmt::Debug for FilterError<R>
11where
12 R: RuleType,
13{
14 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
15 let input = self.parsing_error.line();
16 let pos = match self.parsing_error.location {
17 InputLocation::Pos(pos) => pos..pos,
18 InputLocation::Span((start, end)) => start..end,
19 };
20
21 let message = Level::Error.title("failed to parse filter").snippet(
22 Snippet::source(input).annotation(Level::Error.span(pos).label("unexpected token")),
23 );
24
25 let renderer = Renderer::styled();
26 let rendered = renderer.render(message);
27
28 write!(f, "{}", rendered)
29 }
30}
31
32impl<R> fmt::Display for FilterError<R>
33where
34 R: RuleType,
35{
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 write!(f, "{:?}", self)
38 }
39}
40
41impl<R> std::error::Error for FilterError<R> where R: RuleType {}
42
43impl<R> From<pest::error::Error<R>> for Box<FilterError<R>>
44where
45 R: RuleType,
46{
47 fn from(value: pest::error::Error<R>) -> Self {
48 match value.variant {
49 pest::error::ErrorVariant::ParsingError {
50 positives: _,
51 negatives: _,
52 } => Box::new(FilterError {
53 parsing_error: value.clone(),
54 }),
55 _ => {
56 unimplemented!()
57 }
58 }
59 }
60}