1use crate::DataType;
2use crate::Number;
3use alloc::boxed::Box;
4use alloc::format;
5use alloc::string::String;
6use alloc::string::ToString;
7use alloc::vec::Vec;
8use core::fmt;
9
10pub type Result<T> = core::result::Result<T, Error>;
12
13#[derive(Debug, Clone, PartialEq, PartialOrd)]
15#[cfg_attr(feature = "derive", derive(serde::Serialize, serde::Deserialize))]
16pub struct Error {
17 kind: Box<ErrorKind>,
18}
19
20impl Error {
21 pub fn unexpected(found: Found, expected: Expected) -> Self {
23 Self {
24 kind: Box::new(ErrorKind::Unexpected { found, expected }),
25 }
26 }
27
28 pub fn kind(&self) -> &ErrorKind {
30 &self.kind
31 }
32
33 pub fn into_kind(self) -> ErrorKind {
35 *self.kind
36 }
37}
38
39#[derive(Debug, Clone, PartialEq, PartialOrd)]
41#[cfg_attr(feature = "derive", derive(serde::Serialize, serde::Deserialize))]
42#[non_exhaustive] pub enum ErrorKind {
44 Unexpected {
46 found: Found,
48 expected: Expected,
50 },
51 Custom(String),
53}
54
55impl fmt::Display for Error {
56 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57 match &*self.kind {
58 ErrorKind::Custom(msg) => write!(f, "{msg}"),
59 ErrorKind::Unexpected { found, expected } => write!(
60 f,
61 "failed to deserialize; expected {expected}, found {found}"
62 ),
63 }
64 }
65}
66
67#[cfg(feature = "std")]
68impl std::error::Error for Error {}
69
70#[cfg(feature = "serde")]
71impl serde::ser::Error for Error {
72 fn custom<T>(msg: T) -> Self
73 where
74 T: fmt::Display,
75 {
76 Self {
77 kind: Box::new(ErrorKind::Custom(msg.to_string())),
78 }
79 }
80}
81
82#[cfg(feature = "serde")]
83impl serde::de::Error for Error {
84 fn custom<T>(msg: T) -> Self
85 where
86 T: fmt::Display,
87 {
88 Self {
89 kind: Box::new(ErrorKind::Custom(msg.to_string())),
90 }
91 }
92}
93
94#[derive(Debug, Clone, PartialEq, PartialOrd)]
96#[cfg_attr(feature = "derive", derive(serde::Serialize, serde::Deserialize))]
97#[non_exhaustive] pub enum Expected {
99 Unit,
101 Bool,
103 Char,
105 String,
107 StaticStr,
109 Bytes,
111 Seq,
113 Map,
115 Struct {
117 name: Option<String>,
119 typ: Option<DataType>,
121 },
122 Enum {
124 name: Option<String>,
126 typ: Option<DataType>,
128 },
129 Tuple(usize),
131 Identifier,
133 I8,
135 U8,
137 I16,
139 U16,
141 I32,
143 U32,
145 F32,
147 I64,
149 U64,
151 F64,
153 I128,
155 U128,
157}
158
159#[doc(hidden)] impl fmt::Display for Expected {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 match self {
163 Expected::Unit => write!(f, "a unit"),
164 Expected::Bool => write!(f, "a boolean"),
165 Expected::I8 => write!(f, "an 8-bit signed integer"),
166 Expected::U8 => write!(f, "an 8-bit unsigned integer"),
167 Expected::I16 => write!(f, "a 16-bit signed integer"),
168 Expected::U16 => write!(f, "a 16-bit unsigned integer"),
169 Expected::I32 => write!(f, "a 32-bit signed integer"),
170 Expected::U32 => write!(f, "a 32-bit unsigned integer"),
171 Expected::F32 => write!(f, "a 32-bit floating point"),
172 Expected::I64 => write!(f, "a 64-bit signed integer"),
173 Expected::U64 => write!(f, "a 64-bit unsigned integer"),
174 Expected::F64 => write!(f, "a 64-bit floating point"),
175 Expected::I128 => write!(f, "a 128-bit signed integer"),
176 Expected::U128 => write!(f, "a 128-bit unsigned integer"),
177 Expected::Char => write!(f, "a single character"),
178 Expected::String => write!(f, "a string"),
179 Expected::StaticStr => write!(f, "a static string slice"),
180 Expected::Bytes => write!(f, "a byte array"),
181 Expected::Seq => write!(f, "a sequence"),
182 Expected::Map => write!(f, "a map"),
183 Expected::Struct { name, typ } => match (name.as_deref(), typ) {
184 (None, None) => write!(f, "a struct"),
185 (None, Some(typ)) => write!(f, "{typ} struct"),
186 (Some(name), None) => write!(f, "a struct named {name}"),
187 (Some(name), Some(typ)) => write!(f, "{typ} struct named {name}"),
188 },
189 Expected::Enum { name, typ } => match (name.as_deref(), typ) {
190 (None, None) => write!(f, "an enum variant"),
191 (None, Some(typ)) => write!(f, "{typ} enum variant"),
192 (Some(name), None) => write!(f, "an enum variant of {name}"),
193 (Some(name), Some(typ)) => write!(f, "{typ} enum variant of {name}"),
194 },
195 Expected::Tuple(len) => write!(f, "a tuple with {len} elements"),
196 Expected::Identifier => write!(f, "a struct field name or an enum variant"),
197 }
198 }
199}
200
201#[doc(hidden)] impl fmt::Display for DataType {
203 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
204 match self {
205 DataType::Unit => write!(f, "a unit"),
206 DataType::NewType => write!(f, "a newtype"),
207 DataType::Tuple => write!(f, "a tuple"),
208 DataType::Struct => write!(f, "an object-like"),
209 }
210 }
211}
212
213#[derive(Debug, Clone, PartialEq, PartialOrd)]
215#[cfg_attr(feature = "derive", derive(serde::Serialize, serde::Deserialize))]
216pub enum Data {
217 Unit,
219 NewType(Found),
221 Tuple(Vec<Found>),
223 Struct(Vec<(String, Found)>),
225}
226
227#[derive(Debug, Clone, PartialEq, PartialOrd)]
229#[cfg_attr(feature = "derive", derive(serde::Serialize, serde::Deserialize))]
230pub enum Found {
231 Unit,
233 Bool(bool),
235 Number(Number),
237 Char(char),
239 String(String),
241 Bytes(Vec<u8>),
243 Seq(Vec<Found>),
245 Map(Vec<(Found, Found)>),
247 Option(Option<Box<Found>>),
249 Struct {
251 name: String,
253 data: Box<Data>,
255 },
256 Enum {
258 name: String,
260 variant: String,
262 data: Box<Data>,
264 },
265 Tuple(Vec<Found>),
267 Identifier(String),
269}
270
271#[doc(hidden)] impl fmt::Display for Found {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 match self {
275 Found::Unit => write!(f, "()"),
276 Found::Bool(v) => write!(f, "{v}"),
277 Found::Number(v) => match v {
278 Number::I8(v) => write!(f, "{v}i8"),
279 Number::U8(v) => write!(f, "{v}u8"),
280 Number::I16(v) => write!(f, "{v}i16"),
281 Number::U16(v) => write!(f, "{v}u16"),
282 Number::I32(v) => write!(f, "{v}i32"),
283 Number::U32(v) => write!(f, "{v}u32"),
284 Number::F32(v) => write!(f, "{v}f32"),
285 Number::I64(v) => write!(f, "{v}i64"),
286 Number::U64(v) => write!(f, "{v}u64"),
287 Number::F64(v) => write!(f, "{v}f64"),
288 Number::I128(v) => write!(f, "{v}i128"),
289 Number::U128(v) => write!(f, "{v}u128"),
290 },
291 Found::Char(v) => write!(f, "'{v}'"),
292 Found::String(v) => write!(f, "{v:?}"),
293 Found::Bytes(v) => write!(f, "&{v:?}"),
294 Found::Seq(v) => {
295 f.write_str("[")?;
296 let data = v.iter().map(Self::to_string).collect::<Vec<_>>();
297 f.write_str(&data.join(", "))?;
298 f.write_str("]")
299 }
300 Found::Map(v) => {
301 f.write_str("{ ")?;
302 let data = v
303 .iter()
304 .map(|(k, v)| format!("{k}: {v}"))
305 .collect::<Vec<_>>();
306 f.write_str(&data.join(", "))?;
307 f.write_str(" }")
308 }
309 Found::Option(v) => match v {
310 Some(v) => write!(f, "Some({v})"),
311 None => write!(f, "None"),
312 },
313 Found::Struct { name, data } => match data.as_ref() {
314 Data::Unit => write!(f, "{name}"),
315 Data::NewType(v) => write!(f, "{name}({v})"),
316 Data::Tuple(v) => {
317 write!(f, "{name}(")?;
318 let data = v.iter().map(Self::to_string).collect::<Vec<_>>();
319 f.write_str(&data.join(", "))?;
320 f.write_str(")")
321 }
322 Data::Struct(v) => {
323 write!(f, "{name} {{ ")?;
324 let data = v
325 .iter()
326 .map(|(k, v)| format!("{k}: {v}"))
327 .collect::<Vec<_>>();
328 f.write_str(&data.join(", "))?;
329 f.write_str(" }")
330 }
331 },
332 Found::Enum {
333 name,
334 variant,
335 data,
336 } => match data.as_ref() {
337 Data::Unit => write!(f, "{name}::{variant}"),
338 Data::NewType(v) => write!(f, "{name}::{variant}({v})"),
339 Data::Tuple(v) => {
340 write!(f, "{name}::{variant}(")?;
341 let data = v.iter().map(Self::to_string).collect::<Vec<_>>();
342 f.write_str(&data.join(", "))?;
343 f.write_str(")")
344 }
345 Data::Struct(v) => {
346 write!(f, "{name}::{variant} {{ ")?;
347 let data = v
348 .iter()
349 .map(|(k, v)| format!("{k}: {v}"))
350 .collect::<Vec<_>>();
351 f.write_str(&data.join(", "))?;
352 f.write_str(" }")
353 }
354 },
355 Found::Tuple(v) => {
356 f.write_str("(")?;
357 let data = v.iter().map(Self::to_string).collect::<Vec<_>>();
358 f.write_str(&data.join(", "))?;
359 f.write_str(")")
360 }
361 Found::Identifier(v) => write!(f, "{v}"),
362 }
363 }
364}