1
use alloc::string::{String, ToString};
2
use core::{
3
    fmt,
4
    str::{self, Utf8Error},
5
};
6

            
7
use serde::{
8
    de,
9
    ser::{self, StdError},
10
};
11
use unicode_ident::is_xid_continue;
12

            
13
use crate::parse::{is_ident_first_char, is_ident_raw_char};
14

            
15
#[cfg(feature = "std")]
16
use std::io;
17

            
18
/// This type represents all possible errors that can occur when
19
/// serializing or deserializing RON data.
20
#[allow(clippy::module_name_repetitions)]
21
#[derive(Clone, Debug, PartialEq, Eq)]
22
pub struct SpannedError {
23
    pub code: Error,
24
    pub span: Span,
25
}
26

            
27
pub type Result<T, E = Error> = core::result::Result<T, E>;
28
pub type SpannedResult<T> = core::result::Result<T, SpannedError>;
29

            
30
#[derive(Clone, Debug, PartialEq, Eq)]
31
#[non_exhaustive]
32
pub enum Error {
33
    Fmt,
34
    Io(String),
35
    Message(String),
36
    #[deprecated(
37
        since = "0.9.0",
38
        note = "ambiguous base64 byte strings are replaced by strongly typed Rusty b\"byte strings\""
39
    )]
40
    Base64Error(base64::DecodeError),
41
    Eof,
42
    ExpectedArray,
43
    ExpectedArrayEnd,
44
    ExpectedAttribute,
45
    ExpectedAttributeEnd,
46
    ExpectedBoolean,
47
    ExpectedComma,
48
    ExpectedChar,
49
    ExpectedByteLiteral,
50
    ExpectedFloat,
51
    FloatUnderscore,
52
    ExpectedInteger,
53
    ExpectedOption,
54
    ExpectedOptionEnd,
55
    ExpectedMap,
56
    ExpectedMapColon,
57
    ExpectedMapEnd,
58
    ExpectedDifferentStructName {
59
        expected: &'static str,
60
        found: String,
61
    },
62
    ExpectedStructLike,
63
    ExpectedNamedStructLike(&'static str),
64
    ExpectedStructLikeEnd,
65
    ExpectedUnit,
66
    ExpectedString,
67
    ExpectedByteString,
68
    ExpectedStringEnd,
69
    ExpectedIdentifier,
70

            
71
    InvalidEscape(&'static str),
72

            
73
    IntegerOutOfBounds,
74
    InvalidIntegerDigit {
75
        digit: char,
76
        base: u8,
77
    },
78

            
79
    NoSuchExtension(String),
80

            
81
    UnclosedBlockComment,
82
    UnclosedLineComment,
83
    UnderscoreAtBeginning,
84
    UnexpectedChar(char),
85

            
86
    Utf8Error(Utf8Error),
87
    TrailingCharacters,
88

            
89
    InvalidValueForType {
90
        expected: String,
91
        found: String,
92
    },
93
    ExpectedDifferentLength {
94
        expected: String,
95
        found: usize,
96
    },
97
    NoSuchEnumVariant {
98
        expected: &'static [&'static str],
99
        found: String,
100
        outer: Option<String>,
101
    },
102
    NoSuchStructField {
103
        expected: &'static [&'static str],
104
        found: String,
105
        outer: Option<String>,
106
    },
107
    MissingStructField {
108
        field: &'static str,
109
        outer: Option<String>,
110
    },
111
    DuplicateStructField {
112
        field: &'static str,
113
        outer: Option<String>,
114
    },
115
    InvalidIdentifier(String),
116
    SuggestRawIdentifier(String),
117
    ExpectedRawValue,
118
    ExceededRecursionLimit,
119
    ExpectedStructName(String),
120
}
121

            
122
impl fmt::Display for SpannedError {
123
1390
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124
1390
        write!(f, "{}: {}", self.span, self.code)
125
1390
    }
