use core::fmt;
pub type Result<T> = core::result::Result<T, Error>;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum ErrorKind {
Eof,
InvalidAdditionalInfo,
UnexpectedType,
UnexpectedBreak,
InvalidUtf8,
IntegerOverflow,
DepthLimit,
CollectionLimit,
TrailingData,
NonDeterministic,
DuplicateKey,
OutputTooSmall,
#[cfg(feature = "std")]
Io,
Message,
}
#[cfg_attr(not(feature = "std"), derive(Clone, Copy, Eq, PartialEq))]
#[derive(Debug)]
pub struct Error {
kind: ErrorKind,
offset: usize,
item: Option<usize>,
#[cfg(feature = "std")]
io: Option<std::io::Error>,
}
impl Error {
pub const fn new(kind: ErrorKind, offset: usize) -> Self {
Self {
kind,
offset,
item: None,
#[cfg(feature = "std")]
io: None,
}
}
pub const fn kind(&self) -> ErrorKind {
self.kind
}
pub const fn offset(&self) -> usize {
self.offset
}
pub const fn item_index(&self) -> Option<usize> {
self.item
}
#[cfg(feature = "std")]
pub fn io_error(&self) -> Option<&std::io::Error> {
self.io.as_ref()
}
#[cfg(feature = "std")]
pub(crate) fn from_io(error: std::io::Error, offset: usize) -> Self {
Self {
kind: ErrorKind::Io,
offset,
item: None,
io: Some(error),
}
}
pub(crate) const fn with_item(mut self, item: usize) -> Self {
self.item = Some(item);
self
}
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(feature = "std")]
if let Some(error) = &self.io {
write!(f, "I/O error at byte {}: {error}", self.offset)?;
} else {
write!(f, "{:?} at byte {}", self.kind, self.offset)?;
}
#[cfg(not(feature = "std"))]
write!(f, "{:?} at byte {}", self.kind, self.offset)?;
if let Some(item) = self.item {
write!(f, " (sequence item {item})")?;
}
Ok(())
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
self.io
.as_ref()
.map(|error| error as &(dyn std::error::Error + 'static))
}
}