use crate::position::Position;
use alloc::boxed::Box;
use alloc::string::{String, ToString};
use core::error::Error as CoreError;
use core::fmt;
use serde_core::de;
pub type Result<T> = ::core::result::Result<T, Error>;
pub struct Error(Box<ErrorImpl>);
pub(crate) struct ErrorImpl {
code: ErrorCode,
position: Position,
}
pub(crate) enum ErrorCode {
ExpectedEq,
InvalidUtf8,
Message(String),
InvalidBool,
InvalidInt,
InvalidFloat,
InvalidChar,
}
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum ErrorKind {
Syntax,
Semantic,
}
impl Error {
#[must_use]
pub(crate) fn new(code: ErrorCode, position: Position) -> Self {
Self(Box::new(ErrorImpl { code, position }))
}
#[inline]
#[must_use]
pub(crate) fn with_position(mut self, position: Position) -> Self {
self.0.position = position;
self
}
#[inline]
#[must_use]
pub fn kind(&self) -> ErrorKind {
self.0.code.kind()
}
#[inline]
#[must_use]
pub(crate) fn position(&self) -> Position {
self.0.position
}
#[inline]
#[must_use]
pub fn line(&self) -> usize {
self.0.position.line
}
#[inline]
#[must_use]
pub fn column(&self) -> usize {
self.0.position.column
}
}
impl de::Error for Error {
fn custom<T>(message: T) -> Self
where
T: fmt::Display,
{
Self(Box::new(ErrorImpl {
code: ErrorCode::Message(message.to_string()),
position: Position::default(),
}))
}
}
impl CoreError for Error {
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"Error({:?}, line: {}, column: {})",
self.0.code.to_string(),
self.0.position.line,
self.0.position.column,
)
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{} at line {} column {}",
self.0.code, self.0.position.line, self.0.position.column,
)
}
}
impl ErrorCode {
#[must_use]
fn kind(&self) -> ErrorKind {
#[allow(clippy::match_same_arms)]
match self {
Self::Message(_) => ErrorKind::Syntax,
Self::ExpectedEq => ErrorKind::Syntax,
Self::InvalidUtf8 => ErrorKind::Semantic,
Self::InvalidBool => ErrorKind::Semantic,
Self::InvalidInt => ErrorKind::Semantic,
Self::InvalidFloat => ErrorKind::Semantic,
Self::InvalidChar => ErrorKind::Semantic,
}
}
}
impl fmt::Display for ErrorCode {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorCode::Message(message) => f.write_str(message),
ErrorCode::ExpectedEq => f.write_str("expected equal sign"),
ErrorCode::InvalidUtf8 => f.write_str("invalid UTF-8"),
ErrorCode::InvalidBool => f.write_str("invalid bool"),
ErrorCode::InvalidInt => f.write_str("invalid int"),
ErrorCode::InvalidFloat => f.write_str("invalid float"),
ErrorCode::InvalidChar => f.write_str("invalid char"),
}
}
}