126
}
127

            
128
impl fmt::Display for Error {
129
    #[allow(clippy::too_many_lines)]
130
2190
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131
2190
        match *self {
132
4
            Error::Fmt => f.write_str("Formatting RON failed"),
133
12
            Error::Io(ref s) | Error::Message(ref s) => f.write_str(s),
134
            #[allow(deprecated)]
135
4
            Error::Base64Error(ref e) => write!(f, "Invalid base64: {}", e),
136
282
            Error::Eof => f.write_str("Unexpected end of RON"),
137
4
            Error::ExpectedArray => f.write_str("Expected opening `[`"),
138
4
            Error::ExpectedArrayEnd => f.write_str("Expected closing `]`"),
139
4
            Error::ExpectedAttribute => f.write_str("Expected an `#![enable(...)]` attribute"),
140
            Error::ExpectedAttributeEnd => {
141
4
                f.write_str("Expected closing `)]` after the enable attribute")
142
            }
143
4
            Error::ExpectedBoolean => f.write_str("Expected boolean"),
144
4
            Error::ExpectedComma => f.write_str("Expected comma"),
145
4
            Error::ExpectedChar => f.write_str("Expected char"),
146
282
            Error::ExpectedByteLiteral => f.write_str("Expected byte literal"),
147
4
            Error::ExpectedFloat => f.write_str("Expected float"),
148
4
            Error::FloatUnderscore => f.write_str("Unexpected underscore in float"),
149
4
            Error::ExpectedInteger => f.write_str("Expected integer"),
150
4
            Error::ExpectedOption => f.write_str("Expected option"),
151
            Error::ExpectedOptionEnd | Error::ExpectedStructLikeEnd => {
152
8
                f.write_str("Expected closing `)`")
153
            }
154
4
            Error::ExpectedMap => f.write_str("Expected opening `{`"),
155
4
            Error::ExpectedMapColon => f.write_str("Expected colon"),
156
4
            Error::ExpectedMapEnd => f.write_str("Expected closing `}`"),
157
            Error::ExpectedDifferentStructName {
158
4
                expected,
159
4
                ref found,
160
4
            } => write!(
161
4
                f,
162
4
                "Expected struct {} but found {}",
163
4
                Identifier(expected),
164
4
                Identifier(found)
165
            ),
166
4
            Error::ExpectedStructLike => f.write_str("Expected opening `(`"),
167
564
            Error::ExpectedNamedStructLike(name) => {
168
564
                if name.is_empty() {
169
560
                    f.write_str("Expected only opening `(`, no name, for un-nameable struct")
170
                } else {
171
4
                    write!(f, "Expected opening `(` for struct {}", Identifier(name))
172
                }
173
            }
174
4
            Error::ExpectedUnit => f.write_str("Expected unit"),
175
4
            Error::ExpectedString => f.write_str("Expected string"),
176
282
            Error::ExpectedByteString => f.write_str("Expected byte string"),
177
4
            Error::ExpectedStringEnd => f.write_str("Expected end of string"),
178
4
            Error::ExpectedIdentifier => f.write_str("Expected identifier"),
179
4
            Error::InvalidEscape(s) => f.write_str(s),
180
4
            Error::IntegerOutOfBounds => f.write_str("Integer is out of bounds"),
181
4
            Error::InvalidIntegerDigit { digit, base } => {
182
4
                write!(f, "Invalid digit {:?} for base {} integers", digit, base)
183
            }
184
4
            Error::NoSuchExtension(ref name) => {
185
4
                write!(f, "No RON extension named {}", Identifier(name))
186
            }
187
4
            Error::Utf8Error(ref e) => fmt::Display::fmt(e, f),
188
4
            Error::UnclosedBlockComment => f.write_str("Unclosed block comment"),
189
4
            Error::UnclosedLineComment => f.write_str(
190
4
                "`ron::value::RawValue` cannot end in unclosed line comment, \
191
4
                try using a block comment or adding a newline",
192
            ),
193
            Error::UnderscoreAtBeginning => {
194
4
                f.write_str("Unexpected leading underscore in a number")
195
            }
196
560
            Error::UnexpectedChar(c) => write!(f, "Unexpected char {:?}", c),
197
4
            Error::TrailingCharacters => f.write_str("Non-whitespace trailing characters"),
198
            Error::InvalidValueForType {
199
8
                ref expected,
200
8
                ref found,
201
            } => {
202
8
                write!(f, "Expected {} but found {} instead", expected, found)
203
            }
204
            Error::ExpectedDifferentLength {
205
12
                ref expected,
206
12
                found,
207
            } => {
208
12
                write!(f, "Expected {} but found ", expected)?;
209

            
210
12
                match found {
211
4
                    0 => f.write_str("zero elements")?,
212
4
                    1 => f.write_str("one element")?,
213
4
                    n => write!(f, "{} elements", n)?,
214
                }
215

            
216
12
                f.write_str(" instead")
217
            }
218
            Error::NoSuchEnumVariant {
219
8
                expected,
220
8
                ref found,
221
8
                ref outer,
222
            } => {
223
8
                f.write_str("Unexpected ")?;
224

            
225
8
                if outer.is_none() {
226
4
                    f.write_str("enum ")?;
227
4
                }
228

            
229
8
                write!(f, "variant named {}", Identifier(found))?;
230

            
231
8
                if let Some(outer) = outer {
232
4
                    write!(f, " in enum {}", Identifier(outer))?;
233
4
                }
234

            
235
8
                write!(
236
8
                    f,
237
8
                    ", {}",
238
8
                    OneOf {
239
8
                        alts: expected,
240
8
                        none: "variants"
241
8
                    }
242
                )
243
            }
244
            Error::NoSuchStructField {
245
12
                expected,
246
12
                ref found,
247
12
                ref outer,
248
            } => {
249
12
                write!(f, "Unexpected field named {}", Identifier(found))?;
250

            
251
12
                if let Some(outer) = outer {
252
8
                    write!(f, " in {}", Identifier(outer))?;
253
4
                }
254

            
255
12
                write!(
256
12
                    f,
257
12
                    ", {}",
258
12
                    OneOf {
259
12
                        alts: expected,
260
12
                        none: "fields"
261
12
                    }
262
                )
263
            }
264
8
            Error::MissingStructField { field, ref outer } => {
265
8
                write!(f, "Unexpected missing field named {}", Identifier(field))?;
266

            
267
8
                match outer {
268
4
                    Some(outer) => write!(f, " in {}", Identifier(outer)),
269
4
                    None => Ok(()),
270
                }
271
            }
272
8
            Error::DuplicateStructField { field, ref outer } => {
273
8
                write!(f, "Unexpected duplicate field named {}", Identifier(field))?;
274

            
275
8
                match outer {
276
4
                    Some(outer) => write!(f, " in {}", Identifier(outer)),
277
4
                    None => Ok(()),
278
                }
279
            }
280
4
            Error::InvalidIdentifier(ref invalid) => write!(f, "Invalid identifier {:?}", invalid),
281
4
            Error::SuggestRawIdentifier(ref identifier) => write!(
282
4
                f,
283
4
                "Found invalid std identifier {:?}, try the raw identifier `r#{}` instead",
284
                identifier, identifier
285
            ),
286
4
            Error::ExpectedRawValue => f.write_str("Expected a `ron::value::RawValue`"),
287
4
            Error::ExceededRecursionLimit => f.write_str(
288
4
                "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \
289
4
                and using `serde_stacker` to protect against a stack overflow",
290
            ),
291
4
            Error::ExpectedStructName(ref name) => write!(
292
4
                f,
293
4
                "Expected the explicit struct name {}, but none was found",
294
4
                Identifier(name)
295
            ),
296
        }
297
2190
    }
