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 position: Position,
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
556
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124
556
        write!(f, "{}: {}", self.position, self.code)
125
556
    }
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
4
            ),
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
4
            ),
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
8
            } => {
202
8
                write!(f, "Expected {} but found {} instead", expected, found)
203
            }
204
            Error::ExpectedDifferentLength {
205
12
                ref expected,
206
12
                found,
207
12
            } => {
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
8
            } => {
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
8
                )
243
            }
244
            Error::NoSuchStructField {
245
12
                expected,
246
12
                ref found,
247
12
                ref outer,
248
12
            } => {
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
12
                )
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
4
                identifier, identifier
285
4
            ),
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
4
            ),
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
4
            ),
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
108101
    pub(crate) fn from_src_end(src: &str) -> Position {
308
1949668
        let line = 1 + src.chars().filter(|&c| c == '\n').count();
309
979632
        let col = 1 + src.chars().rev().take_while(|&c| c != '\n').count();
310
108101

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

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

            
321
impl ser::Error for Error {
322
    #[cold]
323
14
    fn custom<T: fmt::Display>(msg: T) -> Self {
324
14
        Error::Message(msg.to_string())
325
14
    }
326
}
327

            
328
impl de::Error for Error {
329
    #[cold]
330
342
    fn custom<T: fmt::Display>(msg: T) -> Self {
331
342
        Error::Message(msg.to_string())
332
342
    }
333

            
334
    #[cold]
335
17943
    fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
336
17943
        // Invalid type and invalid value are merged given their similarity in ron
337
17943
        Self::invalid_value(unexp, exp)
338
17943
    }
339

            
340
    #[cold]
341
19059
    fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
342
        struct UnexpectedSerdeTypeValue<'a>(de::Unexpected<'a>);
343

            
344
        impl<'a> fmt::Display for UnexpectedSerdeTypeValue<'a> {
345
19059
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
346
19059
                match self.0 {
347
12
                    de::Unexpected::Bool(b) => write!(f, "the boolean `{}`", b),
348
4448
                    de::Unexpected::Unsigned(i) => write!(f, "the unsigned integer `{}`", i),
349
                    de::Unexpected::Signed(i) => write!(f, "the signed integer `{}`", i),
350
                    de::Unexpected::Float(n) => write!(f, "the floating point number `{}`", n),
351
                    de::Unexpected::Char(c) => write!(f, "the UTF-8 character `{}`", c),
352
3336
                    de::Unexpected::Str(s) => write!(f, "the string {:?}", s),
353
278
                    de::Unexpected::Bytes(b) => write!(f, "the byte string b\"{}\"", {
354
278
                        b.iter()
355
1112
                            .flat_map(|c| core::ascii::escape_default(*c))
356
278
                            .map(char::from)
357
278
                            .collect::<String>()
358
278
                    }),
359
3058
                    de::Unexpected::Unit => write!(f, "a unit value"),
360
                    de::Unexpected::Option => write!(f, "an optional value"),
361
                    de::Unexpected::NewtypeStruct => write!(f, "a newtype struct"),
362
1946
                    de::Unexpected::Seq => write!(f, "a sequence"),
363
5282
                    de::Unexpected::Map => write!(f, "a map"),
364
4
                    de::Unexpected::Enum => write!(f, "an enum"),
365
                    de::Unexpected::UnitVariant => write!(f, "a unit variant"),
366
                    de::Unexpected::NewtypeVariant => write!(f, "a newtype variant"),
367
                    de::Unexpected::TupleVariant => write!(f, "a tuple variant"),
368
                    de::Unexpected::StructVariant => write!(f, "a struct variant"),
369
695
                    de::Unexpected::Other(other) => f.write_str(other),
370
                }
371
19059
            }
372
        }
373

            
374
19059
        Error::InvalidValueForType {
375
19059
            expected: exp.to_string(),
376
19059
            found: UnexpectedSerdeTypeValue(unexp).to_string(),
377
19059
        }
378
19059
    }
379

            
380
    #[cold]
381
568
    fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self {
382
568
        Error::ExpectedDifferentLength {
383
568
            expected: exp.to_string(),
384
568
            found: len,
385
568
        }
386
568
    }
387

            
388
    #[cold]
389
838
    fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
