ron/
error.rs

1use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error};
2
3use serde::{de, ser};
4
5use crate::parse::{is_ident_first_char, is_ident_other_char, is_ident_raw_char, BASE64_ENGINE};
6
7/// This type represents all possible errors that can occur when
8/// serializing or deserializing RON data.
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct SpannedError {
11    pub code: Error,
12    pub position: Position,
13}
14
15pub type Result<T, E = Error> = std::result::Result<T, E>;
16pub type SpannedResult<T> = std::result::Result<T, SpannedError>;
17
18#[derive(Clone, Debug, PartialEq, Eq)]
19#[non_exhaustive]
20pub enum Error {
21    Io(String),
22    Message(String),
23    Base64Error(base64::DecodeError),
24    Eof,
25    ExpectedArray,
26    ExpectedArrayEnd,
27    ExpectedAttribute,
28    ExpectedAttributeEnd,
29    ExpectedBoolean,
30    ExpectedComma,
31    ExpectedChar,
32    ExpectedFloat,
33    FloatUnderscore,
34    ExpectedInteger,
35    ExpectedOption,
36    ExpectedOptionEnd,
37    ExpectedMap,
38    ExpectedMapColon,
39    ExpectedMapEnd,
40    ExpectedDifferentStructName {
41        expected: &'static str,
42        found: String,
43    },
44    ExpectedStructLike,
45    ExpectedNamedStructLike(&'static str),
46    ExpectedStructLikeEnd,
47    ExpectedUnit,
48    ExpectedString,
49    ExpectedStringEnd,
50    ExpectedIdentifier,
51
52    InvalidEscape(&'static str),
53
54    IntegerOutOfBounds,
55
56    NoSuchExtension(String),
57
58    UnclosedBlockComment,
59    UnderscoreAtBeginning,
60    UnexpectedByte(char),
61
62    Utf8Error(Utf8Error),
63    TrailingCharacters,
64
65    InvalidValueForType {
66        expected: String,
67        found: String,
68    },
69    ExpectedDifferentLength {
70        expected: String,
71        found: usize,
72    },
73    NoSuchEnumVariant {
74        expected: &'static [&'static str],
75        found: String,
76        outer: Option<String>,
77    },
78    NoSuchStructField {
79        expected: &'static [&'static str],
80        found: String,
81        outer: Option<String>,
82    },
83    MissingStructField {
84        field: &'static str,
85        outer: Option<String>,
86    },
87    DuplicateStructField {
88        field: &'static str,
89        outer: Option<String>,
90    },
91    InvalidIdentifier(String),
92    SuggestRawIdentifier(String),
93    ExceededRecursionLimit,
94}
95
96impl fmt::Display for SpannedError {
97    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98        if (self.position == Position { line: 0, col: 0 }) {
99            write!(f, "{}", self.code)
100        } else {
101            write!(f, "{}: {}", self.position, self.code)
102        }
103    }
104}
105
106impl fmt::Display for Error {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        match *self {
109            Error::Io(ref s) => f.write_str(s),
110            Error::Message(ref s) => f.write_str(s),
111            Error::Base64Error(ref e) => fmt::Display::fmt(e, f),
112            Error::Eof => f.write_str("Unexpected end of RON"),
113            Error::ExpectedArray => f.write_str("Expected opening `[`"),
114            Error::ExpectedArrayEnd => f.write_str("Expected closing `]`"),
115            Error::ExpectedAttribute => f.write_str("Expected an `#![enable(...)]` attribute"),
116            Error::ExpectedAttributeEnd => {
117                f.write_str("Expected closing `)]` after the enable attribute")
118            }
119            Error::ExpectedBoolean => f.write_str("Expected boolean"),
120            Error::ExpectedComma => f.write_str("Expected comma"),
121            Error::ExpectedChar => f.write_str("Expected char"),
122            Error::ExpectedFloat => f.write_str("Expected float"),
123            Error::FloatUnderscore => f.write_str("Unexpected underscore in float"),
124            Error::ExpectedInteger => f.write_str("Expected integer"),
125            Error::ExpectedOption => f.write_str("Expected option"),
126            Error::ExpectedOptionEnd => f.write_str("Expected closing `)`"),
127            Error::ExpectedMap => f.write_str("Expected opening `{`"),
128            Error::ExpectedMapColon => f.write_str("Expected colon"),
129            Error::ExpectedMapEnd => f.write_str("Expected closing `}`"),
130            Error::ExpectedDifferentStructName {
131                expected,
132                ref found,
133            } => write!(
134                f,
135                "Expected struct {} but found {}",
136                Identifier(expected),
137                Identifier(found)
138            ),
139            Error::ExpectedStructLike => f.write_str("Expected opening `(`"),
140            Error::ExpectedNamedStructLike(name) => {
141                if name.is_empty() {
142                    f.write_str("Expected only opening `(`, no name, for un-nameable struct")
143                } else {
144                    write!(f, "Expected opening `(` for struct {}", Identifier(name))
145                }
146            }
147            Error::ExpectedStructLikeEnd => f.write_str("Expected closing `)`"),
148            Error::ExpectedUnit => f.write_str("Expected unit"),
149            Error::ExpectedString => f.write_str("Expected string"),
150            Error::ExpectedStringEnd => f.write_str("Expected end of string"),
151            Error::ExpectedIdentifier => f.write_str("Expected identifier"),
152            Error::InvalidEscape(s) => f.write_str(s),
153            Error::IntegerOutOfBounds => f.write_str("Integer is out of bounds"),
154            Error::NoSuchExtension(ref name) => {
155                write!(f, "No RON extension named {}", Identifier(name))
156            }
157            Error::Utf8Error(ref e) => fmt::Display::fmt(e, f),
158            Error::UnclosedBlockComment => f.write_str("Unclosed block comment"),
159            Error::UnderscoreAtBeginning => {
160                f.write_str("Unexpected leading underscore in an integer")
161            }
162            Error::UnexpectedByte(ref byte) => write!(f, "Unexpected byte {:?}", byte),
163            Error::TrailingCharacters => f.write_str("Non-whitespace trailing characters"),
164            Error::InvalidValueForType {
165                ref expected,
166                ref found,
167            } => {
168                write!(f, "Expected {} but found {} instead", expected, found)
169            }
170            Error::ExpectedDifferentLength {
171                ref expected,
172                found,
173            } => {
174                write!(f, "Expected {} but found ", expected)?;
175
176                match found {
177                    0 => f.write_str("zero elements")?,
178                    1 => f.write_str("one element")?,
179                    n => write!(f, "{} elements", n)?,
180                }
181
182                f.write_str(" instead")
183            }
184            Error::NoSuchEnumVariant {
185                expected,
186                ref found,
187                ref outer,
188            } => {
189                f.write_str("Unexpected ")?;
190
191                if outer.is_none() {
192                    f.write_str("enum ")?;
193                }
194
195                write!(f, "variant named {}", Identifier(found))?;
196
197                if let Some(outer) = outer {
198                    write!(f, "in enum {}", Identifier(outer))?;
199                }
200
201                write!(
202                    f,
203                    ", {}",
204                    OneOf {
205                        alts: expected,
206                        none: "variants"
207                    }
208                )
209            }
210            Error::NoSuchStructField {
211                expected,
212                ref found,
213                ref outer,
214            } => {
215                write!(f, "Unexpected field named {}", Identifier(found))?;
216
217                if let Some(outer) = outer {
218                    write!(f, "in {}", Identifier(outer))?;
219                }
220
221                write!(
222                    f,
223                    ", {}",
224                    OneOf {
225                        alts: expected,
226                        none: "fields"
227                    }
228                )
229            }
230            Error::MissingStructField { field, ref outer } => {
231                write!(f, "Unexpected missing field {}", Identifier(field))?;
232
233                match outer {
234                    Some(outer) => write!(f, " in {}", Identifier(outer)),
235                    None => Ok(()),
236                }
237            }
238            Error::DuplicateStructField { field, ref outer } => {
239                write!(f, "Unexpected duplicate field {}", Identifier(field))?;
240
241                match outer {
242                    Some(outer) => write!(f, " in {}", Identifier(outer)),
243                    None => Ok(()),
244                }
245            }
246            Error::InvalidIdentifier(ref invalid) => write!(f, "Invalid identifier {:?}", invalid),
247            Error::SuggestRawIdentifier(ref identifier) => write!(
248                f,
249                "Found invalid std identifier `{}`, try the raw identifier `r#{}` instead",
250                identifier, identifier
251            ),
252            Error::ExceededRecursionLimit => f.write_str("Exceeded recursion limit, try increasing the limit and using `serde_stacker` to protect against a stack overflow"),
253        }
254    }
255}
256
257#[derive(Clone, Copy, Debug, PartialEq, Eq)]
258pub struct Position {
259    pub line: usize,
260    pub col: usize,
261}
262
263impl fmt::Display for Position {
264    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265        write!(f, "{}:{}", self.line, self.col)
266    }
267}
268
269impl ser::Error for Error {
270    #[cold]
271    fn custom<T: fmt::Display>(msg: T) -> Self {
272        Error::Message(msg.to_string())
273    }
274}
275
276impl de::Error for Error {
277    #[cold]
278    fn custom<T: fmt::Display>(msg: T) -> Self {
279        Error::Message(msg.to_string())
280    }
281
282    #[cold]
283    fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
284        // Invalid type and invalid value are merged given their similarity in ron
285        Self::invalid_value(unexp, exp)
286    }
287
288    #[cold]
289    fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
290        struct UnexpectedSerdeTypeValue<'a>(de::Unexpected<'a>);
291
292        impl<'a> fmt::Display for UnexpectedSerdeTypeValue<'a> {
293            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
294                use de::Unexpected::*;
295
296                match self.0 {
297                    Bool(b) => write!(f, "the boolean `{}`", b),
298                    Unsigned(i) => write!(f, "the unsigned integer `{}`", i),
299                    Signed(i) => write!(f, "the signed integer `{}`", i),
300                    Float(n) => write!(f, "the floating point number `{}`", n),
301                    Char(c) => write!(f, "the UTF-8 character `{}`", c),
302                    Str(s) => write!(f, "the string {:?}", s),
303                    Bytes(b) => write!(f, "the bytes \"{}\"", {
304                        base64::display::Base64Display::new(b, &BASE64_ENGINE)
305                    }),
306                    Unit => write!(f, "a unit value"),
307                    Option => write!(f, "an optional value"),
308                    NewtypeStruct => write!(f, "a newtype struct"),
309                    Seq => write!(f, "a sequence"),
310                    Map => write!(f, "a map"),
311                    Enum => write!(f, "an enum"),
312                    UnitVariant => write!(f, "a unit variant"),
313                    NewtypeVariant => write!(f, "a newtype variant"),
314                    TupleVariant => write!(f, "a tuple variant"),
315                    StructVariant => write!(f, "a struct variant"),
316                    Other(other) => f.write_str(other),
317                }
318            }
319        }
320
321        Error::InvalidValueForType {
322            expected: exp.to_string(),
323            found: UnexpectedSerdeTypeValue(unexp).to_string(),
324        }
325    }
326
327    #[cold]
328    fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self {
329        Error::ExpectedDifferentLength {
330            expected: exp.to_string(),
331            found: len,
332        }
333    }
334
335    #[cold]
336    fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
337        Error::NoSuchEnumVariant {
338            expected,
339            found: variant.to_string(),
340            outer: None,
341        }
342    }
343
344    #[cold]
345    fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
346        Error::NoSuchStructField {
347            expected,
348            found: field.to_string(),
349            outer: None,
350        }
351    }
352
353    #[cold]
354    fn missing_field(field: &'static str) -> Self {
355        Error::MissingStructField { field, outer: None }
356    }
357
358    #[cold]
359    fn duplicate_field(field: &'static str) -> Self {
360        Error::DuplicateStructField { field, outer: None }
361    }
362}
363
364impl StdError for SpannedError {}
365impl StdError for Error {}
366
367impl From<Utf8Error> for Error {
368    fn from(e: Utf8Error) -> Self {
369        Error::Utf8Error(e)
370    }
371}
372
373impl From<FromUtf8Error> for Error {
374    fn from(e: FromUtf8Error) -> Self {
375        Error::Utf8Error(e.utf8_error())
376    }
377}
378
379impl From<io::Error> for Error {
380    fn from(e: io::Error) -> Self {
381        Error::Io(e.to_string())
382    }
383}
384
385impl From<io::Error> for SpannedError {
386    fn from(e: io::Error) -> Self {
387        SpannedError {
388            code: e.into(),
389            position: Position { line: 0, col: 0 },
390        }
391    }
392}
393
394impl From<SpannedError> for Error {
395    fn from(e: SpannedError) -> Self {
396        e.code
397    }
398}
399
400struct OneOf {
401    alts: &'static [&'static str],
402    none: &'static str,
403}
404
405impl fmt::Display for OneOf {
406    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
407        match self.alts {
408            [] => write!(f, "there are no {}", self.none),
409            [a1] => write!(f, "expected {} instead", Identifier(a1)),
410            [a1, a2] => write!(
411                f,
412                "expected either {} or {} instead",
413                Identifier(a1),
414                Identifier(a2)
415            ),
416            [a1, ref alts @ ..] => {
417                write!(f, "expected one of {}", Identifier(a1))?;
418
419                for alt in alts {
420                    write!(f, ", {}", Identifier(alt))?;
421                }
422
423                f.write_str(" instead")
424            }
425        }
426    }
427}
428
429struct Identifier<'a>(&'a str);
430
431impl<'a> fmt::Display for Identifier<'a> {
432    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
433        if self.0.is_empty() || !self.0.as_bytes().iter().copied().all(is_ident_raw_char) {
434            return write!(f, "{:?}_[invalid identifier]", self.0);
435        }
436
437        let mut bytes = self.0.as_bytes().iter().copied();
438
439        if !bytes.next().map_or(false, is_ident_first_char) || !bytes.all(is_ident_other_char) {
440            write!(f, "`r#{}`", self.0)
441        } else {
442            write!(f, "`{}`", self.0)
443        }
444    }
445}