298
}
299

            
300
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
301
pub struct Position {
302
    pub line: usize,
303
    pub col: usize,
304
}
305

            
306
impl Position {
307
222846
    pub(crate) fn from_src_end(src: &str) -> Position {
308
3947205
        let line = 1 + src.chars().filter(|&c| c == '\n').count();
309
2038951
        let col = 1 + src.chars().rev().take_while(|&c| c != '\n').count();
310

            
311
222846
        Self { line, col }
312
222846
    }
313
}
314

            
315
impl fmt::Display for Position {
316
1946
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
317
1946
        write!(f, "{}:{}", self.line, self.col)
318
1946
    }
319
}
320

            
321
#[derive(Clone, Debug, PartialEq, Eq)]
322
/// Spans select a range of text between two positions.
323
/// Spans are used in [`SpannedError`] to indicate the start and end positions
324
/// of the parser cursor before and after it encountered an error in parsing.
325
pub struct Span {
326
    pub start: Position,
327
    pub end: Position,
328
}
329

            
330
impl fmt::Display for Span {
331
1390
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
332
1390
        if self.start == self.end {
333
834
            write!(f, "{}", self.start)
334
        } else {
335
556
            write!(f, "{}-{}", self.start, self.end)
336
        }
337
1390
    }
338
}
339

            
340
impl ser::Error for Error {
341
    #[cold]
342
14
    fn custom<T: fmt::Display>(msg: T) -> Self {
343
14
        Error::Message(msg.to_string())
344
14
    }
345
}
346

            
347
impl de::Error for Error {
348
    #[cold]
349
345
    fn custom<T: fmt::Display>(msg: T) -> Self {
350
345
        Error::Message(msg.to_string())
351
345
    }
352

            
353
    #[cold]
354
18153
    fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
355
        // Invalid type and invalid value are merged given their similarity in ron
356
18153
        Self::invalid_value(unexp, exp)
357
18153
    }
