#[cfg(feature = "alloc")]
use alloc::string::ToString;
use core::fmt::{self, Debug, Display};
#[derive(Debug)]
pub enum Error<E> {
FloatingPointUnsupported,
TooManyVariants {
enum_name: &'static str,
variant_name: &'static str,
variant_index: u32,
},
LengthNeeded,
TypeMustBeKnown,
ExpectedBoolean {
found: u8,
},
InvalidCharacter {
found: u32,
},
CollectionTooLargeToSerialize {
len: usize,
},
CollectionTooLargeToDeserialize,
InvalidUnicode(core::str::Utf8Error),
InvalidOption {
found_discriminant: u8,
},
Io(E),
Other(OtherError),
}
impl<E> From<E> for Error<E> {
fn from(e: E) -> Self {
Error::Io(e)
}
}
impl<E: Display> Display for Error<E> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Error::FloatingPointUnsupported => {
write!(f, "Floating point values are not supported by the SCALE encoding")
}
Error::TooManyVariants { enum_name, variant_name, variant_index } => {
write!(f, "Variant {}::{} has index {} but the SCALE encoding limits enumerations \
to 255 variants", enum_name, variant_name, variant_index)
}
Error::LengthNeeded => {
write!(f, "Sequence length unknown but the SCALE encoding requires to know it")
}
Error::TypeMustBeKnown => {
write!(f, "Type unknown but the SCALE encoding requires to know it")
}
Error::ExpectedBoolean { found } => {
write!(f, "Expected boolean (0 or 1), found {}", found)
}
Error::InvalidCharacter { found } => {
write!(f, "{} is an invalid UTF-32 codepoint", found)
}
Error::CollectionTooLargeToSerialize { len } => {
write!(f, "Found a collection of {} elements but this implementation limits \
collections to 2^64 elements", len)
}
Error::CollectionTooLargeToDeserialize => {
write!(f, "Collections of more than 2^64 elements are not supported")
}
Error::InvalidUnicode(e) => {
write!(f, "Invalid Unicode in string: {}", e)
}
Error::InvalidOption { found_discriminant } => {
write!(f, "Invalid option. Expected a discriminant of 0 or 1 but found {}",
found_discriminant)
}
Error::Io(e) => {
write!(f, "I/O error: {}", e)
}
Error::Other(e) => write!(f, "{}", e),
}
}
}
#[cfg(feature = "std")]
impl<E: Debug + Display> std::error::Error for Error<E> {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Error::InvalidUnicode(e) => Some(e),
Error::Io(_) => {
None
}
Error::FloatingPointUnsupported
| Error::TooManyVariants { .. }
| Error::LengthNeeded
| Error::TypeMustBeKnown
| Error::ExpectedBoolean { .. }
| Error::InvalidCharacter { .. }
| Error::CollectionTooLargeToSerialize { .. }
| Error::CollectionTooLargeToDeserialize
| Error::InvalidOption { .. }
| Error::Other(_) => None,
}
}
}
#[cfg(not(feature = "std"))]
impl<E: Debug + Display> serde::ser::StdError for Error<E> {}
impl<E: Debug + Display> serde::ser::Error for Error<E> {
fn custom<T: Display>(msg: T) -> Self {
#[cfg(feature = "alloc")]
{
Error::Other(msg.to_string().into())
}
#[cfg(not(feature = "alloc"))]
{
let _ = msg;
Error::Other("Custom error".into())
}
}
}
impl<E: Debug + Display> serde::de::Error for Error<E> {
fn custom<T: Display>(msg: T) -> Self {
serde::ser::Error::custom(msg)
}
}
pub use other_error::OtherError;
#[cfg(feature = "alloc")]
mod other_error {
use alloc::string::String;
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherError(String);
impl OtherError {
pub fn as_str(&self) -> &str {
&self.0
}
}
impl From<String> for OtherError {
fn from(s: String) -> Self {
Self(s)
}
}
impl From<&str> for OtherError {
fn from(s: &str) -> Self {
Self(s.into())
}
}
}
#[cfg(not(feature = "alloc"))]
mod other_error {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct OtherError(&'static str);
impl OtherError {
pub fn as_str(&self) -> &str {
self.0
}
}
impl From<&'static str> for OtherError {
fn from(s: &'static str) -> Self {
Self(s)
}
}
}
impl Display for OtherError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}