use std::fmt;
use value_trait::ValueType;
#[derive(Debug)]
pub enum ErrorType {
Unexpected(Option<ValueType>, Option<ValueType>),
InputTooLarge,
BadKeyType,
ExpectedArray,
ExpectedArrayComma,
ExpectedBoolean,
ExpectedEnum,
ExpectedFloat,
ExpectedInteger,
ExpectedMap,
ExpectedObjectColon,
ExpectedMapComma,
ExpectedMapEnd,
ExpectedNull,
ExpectedTrue,
ExpectedFalse,
ExpectedNumber,
ExpectedSigned,
ExpectedString,
ExpectedUnsigned,
InternalError(InternalError),
InvalidEscape,
InvalidExponent,
InvalidNumber,
InvalidUtf8,
InvalidUnicodeEscape,
InvalidUnicodeCodepoint,
KeyMustBeAString,
NoStructure,
Parser,
Eof,
Serde(String),
Syntax,
TrailingData,
UnexpectedCharacter,
UnterminatedString,
ExpectedArrayContent,
ExpectedObjectContent,
ExpectedObjectKey,
Overflow,
SimdUnsupported,
Io(std::io::Error),
}
#[derive(Clone, Debug, PartialEq)]
pub enum InternalError {
TapeError,
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Self {
Self::generic(ErrorType::Io(e))
}
}
#[cfg(not(tarpaulin_include))]
impl PartialEq for ErrorType {
#[must_use]
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Io(_), Self::Io(_))
| (Self::BadKeyType, Self::BadKeyType)
| (Self::ExpectedArray, Self::ExpectedArray)
| (Self::ExpectedArrayComma, Self::ExpectedArrayComma)
| (Self::ExpectedBoolean, Self::ExpectedBoolean)
| (Self::ExpectedTrue, Self::ExpectedTrue)
| (Self::ExpectedFalse, Self::ExpectedFalse)
| (Self::ExpectedEnum, Self::ExpectedEnum)
| (Self::ExpectedFloat, Self::ExpectedFloat)
| (Self::ExpectedInteger, Self::ExpectedInteger)
| (Self::ExpectedMap, Self::ExpectedMap)
| (Self::ExpectedObjectColon, Self::ExpectedObjectColon)
| (Self::ExpectedMapComma, Self::ExpectedMapComma)
| (Self::ExpectedMapEnd, Self::ExpectedMapEnd)
| (Self::ExpectedNull, Self::ExpectedNull)
| (Self::ExpectedNumber, Self::ExpectedNumber)
| (Self::ExpectedSigned, Self::ExpectedSigned)
| (Self::ExpectedString, Self::ExpectedString)
| (Self::ExpectedUnsigned, Self::ExpectedUnsigned)
| (Self::InvalidEscape, Self::InvalidEscape)
| (Self::InvalidExponent, Self::InvalidExponent)
| (Self::InvalidNumber, Self::InvalidNumber)
| (Self::InvalidUtf8, Self::InvalidUtf8)
| (Self::InvalidUnicodeEscape, Self::InvalidUnicodeEscape)
| (Self::InvalidUnicodeCodepoint, Self::InvalidUnicodeCodepoint)
| (Self::KeyMustBeAString, Self::KeyMustBeAString)
| (Self::NoStructure, Self::NoStructure)
| (Self::Parser, Self::Parser)
| (Self::Eof, Self::Eof)
| (Self::Syntax, Self::Syntax)
| (Self::TrailingData, Self::TrailingData)
| (Self::UnexpectedCharacter, Self::UnexpectedCharacter)
| (Self::UnterminatedString, Self::UnterminatedString)
| (Self::ExpectedArrayContent, Self::ExpectedArrayContent)
| (Self::ExpectedObjectContent, Self::ExpectedObjectContent)
| (Self::ExpectedObjectKey, Self::ExpectedObjectKey)
| (Self::Overflow, Self::Overflow) => true,
(Self::Serde(s1), Self::Serde(s2)) => s1 == s2,
(Self::InternalError(e1), Self::InternalError(e2)) => e1 == e2,
_ => false,
}
}
}
#[derive(Debug, PartialEq)]
pub struct Error {
index: usize,
character: Option<char>,
error: ErrorType,
}
impl Error {
pub(crate) fn new(index: usize, character: Option<char>, error: ErrorType) -> Self {
Self {
index,
character,
error,
}
}
pub(crate) fn new_c(index: usize, character: char, error: ErrorType) -> Self {
Self::new(index, Some(character), error)
}
#[must_use = "Error creation"]
pub fn generic(t: ErrorType) -> Self {
Self {
index: 0,
character: None,
error: t,
}
}
#[must_use]
pub fn index(&self) -> usize {
self.index
}
#[must_use]
pub fn character(&self) -> Option<char> {
self.character
}
#[must_use]
pub fn error(&self) -> &ErrorType {
&self.error
}
#[must_use]
pub fn is_io(&self) -> bool {
match &self.error {
ErrorType::Io(_) | ErrorType::InputTooLarge => true,
ErrorType::InternalError(e) if !matches!(e, crate::InternalError::TapeError) => true,
_ => false,
}
}
#[must_use]
pub fn is_eof(&self) -> bool {
matches!(self.error, ErrorType::Eof)
}
#[must_use]
pub fn is_data(&self) -> bool {
!(self.is_syntax() || self.is_eof() || self.is_io())
}
#[must_use]
pub fn is_syntax(&self) -> bool {
matches!(
self.error,
ErrorType::InternalError(crate::InternalError::TapeError) | ErrorType::BadKeyType |
ErrorType::ExpectedArrayComma |
ErrorType::ExpectedObjectColon |
ErrorType::ExpectedMapComma |
ErrorType::ExpectedMapEnd |
ErrorType::InvalidEscape |
ErrorType::InvalidExponent |
ErrorType::InvalidNumber |
ErrorType::InvalidUtf8 |
ErrorType::InvalidUnicodeEscape |
ErrorType::InvalidUnicodeCodepoint |
ErrorType::KeyMustBeAString |
ErrorType::NoStructure |
ErrorType::Parser |
ErrorType::Syntax |
ErrorType::TrailingData |
ErrorType::UnexpectedCharacter |
ErrorType::UnterminatedString |
ErrorType::ExpectedArrayContent |
ErrorType::ExpectedObjectContent |
ErrorType::ExpectedObjectKey |
ErrorType::Overflow |
ErrorType::SimdUnsupported
)
}
}
impl std::error::Error for Error {}
#[cfg(not(tarpaulin_include))]
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(c) = self.character {
write!(f, "{:?} at character {} ('{c}')", self.error, self.index)
} else {
write!(f, "{:?} at character {}", self.error, self.index)
}
}
}
#[cfg(not(tarpaulin_include))]
impl From<Error> for std::io::Error {
fn from(e: Error) -> Self {
std::io::Error::new(std::io::ErrorKind::InvalidData, e)
}
}