358

            
359
    #[cold]
360
19479
    fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
361
        struct UnexpectedSerdeTypeValue<'a>(de::Unexpected<'a>);
362

            
363
        impl<'a> fmt::Display for UnexpectedSerdeTypeValue<'a> {
364
19479
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
365
19479
                match self.0 {
366
12
                    de::Unexpected::Bool(b) => write!(f, "the boolean `{}`", b),
367
4658
                    de::Unexpected::Unsigned(i) => write!(f, "the unsigned integer `{}`", i),
368
                    de::Unexpected::Signed(i) => write!(f, "the signed integer `{}`", i),
369
                    de::Unexpected::Float(n) => write!(f, "the floating point number `{}`", n),
370
                    de::Unexpected::Char(c) => write!(f, "the UTF-8 character `{}`", c),
371
3336
                    de::Unexpected::Str(s) => write!(f, "the string {:?}", s),
372
278
                    de::Unexpected::Bytes(b) => write!(f, "the byte string b\"{}\"", {
373
278
                        b.iter()
374
1112
                            .flat_map(|c| core::ascii::escape_default(*c))
375
278
                            .map(char::from)
376
278
                            .collect::<String>()
377
                    }),
378
3268
                    de::Unexpected::Unit => write!(f, "a unit value"),
379
                    de::Unexpected::Option => write!(f, "an optional value"),
380
                    de::Unexpected::NewtypeStruct => write!(f, "a newtype struct"),
381
1946
                    de::Unexpected::Seq => write!(f, "a sequence"),
382
5282
                    de::Unexpected::Map => write!(f, "a map"),
383
4
                    de::Unexpected::Enum => write!(f, "an enum"),
384
                    de::Unexpected::UnitVariant => write!(f, "a unit variant"),
385
                    de::Unexpected::NewtypeVariant => write!(f, "a newtype variant"),
386
                    de::Unexpected::TupleVariant => write!(f, "a tuple variant"),
387
                    de::Unexpected::StructVariant => write!(f, "a struct variant"),
388
695
                    de::Unexpected::Other(other) => f.write_str(other),
389
                }
390
19479
            }
391
        }
392

            
393
19479
        Error::InvalidValueForType {
394
19479
            expected: exp.to_string(),
395
19479
            found: UnexpectedSerdeTypeValue(unexp).to_string(),
396
19479
        }
397
19479
    }
398

            
399
    #[cold]
400
778
    fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self {
401
778
        Error::ExpectedDifferentLength {
402
778
            expected: exp.to_string(),
403
778
            found: len,
404
778
        }
405
778
    }
406

            
407
    #[cold]
408
1258
    fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
409
1258
        Error::NoSuchEnumVariant {
410
1258
            expected,
411
1258
            found: variant.to_string(),
412
1258
            outer: None,
413
1258
        }
414
1258
    }
415

            
416
    #[cold]
417
3068
    fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
418
3068
        Error::NoSuchStructField {
419
3068
            expected,
420
3068
            found: field.to_string(),
421
3068
            outer: None,
422
3068
        }
423
3068
    }
424

            
425
    #[cold]
426
4736
    fn missing_field(field: &'static str) -> Self {
427
4736
        Error::MissingStructField { field, outer: None }
428
4736
    }
429

            
430
    #[cold]
431
3000
    fn duplicate_field(field: &'static str) -> Self {
432
3000
        Error::DuplicateStructField { field, outer: None }
433
3000
    }
