use crate::Parser;
use core::{
fmt::{self, Display},
marker::PhantomData,
};
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct ParseError<'a> {
start_offset: u32,
end_offset: u32,
direction: ParseDirection,
kind: ErrorKind,
_lifetime: PhantomData<&'a [u8]>,
}
impl<'a> ParseError<'a> {
#[inline(always)]
pub const fn new(parser: Parser<'a>, kind: ErrorKind) -> Self {
Self {
start_offset: parser.start_offset,
end_offset: parser.start_offset + parser.bytes.len() as u32,
direction: parser.parse_direction,
kind,
_lifetime: PhantomData,
}
}
pub const fn copy(&self) -> Self {
Self {
start_offset: self.start_offset,
end_offset: self.end_offset,
direction: self.direction,
kind: self.kind,
_lifetime: PhantomData,
}
}
#[inline(always)]
pub const fn offset(&self) -> usize {
(match self.direction {
ParseDirection::FromStart => self.start_offset,
ParseDirection::FromEnd => self.end_offset,
}) as usize
}
pub const fn error_direction(&self) -> ParseDirection {
self.direction
}
pub const fn kind(&self) -> ErrorKind {
self.kind
}
#[track_caller]
pub const fn panic(&self) -> ! {
match self.kind {
ErrorKind::ParseInteger => match self.direction {
ParseDirection::FromStart => {
[][self.offset()]
}
ParseDirection::FromEnd => {
[][self.offset()]
}
},
ErrorKind::ParseBool => match self.direction {
ParseDirection::FromStart => {
[][self.offset()]
}
ParseDirection::FromEnd => {
[][self.offset()]
}
},
ErrorKind::Find => match self.direction {
ParseDirection::FromStart => {
[][self.offset()]
}
ParseDirection::FromEnd => {
[][self.offset()]
}
},
ErrorKind::Strip => match self.direction {
ParseDirection::FromStart => [][self.offset()],
ParseDirection::FromEnd => [][self.offset()],
},
ErrorKind::SkipByte => [][self.offset()],
ErrorKind::Other => match self.direction {
ParseDirection::FromStart => [][self.offset()],
ParseDirection::FromEnd => [][self.offset()],
},
}
}
}
impl<'a> Display for ParseError<'a> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self.direction {
ParseDirection::FromStart => "error from the start at the ",
ParseDirection::FromEnd => "error from the end at the ",
})?;
Display::fmt(&self.offset(), f)?;
f.write_str(" byte offset")?;
f.write_str(match self.kind {
ErrorKind::ParseInteger => " while parsing an integer",
ErrorKind::ParseBool => " while parsing a bool",
ErrorKind::Find => " while trying to find and skip a pattern",
ErrorKind::Strip => " while trying to strip a pattern",
ErrorKind::SkipByte => " while trying to skip a byte",
ErrorKind::Other => " (a parsing error)",
})
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum ParseDirection {
FromStart = 0,
FromEnd = 1,
}
#[non_exhaustive]
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum ErrorKind {
ParseInteger,
ParseBool,
Find,
Strip,
SkipByte,
Other,
}
pub type ParserResult<'a, E = ParseError<'a>> = Result<Parser<'a>, E>;
pub type ParseValueResult<'a, T, E = ParseError<'a>> = Result<(T, Parser<'a>), E>;