diskplan_schema/text/
error.rs1use std::fmt::Display;
2
3#[derive(Debug, PartialEq)]
5pub struct ParseError<'a> {
6 error: String,
7 text: &'a str,
8 span: &'a str,
9 next: Option<Box<ParseError<'a>>>,
10}
11
12impl Display for ParseError<'_> {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 let lineno = self.line_number();
15 let line = self.text.lines().nth(lineno - 1).unwrap_or("<EOF>");
16 let column = self.span.as_ptr() as usize - line.as_ptr() as usize;
17 writeln!(f, "Error: {}", self.error)?;
18 writeln!(f, " |")?;
19 writeln!(f, "{lineno:4} | {line}")?;
20 if column == 0 {
21 writeln!(f, " |")?;
22 } else {
23 writeln!(f, " | {0:1$}^", "", column)?;
24 }
25 if let Some(next) = &self.next {
26 write!(f, "{next}")?;
27 }
28 Ok(())
29 }
30}
31
32impl std::error::Error for ParseError<'_> {}
33
34impl<'a> ParseError<'a> {
35 pub fn new(
37 error: String,
38 text: &'a str,
39 span: &'a str,
40 next: Option<Box<ParseError<'a>>>,
41 ) -> ParseError<'a> {
42 ParseError {
43 error,
44 text,
45 span,
46 next,
47 }
48 }
49
50 pub fn line_number(&self) -> usize {
52 let pos = self.span.as_ptr() as usize - self.text.as_ptr() as usize;
53 self.text[..pos].chars().filter(|&c| c == '\n').count() + 1
54 }
55}
56
57impl<'a, 'b> IntoIterator for &'b ParseError<'a> {
58 type IntoIter = ParseErrorIter<'a, 'b>;
59 type Item = &'b ParseError<'a>;
60
61 fn into_iter(self) -> Self::IntoIter {
62 ParseErrorIter { err: Some(self) }
63 }
64}
65
66pub struct ParseErrorIter<'a, 'b> {
67 err: Option<&'b ParseError<'a>>,
68}
69
70impl<'a, 'b> Iterator for ParseErrorIter<'a, 'b> {
71 type Item = &'b ParseError<'a>;
72
73 fn next(&mut self) -> Option<Self::Item> {
74 let cur = self.err;
75 if let Some(err) = cur {
76 self.err = err.next.as_deref();
77 }
78 cur
79 }
80}