434
}
435

            
436
impl StdError for SpannedError {}
437

            
438
impl StdError for Error {}
439

            
440
impl From<Utf8Error> for Error {
441
556
    fn from(e: Utf8Error) -> Self {
442
556
        Error::Utf8Error(e)
443
556
    }
444
}
445

            
446
impl From<fmt::Error> for Error {
447
4
    fn from(_: fmt::Error) -> Self {
448
4
        Error::Fmt
449
4
    }
450
}
451

            
452
#[cfg(feature = "std")]
453
impl From<io::Error> for Error {
454
838
    fn from(e: io::Error) -> Self {
455
838
        Error::Io(e.to_string())
456
838
    }
457
}
458

            
459
impl From<SpannedError> for Error {
460
8
    fn from(e: SpannedError) -> Self {
461
8
        e.code
462
8
    }
463
}
464

            
465
struct OneOf {
466
    alts: &'static [&'static str],
467
    none: &'static str,
468
}
469

            
470
impl fmt::Display for OneOf {
471
20
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472
20
        match self.alts {
473
20
            [] => write!(f, "there are no {}", self.none),
474
4
            [a1] => write!(f, "expected {} instead", Identifier(a1)),
475
4
            [a1, a2] => write!(
476
4
                f,
477
4
                "expected either {} or {} instead",
478
4
                Identifier(a1),
479
4
                Identifier(a2)
480
            ),
481
4
            [a1, ref alts @ .., an] => {
482
4
                write!(f, "expected one of {}", Identifier(a1))?;
483

            
484
8
                for alt in alts {
485
4
                    write!(f, ", {}", Identifier(alt))?;
486
                }
487

            
488
4
                write!(f, ", or {} instead", Identifier(an))
489
            }
490
        }
491
20
    }
492
}
493

            
494
struct Identifier<'a>(&'a str);
495

            
496
impl<'a> fmt::Display for Identifier<'a> {
497
100
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
498
100
        if self.0.is_empty() || !self.0.chars().all(is_ident_raw_char) {
499
4
            return write!(f, "{:?}_[invalid identifier]", self.0);
500
96
        }
501

            
502
96
        let mut chars = self.0.chars();
503

            
504
96
        if !chars.next().map_or(false, is_ident_first_char) || !chars.all(is_xid_continue) {
505
24
            write!(f, "`r#{}`", self.0)
506
        } else {
507
72
            write!(f, "`{}`", self.0)
508
        }
509
100
    }
