//! Config parsing error use super::*; use std::{ io, path::PathBuf, }; //TODO: Embed info about the file, the line number, the expression, etc? /// Error type for parsing config errors #[derive(Debug)] pub enum Error { /// Internal IO error IO(io::Error), /// S-expression syntax error Syntax(sexp::Error), /// File not found, or was a directory NotFound(PathBuf), /// File contained invalid UTF-8 InvalidUtf8, /// Invalid or unexpected type TypeError{expected:LispType, got: LispType}, /// Expected a list with at least one element UnexpectedEmpty, /// Unknown definition string UnknownDefinition(String), /// Non-descript other error Unknown, } impl Error { /// Helper function for type errors #[inline] pub fn bad_type(expected: T, got: U) -> Self where T: Into, U: Into { Self::TypeError { expected: expected.into(), got: got.into() } } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { Some(match &self { Self::IO(io) => io, Self::Syntax(sy) => sy, _ => return None, }) } } impl std::fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::IO(io) => write!(f, "i/o error: {}", io), Self::Syntax(sy) => write!(f, "s-expression syntax error: {}", sy), Self::NotFound(path) => write!(f, "File not found: {:?}", path), Self::InvalidUtf8 => write!(f, "Invalid UTF8 decoded string or some such"), Self::TypeError{expected, got} => write!(f, "Type mismatch: Expected {}, got {}", expected, got), Self::UnexpectedEmpty => write!(f, "expected a non-empty list"), Self::UnknownDefinition(def) => write!(f, "unknown definition `{}'", def), _ => write!(f, "unknown error") } } } impl From for Error { fn from(from: io::Error) -> Self { Self::IO(from) } } impl From for Error { fn from(from: sexp::Error) -> Self { Self::Syntax(from) } } impl From> for Error { fn from(from: Box) -> Self { Self::Syntax(*from) } } impl From for Error { fn from(_: std::str::Utf8Error) -> Self { Self::InvalidUtf8 } }