use std::fmt;
#[derive(Debug, Clone, PartialEq)]
pub enum ErrorKind {
InvalidIndentation,
TabInIndentation,
UnrecognizedLine,
UnexpectedLineType,
DuplicateKey,
InvalidIndentLevel,
UnterminatedInlineList,
UnterminatedInlineDict,
InvalidInlineCharacter,
TrailingContent,
UnsupportedType,
Io,
}
#[derive(Debug, Clone)]
pub struct Error {
pub kind: ErrorKind,
pub message: String,
pub lineno: Option<usize>,
pub colno: Option<usize>,
pub line: Option<String>,
}
impl Error {
pub fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
Error {
kind,
message: message.into(),
lineno: None,
colno: None,
line: None,
}
}
pub fn with_location(mut self, lineno: usize, colno: usize, line: impl Into<String>) -> Self {
self.lineno = Some(lineno);
self.colno = Some(colno);
self.line = Some(line.into());
self
}
pub fn with_lineno(mut self, lineno: usize) -> Self {
self.lineno = Some(lineno);
self
}
pub fn with_line(mut self, line: impl Into<String>) -> Self {
self.line = Some(line.into());
self
}
pub fn with_colno(mut self, colno: usize) -> Self {
self.colno = Some(colno);
self
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if let Some(lineno) = self.lineno {
write!(f, "line {}: {}", lineno, self.message)
} else {
write!(f, "{}", self.message)
}
}
}
impl std::error::Error for Error {}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Error::new(ErrorKind::Io, e.to_string())
}
}