510
}
511

            
512
#[cfg(test)]
513
mod tests {
514
    use alloc::{format, string::String};
515

            
516
    use serde::{de::Error as DeError, de::Unexpected, ser::Error as SerError};
517

            
518
    use super::{Error, Position, Span, SpannedError};
519

            
520
    #[test]
521
4
    fn error_messages() {
522
4
        check_error_message(&Error::from(core::fmt::Error), "Formatting RON failed");
523
        #[cfg(feature = "std")]
524
4
        check_error_message(
525
4
            &Error::from(std::io::Error::new(
526
4
                std::io::ErrorKind::InvalidData,
527
4
                "my-error",
528
4
            )),
529
4
            "my-error",
530
        );
531
4
        check_error_message(&<Error as SerError>::custom("my-ser-error"), "my-ser-error");
532
4
        check_error_message(&<Error as DeError>::custom("my-de-error"), "my-de-error");
533
        #[allow(deprecated)]
534
4
        check_error_message(
535
4
            &Error::Base64Error(base64::DecodeError::InvalidPadding),
536
4
            "Invalid base64: Invalid padding",
537
        );
538
4
        check_error_message(&Error::Eof, "Unexpected end of RON");
539
4
        check_error_message(&Error::ExpectedArray, "Expected opening `[`");
540
4
        check_error_message(&Error::ExpectedArrayEnd, "Expected closing `]`");
541
4
        check_error_message(
542
4
            &Error::ExpectedAttribute,
543
4
            "Expected an `#![enable(...)]` attribute",
544
        );
545
4
        check_error_message(
546
4
            &Error::ExpectedAttributeEnd,
547
4
            "Expected closing `)]` after the enable attribute",
548
        );
549
4
        check_error_message(&Error::ExpectedBoolean, "Expected boolean");
550
4
        check_error_message(&Error::ExpectedComma, "Expected comma");
551
4
        check_error_message(&Error::ExpectedChar, "Expected char");
552
4
        check_error_message(&Error::ExpectedByteLiteral, "Expected byte literal");
553
4
        check_error_message(&Error::ExpectedFloat, "Expected float");
554
4
        check_error_message(&Error::FloatUnderscore, "Unexpected underscore in float");
555
4
        check_error_message(&Error::ExpectedInteger, "Expected integer");
556
4
        check_error_message(&Error::ExpectedOption, "Expected option");
557
4
        check_error_message(&Error::ExpectedOptionEnd, "Expected closing `)`");
558
4
        check_error_message(&Error::ExpectedStructLikeEnd, "Expected closing `)`");
559
4
        check_error_message(&Error::ExpectedMap, "Expected opening `{`");
560
4
        check_error_message(&Error::ExpectedMapColon, "Expected colon");
561
4
        check_error_message(&Error::ExpectedMapEnd, "Expected closing `}`");
562
4
        check_error_message(
563
4
            &Error::ExpectedDifferentStructName {
564
4
                expected: "raw+identifier",
565
4
                found: String::from("identifier"),
566
4
            },
567
4
            "Expected struct `r#raw+identifier` but found `identifier`",
568
        );
569
4
        check_error_message(&Error::ExpectedStructLike, "Expected opening `(`");
570
4
        check_error_message(
571
4
            &Error::ExpectedNamedStructLike(""),
572
4
            "Expected only opening `(`, no name, for un-nameable struct",
573
        );
574
4
        check_error_message(
575
4
            &Error::ExpectedNamedStructLike("_ident"),
576
4
            "Expected opening `(` for struct `_ident`",
577
        );
578
4
        check_error_message(&Error::ExpectedUnit, "Expected unit");
579
4
        check_error_message(&Error::ExpectedString, "Expected string");
580
4
        check_error_message(&Error::ExpectedByteString, "Expected byte string");
581
4
        check_error_message(&Error::ExpectedStringEnd, "Expected end of string");
582
4
        check_error_message(&Error::ExpectedIdentifier, "Expected identifier");
583
4
        check_error_message(&Error::InvalidEscape("Invalid escape"), "Invalid escape");
584
4
        check_error_message(&Error::IntegerOutOfBounds, "Integer is out of bounds");
585
4
        check_error_message(
586
4
            &Error::InvalidIntegerDigit {
587
4
                digit: 'q',
588
4
                base: 16,
589
4
            },
590
4
            "Invalid digit 'q' for base 16 integers",
591
        );
592
4
        check_error_message(
593
4
            &Error::NoSuchExtension(String::from("unknown")),
594
4
            "No RON extension named `unknown`",
595
        );
596
4
        check_error_message(&Error::UnclosedBlockComment, "Unclosed block comment");
597
4
        check_error_message(
598
4
            &Error::UnclosedLineComment,
599
4
            "`ron::value::RawValue` cannot end in unclosed line comment, \
600
4
        try using a block comment or adding a newline",
601
        );
602
4
        check_error_message(
603
4
            &Error::UnderscoreAtBeginning,
604
4
            "Unexpected leading underscore in a number",
605
        );
606
4
        check_error_message(&Error::UnexpectedChar('🦀'), "Unexpected char \'🦀\'");
607
        #[allow(invalid_from_utf8)]
608
4
        check_error_message(
609
4
            &Error::Utf8Error(core::str::from_utf8(b"error: \xff\xff\xff\xff").unwrap_err()),
610
4
            "invalid utf-8 sequence of 1 bytes from index 7",
611
        );
612
4
        check_error_message(
613
4
            &Error::TrailingCharacters,
614
4
            "Non-whitespace trailing characters",
615
        );
616
4
        check_error_message(
617
4
            &Error::invalid_value(Unexpected::Enum, &"struct `Hi`"),
618
4
            "Expected struct `Hi` but found an enum instead",
619
        );
620
4
        check_error_message(
621
4
            &Error::invalid_length(0, &"two bees"),
622
4
            "Expected two bees but found zero elements instead",
623
        );
624
4
        check_error_message(
625
4
            &Error::invalid_length(1, &"two bees"),
626
4
            "Expected two bees but found one element instead",
627
        );
628
4
        check_error_message(
629
4
            &Error::invalid_length(3, &"two bees"),
630
4
            "Expected two bees but found 3 elements instead",
631
        );
632
4
        check_error_message(
633
4
            &Error::unknown_variant("unknown", &[]),
634
4
            "Unexpected enum variant named `unknown`, there are no variants",
635
        );
636
4
        check_error_message(
637
4
            &Error::NoSuchEnumVariant {
638
4
                expected: &["A", "B+C"],
639
4
                found: String::from("D"),
640
4
                outer: Some(String::from("E")),
641
4
            },
642
4
            "Unexpected variant named `D` in enum `E`, \
643
4
            expected either `A` or `r#B+C` instead",
644
        );
645
4
        check_error_message(
646
4
            &Error::unknown_field("unknown", &[]),
647
4
            "Unexpected field named `unknown`, there are no fields",
648
        );
649
4
        check_error_message(
650
4
            &Error::NoSuchStructField {
651
4
                expected: &["a"],
652
4
                found: String::from("b"),
653
4
                outer: Some(String::from("S")),
654
4
            },
655
4
            "Unexpected field named `b` in `S`, expected `a` instead",
656
        );
657
4
        check_error_message(
658
4
            &Error::NoSuchStructField {
659
4
                expected: &["a", "b+c", "d"],
660
4
                found: String::from("e"),
661
4
                outer: Some(String::from("S")),
662
4
            },
663
4
            "Unexpected field named `e` in `S`, \
664
4
            expected one of `a`, `r#b+c`, or `d` instead",
665
        );
666
4
        check_error_message(
667
4
            &Error::missing_field("a"),
668
4
            "Unexpected missing field named `a`",
669
        );
670
4
        check_error_message(
671
4
            &Error::MissingStructField {
672
4
                field: "",
673
4
                outer: Some(String::from("S+T")),
674
4
            },
675
4
            "Unexpected missing field named \"\"_[invalid identifier] in `r#S+T`",
676
        );
677
4
        check_error_message(
678
4
            &Error::duplicate_field("a"),
679
4
            "Unexpected duplicate field named `a`",
680
        );
681
4
        check_error_message(
682
4
            &Error::DuplicateStructField {
683
4
                field: "b+c",
684
4
                outer: Some(String::from("S+T")),
685
4
            },
686
4
            "Unexpected duplicate field named `r#b+c` in `r#S+T`",
687
        );
688
4
        check_error_message(
689
4
            &Error::InvalidIdentifier(String::from("why+🦀+not")),
690
4
            "Invalid identifier \"why+🦀+not\"",
691
        );
692
4
        check_error_message(
693
4
            &Error::SuggestRawIdentifier(String::from("raw+ident")),
694
4
            "Found invalid std identifier \"raw+ident\", \
695
4
            try the raw identifier `r#raw+ident` instead",
696
        );
697
4
        check_error_message(
698
4
            &Error::ExpectedRawValue,
699
4
            "Expected a `ron::value::RawValue`",
700
        );
701
4
        check_error_message(
702
4
            &Error::ExceededRecursionLimit,
703
4
            "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \
704
4
            and using `serde_stacker` to protect against a stack overflow",
705
        );
706
4
        check_error_message(
707
4
            &Error::ExpectedStructName(String::from("Struct")),
708
4
            "Expected the explicit struct name `Struct`, but none was found",
709
        );
710
4
    }
711

            
712
240
    fn check_error_message<T: core::fmt::Display>(err: &T, msg: &str) {
713
240
        assert_eq!(format!("{}", err), msg);
714
240
    }
715

            
716
    #[test]
717
4
    fn spanned_error_into_code() {
718
4
        assert_eq!(
719
4
            Error::from(SpannedError {
720
4
                code: Error::Eof,
721
4
                span: Span {
722
4
                    start: Position { line: 1, col: 1 },
723
4
                    end: Position { line: 1, col: 5 },
724
4
                }
725
4
            }),
726
            Error::Eof
727
        );
728
4
        assert_eq!(
729
4
            Error::from(SpannedError {
730
4
                code: Error::ExpectedRawValue,
731
4
                span: Span {
732
4
                    start: Position { line: 1, col: 1 },
733
4
                    end: Position { line: 1, col: 5 },
734
4
                }
735
4
            }),
736
            Error::ExpectedRawValue
737
        );
738
4
    }
739
}