1use std::fmt;
2
3#[derive(Debug, Clone, PartialEq)]
4pub enum ErrorKind {
5 InvalidIndentation,
7 TabInIndentation,
8 UnrecognizedLine,
10 UnexpectedLineType,
11 DuplicateKey,
12 InvalidIndentLevel,
13 UnterminatedInlineList,
15 UnterminatedInlineDict,
16 InvalidInlineCharacter,
17 TrailingContent,
18 UnsupportedType,
20 Io,
22}
23
24#[derive(Debug, Clone)]
26pub struct Error {
27 pub kind: ErrorKind,
28 pub message: String,
29 pub lineno: Option<usize>,
31 pub colno: Option<usize>,
33 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}