390
838
        Error::NoSuchEnumVariant {
391
838
            expected,
392
838
            found: variant.to_string(),
393
838
            outer: None,
394
838
        }
395
838
    }
396

            
397
    #[cold]
398
2228
    fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
399
2228
        Error::NoSuchStructField {
400
2228
            expected,
401
2228
            found: field.to_string(),
402
2228
            outer: None,
403
2228
        }
404
2228
    }
405

            
406
    #[cold]
407
3896
    fn missing_field(field: &'static str) -> Self {
408
3896
        Error::MissingStructField { field, outer: None }
409
3896
    }
410

            
411
    #[cold]
412
1950
    fn duplicate_field(field: &'static str) -> Self {
413
1950
        Error::DuplicateStructField { field, outer: None }
414
1950
    }
415
}
416

            
417
impl StdError for SpannedError {}
418

            
419
impl StdError for Error {}
420

            
421
impl From<Utf8Error> for Error {
422
556
    fn from(e: Utf8Error) -> Self {
423
556
        Error::Utf8Error(e)
424
556
    }
425
}
426

            
427
impl From<fmt::Error> for Error {
428
4
    fn from(_: fmt::Error) -> Self {
429
4
        Error::Fmt
430
4
    }
431
}
432

            
433
#[cfg(feature = "std")]
434
impl From<io::Error> for Error {
435
838
    fn from(e: io::Error) -> Self {
436
838
        Error::Io(e.to_string())
437
838
    }
438
}
439

            
440
impl From<SpannedError> for Error {
441
8
    fn from(e: SpannedError) -> Self {
442
8
        e.code
443
8
    }
444
}
445

            
446
struct OneOf {
447
    alts: &'static [&'static str],
448
    none: &'static str,
449
}
450

            
451
impl fmt::Display for OneOf {
452
20
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
453
20
        match self.alts {
454
20
            [] => write!(f, "there are no {}", self.none),
455
4
            [a1] => write!(f, "expected {} instead", Identifier(a1)),
456
4
            [a1, a2] => write!(
457
4
                f,
458
4
                "expected either {} or {} instead",
459
4
                Identifier(a1),
460
4
                Identifier(a2)
461
4
            ),
462
4
            [a1, ref alts @ .., an] => {
463
4
                write!(f, "expected one of {}", Identifier(a1))?;
464

            
465
8
                for alt in alts {
466
4
                    write!(f, ", {}", Identifier(alt))?;
467
                }
468

            
469
4
                write!(f, ", or {} instead", Identifier(an))
470
            }
471
        }
472
20
    }
473
}
474

            
475
struct Identifier<'a>(&'a str);
476

            
477
impl<'a> fmt::Display for Identifier<'a> {
478
100
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
479
100
        if self.0.is_empty() || !self.0.chars().all(is_ident_raw_char) {
480
4
            return write!(f, "{:?}_[invalid identifier]", self.0);
481
96
        }
482
96

            
483
96
        let mut chars = self.0.chars();
484
96

            
485
96
        if !chars.next().map_or(false, is_ident_first_char) || !chars.all(is_xid_continue) {
486
24
            write!(f, "`r#{}`", self.0)
487
        } else {
488
72
            write!(f, "`{}`", self.0)
489
        }
490
100
    }
491
}
492

            
493
#[cfg(test)]
494
mod tests {
495
    use alloc::{format, string::String};
496

            
497
    use serde::{de::Error as DeError, de::Unexpected, ser::Error as SerError};
498

            
499
    use super::{Error, Position, SpannedError};
500

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

            
693
240
    fn check_error_message<T: core::fmt::Display>(err: &T, msg: &str) {
694
240
        assert_eq!(format!("{}", err), msg);
695
240
    }
696

            
697
    #[test]
698
4
    fn spanned_error_into_code() {
699
4
        assert_eq!(
700
4
            Error::from(SpannedError {
701
4
                code: Error::Eof,
702
4
                position: Position { line: 1, col: 1 }
703
4
            }),
704
4
            Error::Eof
705
4
        );
706
4
        assert_eq!(
707
4
            Error::from(SpannedError {
708
4
                code: Error::ExpectedRawValue,
709
4
                position: Position { line: 1, col: 1 }
710
4
            }),
711
4
            Error::ExpectedRawValue
712
4
        );
713
4
    }
714
}