1#[cfg(feature = "alloc")]
4use alloc::string::ToString;
5use core::fmt::{self, Debug, Display};
6
7#[derive(Debug)]
9pub enum Error<E> {
10 FloatingPointUnsupported,
12 TooManyVariants {
14 enum_name: &'static str,
15 variant_name: &'static str,
16 variant_index: u32,
17 },
18 LengthNeeded,
20 TypeMustBeKnown,
22 ExpectedBoolean {
24 found: u8,
25 },
26 InvalidCharacter {
28 found: u32,
29 },
30 CollectionTooLargeToSerialize {
32 len: usize,
33 },
34 CollectionTooLargeToDeserialize,
36 InvalidUnicode(core::str::Utf8Error),
38 InvalidOption {
40 found_discriminant: u8,
41 },
42 Io(E),
44 Other(OtherError),
46}
47
48impl<E> From<E> for Error<E> {
49 fn from(e: E) -> Self {
50 Error::Io(e)
51 }
52}
53
54impl<E: Display> Display for Error<E> {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 match self {
57 Error::FloatingPointUnsupported => {
58 write!(f, "Floating point values are not supported by the SCALE encoding")
59 }
60 Error::TooManyVariants { enum_name, variant_name, variant_index } => {
61 write!(f, "Variant {}::{} has index {} but the SCALE encoding limits enumerations \
62 to 255 variants", enum_name, variant_name, variant_index)
63 }
64 Error::LengthNeeded => {
65 write!(f, "Sequence length unknown but the SCALE encoding requires to know it")
66 }
67 Error::TypeMustBeKnown => {
68 write!(f, "Type unknown but the SCALE encoding requires to know it")
69 }
70 Error::ExpectedBoolean { found } => {
71 write!(f, "Expected boolean (0 or 1), found {}", found)
72 }
73 Error::InvalidCharacter { found } => {
74 write!(f, "{} is an invalid UTF-32 codepoint", found)
75 }
76 Error::CollectionTooLargeToSerialize { len } => {
77 write!(f, "Found a collection of {} elements but this implementation limits \
78 collections to 2^64 elements", len)
79 }
80 Error::CollectionTooLargeToDeserialize => {
81 write!(f, "Collections of more than 2^64 elements are not supported")
82 }
83 Error::InvalidUnicode(e) => {
84 write!(f, "Invalid Unicode in string: {}", e)
85 }
86 Error::InvalidOption { found_discriminant } => {
87 write!(f, "Invalid option. Expected a discriminant of 0 or 1 but found {}",
88 found_discriminant)
89 }
90 Error::Io(e) => {
91 write!(f, "I/O error: {}", e)
92 }
93 Error::Other(e) => write!(f, "{}", e),
94 }
95 }
96}
97
98#[cfg(feature = "std")]
99impl<E: Debug + Display> std::error::Error for Error<E> {
100 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
101 match self {
102 Error::InvalidUnicode(e) => Some(e),
103 Error::Io(_) => {
104 None
109 }
110 Error::FloatingPointUnsupported
111 | Error::TooManyVariants { .. }
112 | Error::LengthNeeded
113 | Error::TypeMustBeKnown
114 | Error::ExpectedBoolean { .. }
115 | Error::InvalidCharacter { .. }
116 | Error::CollectionTooLargeToSerialize { .. }
117 | Error::CollectionTooLargeToDeserialize
118 | Error::InvalidOption { .. }
119 | Error::Other(_) => None,
120 }
121 }
122}
123
124#[cfg(not(feature = "std"))]
125impl<E: Debug + Display> serde::ser::StdError for Error<E> {}
126
127impl<E: Debug + Display> serde::ser::Error for Error<E> {
128 fn custom<T: Display>(msg: T) -> Self {
129 #[cfg(feature = "alloc")]
130 {
131 Error::Other(msg.to_string().into())
132 }
133 #[cfg(not(feature = "alloc"))]
134 {
135 let _ = msg;
136 Error::Other("Custom error".into())
137 }
138 }
139}
140
141impl<E: Debug + Display> serde::de::Error for Error<E> {
142 fn custom<T: Display>(msg: T) -> Self {
143 serde::ser::Error::custom(msg)
144 }
145}
146
147pub use other_error::OtherError;
148
149#[cfg(feature = "alloc")]
150mod other_error {
151 use alloc::string::String;
152
153 #[derive(Clone, Debug, Eq, PartialEq)]
154 pub struct OtherError(String);
155
156 impl OtherError {
157 pub fn as_str(&self) -> &str {
158 &self.0
159 }
160 }
161
162 impl From<String> for OtherError {
163 fn from(s: String) -> Self {
164 Self(s)
165 }
166 }
167
168 impl From<&str> for OtherError {
169 fn from(s: &str) -> Self {
170 Self(s.into())
171 }
172 }
173}
174
175#[cfg(not(feature = "alloc"))]
176mod other_error {
177 #[derive(Clone, Debug, Eq, PartialEq)]
178 pub struct OtherError(&'static str);
179
180 impl OtherError {
181 pub fn as_str(&self) -> &str {
182 self.0
183 }
184 }
185
186 impl From<&'static str> for OtherError {
187 fn from(s: &'static str) -> Self {
188 Self(s)
189 }
190 }
191}
192
193impl Display for OtherError {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 f.write_str(self.as_str())
196 }
197}