Skip to main content

nested_text/
error.rs

1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum ErrorKind {
5    // Lexer errors
6    InvalidIndentation,
7    TabInIndentation,
8    // Parser errors
9    UnrecognizedLine,
10    UnexpectedLineType,
11    DuplicateKey,
12    InvalidIndentLevel,
13    // Inline errors
14    UnterminatedInlineList,
15    UnterminatedInlineDict,
16    InvalidInlineCharacter,
17    TrailingContent,
18    // Dump errors
19    UnsupportedType,
20    // IO
21    Io,
22}
23
24/// Error type with location information matching the NestedText test suite format.
25#[derive(Debug, Clone)]
26pub struct Error {
27    pub kind: ErrorKind,
28    pub message: String,
29    /// 0-based line number where the error occurred.
30    pub lineno: Option<usize>,
31    /// 0-based column number where the error occurred.
32    pub colno: Option<usize>,
33    /// The source line that caused the error.
34    pub line: Option<String>,
35}
36
37impl Error {
38    pub fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
39        Error {
40            kind,
41            message: message.into(),
42            lineno: None,
43            colno: None,
44            line: None,
45        }
46    }
47
48    pub fn with_location(mut self, lineno: usize, colno: usize, line: impl Into<String>) -> Self {
49        self.lineno = Some(lineno);
50        self.colno = Some(colno);
51        self.line = Some(line.into());
52        self
53    }
54
55    pub fn with_lineno(mut self, lineno: usize) -> Self {
56        self.lineno = Some(lineno);
57        self
58    }
59
60    pub fn with_line(mut self, line: impl Into<String>) -> Self {
61        self.line = Some(line.into());
62        self
63    }
64
65    pub fn with_colno(mut self, colno: usize) -> Self {
66        self.colno = Some(colno);
67        self
68    }
69}
70
71impl fmt::Display for Error {
72    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
73        if let Some(lineno) = self.lineno {
74            write!(f, "line {}: {}", lineno, self.message)
75        } else {
76            write!(f, "{}", self.message)
77        }
78    }
79}
80
81impl std::error::Error for Error {}
82
83impl From<std::io::Error> for Error {
84    fn from(e: std::io::Error) -> Self {
85        Error::new(ErrorKind::Io, e.to_string())
86    }
87}