vimwiki_core/lang/parsers/
errors.rs1use super::Span;
2use nom::error::{ContextError, ErrorKind, FromExternalError, ParseError};
3use std::{borrow::Cow, fmt};
4
5#[derive(Clone, Debug, Default, Eq, PartialEq)]
7pub struct LangParserError<'a> {
8 ctx: Cow<'a, str>,
9 input: Span<'a>,
10 next: Option<Box<Self>>,
11}
12
13impl<'a> From<nom::Err<LangParserError<'a>>> for LangParserError<'a> {
14 fn from(nom_err: nom::Err<LangParserError<'a>>) -> Self {
15 match nom_err {
16 nom::Err::Error(x) | nom::Err::Failure(x) => x,
17 nom::Err::Incomplete(_) => {
18 Self::from_ctx(&Span::default(), "Incomplete")
19 }
20 }
21 }
22}
23
24impl<'a> fmt::Display for LangParserError<'a> {
25 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26 writeln!(
29 f,
30 "{}: Line {}, Column {}",
31 self.ctx,
32 self.input.line(),
33 self.input.column()
34 )?;
35
36 writeln!(
39 f,
40 "{}",
41 &self
42 .input
43 .as_unsafe_remaining_str()
44 .lines()
45 .next()
46 .unwrap_or_default()
47 .chars()
48 .take(100)
49 .collect::<String>()
50 )?;
51
52 if let Some(next) = self.next.as_ref() {
53 next.fmt(f)?;
54 }
55
56 Ok(())
57 }
58}
59
60impl<'a> std::error::Error for LangParserError<'a> {}
61
62impl<'a> LangParserError<'a> {
63 pub fn unsupported() -> Self {
64 Self {
65 ctx: Cow::from("Unsupported"),
66 input: Span::from(""),
67 next: None,
68 }
69 }
70
71 pub fn from_ctx(input: &Span<'a>, ctx: &'static str) -> Self {
72 Self {
73 ctx: Cow::from(ctx),
74 input: *input,
75 next: None,
76 }
77 }
78}
79
80impl<'a, E> FromExternalError<Span<'a>, E> for LangParserError<'a> {
81 fn from_external_error(input: Span<'a>, kind: ErrorKind, _e: E) -> Self {
82 Self::from_error_kind(input, kind)
84 }
85}
86
87impl<'a> ParseError<Span<'a>> for LangParserError<'a> {
88 fn from_error_kind(input: Span<'a>, kind: ErrorKind) -> Self {
89 Self {
90 ctx: Cow::from(kind.description().to_string()),
91 input,
92 next: None,
93 }
94 }
95
96 fn append(input: Span<'a>, kind: ErrorKind, other: Self) -> Self {
97 let mut e = Self::from_error_kind(input, kind);
98 e.next = Some(Box::new(other));
99 e
100 }
101
102 fn from_char(input: Span<'a>, c: char) -> Self {
103 Self {
104 ctx: Cow::from(format!("Char {}", c)),
105 input,
106 next: None,
107 }
108 }
109
110 fn or(self, other: Self) -> Self {
111 if self.input.start_offset() > other.input.start_offset() {
113 self
114 } else {
115 other
116 }
117 }
118}
119
120impl<'a> ContextError<Span<'a>> for LangParserError<'a> {
121 fn add_context(input: Span<'a>, ctx: &'static str, other: Self) -> Self {
122 Self {
123 ctx: Cow::from(ctx),
124 input,
125 next: Some(Box::new(other)),
126 }
127 }
128}