use serde::{de, ser};
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::{
boxed::Box,
format,
string::{String, ToString},
};
#[cfg(feature = "std")]
use std::{
boxed::Box,
error, format,
string::{String, ToString},
};
use core::{
fmt::{self, Display},
result,
};
pub type Result<T> = result::Result<T, Error>;
pub struct Error {
inner: Box<ErrorImpl>,
}
impl Error {
#[must_use]
#[inline]
pub fn new(kind: ErrorKind, byte_offset: usize) -> Self {
Self {
inner: Box::new(ErrorImpl { kind, byte_offset }),
}
}
#[must_use]
#[inline]
pub(crate) fn with_kind(kind: ErrorKind) -> Self {
Self::new(kind, 0)
}
#[must_use]
#[inline]
pub fn kind(&self) -> &ErrorKind {
&self.inner.kind
}
#[must_use]
#[inline]
pub fn byte_offset(&self) -> usize {
self.inner.byte_offset
}
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
Display::fmt(&self.inner, f)
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Debug::fmt(&self.inner, f)
}
}
impl de::StdError for Error {
#[cfg(feature = "std")]
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
self.inner.kind.source()
}
}
impl de::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error::with_kind(ErrorKind::Deserialize(msg.to_string()))
}
fn invalid_type(unexp: de::Unexpected<'_>, exp: &dyn de::Expected) -> Self {
Error::with_kind(ErrorKind::Deserialize(format!(
"unexpected type error. invalid_type={}, expected_type={}",
unexp, exp
)))
}
}
impl ser::Error for Error {
fn custom<T: Display>(msg: T) -> Self {
Error::with_kind(ErrorKind::Serialize(msg.to_string()))
}
}
#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
fn from(error: Error) -> Self {
if let ErrorKind::Io(error) = error.inner.kind {
return error;
}
std::io::Error::new(std::io::ErrorKind::Other, error.to_string())
}
}
struct ErrorImpl {
kind: ErrorKind,
byte_offset: usize,
}
impl Display for ErrorImpl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.byte_offset == 0 {
Display::fmt(&self.kind, f)
} else {
write!(f, "{} at byte offset {}", self.kind, self.byte_offset)
}
}
}
impl fmt::Debug for ErrorImpl {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Error")
.field("kind", &self.kind)
.field("byte_offset", &self.byte_offset)
.finish()
}
}
#[allow(clippy::module_name_repetitions)]
pub enum ErrorKind {
Deserialize(String),
EofWhileParsingValue,
ExpectedSomeValue,
InvalidByteStrLen,
InvalidInteger,
InvalidDict,
InvalidList,
#[cfg(feature = "std")]
Io(std::io::Error),
KeyMustBeAByteStr,
KeyWithoutValue,
Serialize(String),
TrailingData,
UnsupportedType,
ValueWithoutKey,
}
#[cfg(feature = "std")]
impl error::Error for ErrorKind {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
ErrorKind::Deserialize(_)
| ErrorKind::EofWhileParsingValue
| ErrorKind::ExpectedSomeValue
| ErrorKind::InvalidByteStrLen
| ErrorKind::InvalidInteger
| ErrorKind::InvalidDict
| ErrorKind::InvalidList
| ErrorKind::KeyMustBeAByteStr
| ErrorKind::KeyWithoutValue
| ErrorKind::Serialize(_)
| ErrorKind::TrailingData
| ErrorKind::UnsupportedType
| ErrorKind::ValueWithoutKey => None,
#[cfg(feature = "std")]
ErrorKind::Io(source) => Some(source),
}
}
}
impl Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::Deserialize(str) | ErrorKind::Serialize(str) => f.write_str(str),
ErrorKind::EofWhileParsingValue => f.write_str("eof while parsing value"),
ErrorKind::ExpectedSomeValue => f.write_str("expected some value"),
ErrorKind::InvalidByteStrLen => f.write_str("invalid byte string length"),
ErrorKind::InvalidInteger => f.write_str("invalid integer"),
ErrorKind::InvalidDict => f.write_str("invalid dictionary"),
ErrorKind::InvalidList => f.write_str("invalid list"),
ErrorKind::KeyMustBeAByteStr => f.write_str("key must be a byte string"),
ErrorKind::KeyWithoutValue => f.write_str("key without value"),
ErrorKind::TrailingData => f.write_str("trailing data error"),
ErrorKind::UnsupportedType => f.write_str("unsupported type"),
ErrorKind::ValueWithoutKey => f.write_str("value without key"),
#[cfg(feature = "std")]
ErrorKind::Io(source) => Display::fmt(source, f),
}
}
}
impl fmt::Debug for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ErrorKind::Deserialize(str) | ErrorKind::Serialize(str) => f.write_str(str),
ErrorKind::EofWhileParsingValue => f.write_str("eof while parsing value"),
ErrorKind::ExpectedSomeValue => f.write_str("expected some value"),
ErrorKind::InvalidByteStrLen => f.write_str("invalid byte string length"),
ErrorKind::InvalidInteger => f.write_str("invalid integer"),
ErrorKind::InvalidDict => f.write_str("invalid dictionary"),
ErrorKind::InvalidList => f.write_str("invalid list"),
ErrorKind::KeyMustBeAByteStr => f.write_str("key must be a byte string"),
ErrorKind::KeyWithoutValue => f.write_str("key without value"),
ErrorKind::TrailingData => f.write_str("trailing data error"),
ErrorKind::UnsupportedType => f.write_str("unsupported type"),
ErrorKind::ValueWithoutKey => f.write_str("value without key"),
#[cfg(feature = "std")]
ErrorKind::Io(source) => fmt::Debug::fmt(source, f),
}
}
}