1
use std::{
2
    error::Error as StdError,
3
    fmt, io,
4
    str::{self, Utf8Error},
5
};
6

            
7
use serde::{de, ser};
8
use unicode_ident::is_xid_continue;
9

            
10
use crate::parse::{is_ident_first_char, is_ident_raw_char};
11

            
12
/// This type represents all possible errors that can occur when
13
/// serializing or deserializing RON data.
14
#[allow(clippy::module_name_repetitions)]
15
#[derive(Clone, Debug, PartialEq, Eq)]
16
pub struct SpannedError {
17
    pub code: Error,
18
    pub position: Position,
19
}
20

            
21
pub type Result<T, E = Error> = std::result::Result<T, E>;
22
pub type SpannedResult<T> = std::result::Result<T, SpannedError>;
23

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

            
65
    InvalidEscape(&'static str),
66

            
67
    IntegerOutOfBounds,
68
    InvalidIntegerDigit {
69
        digit: char,
70
        base: u8,
71
    },
72

            
73
    NoSuchExtension(String),
74

            
75
    UnclosedBlockComment,
76
    UnclosedLineComment,
77
    UnderscoreAtBeginning,
78
    UnexpectedChar(char),
79

            
80
    Utf8Error(Utf8Error),
81
    TrailingCharacters,
82

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

            
116
impl fmt::Display for SpannedError {
117
548
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118
548
        write!(f, "{}: {}", self.position, self.code)
119
548
    }
120
}
121

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

            
204
12
                match found {
205
4
                    0 => f.write_str("zero elements")?,
206
4
                    1 => f.write_str("one element")?,
207
4
                    n => write!(f, "{} elements", n)?,
208
                }
209

            
210
12
                f.write_str(" instead")
211
            }
212
            Error::NoSuchEnumVariant {
213
8
                expected,
214
8
                ref found,
215
8
                ref outer,
216
8
            } => {
217
8
                f.write_str("Unexpected ")?;
218

            
219
8
                if outer.is_none() {
220
4
                    f.write_str("enum ")?;
221
4
                }
222

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

            
225
8
                if let Some(outer) = outer {
226
4
                    write!(f, " in enum {}", Identifier(outer))?;
227
4
                }
228

            
229
8
                write!(
230
8
                    f,
231
8
                    ", {}",
232
8
                    OneOf {
233
8
                        alts: expected,
234
8
                        none: "variants"
235
8
                    }
236
8
                )
237
            }
238
            Error::NoSuchStructField {
239
12
                expected,
240
12
                ref found,
241
12
                ref outer,
242
12
            } => {
243
12
                write!(f, "Unexpected field named {}", Identifier(found))?;
244

            
245
12
                if let Some(outer) = outer {
246
8
                    write!(f, " in {}", Identifier(outer))?;
247
4
                }
248

            
249
12
                write!(
250
12
                    f,
251
12
                    ", {}",
252
12
                    OneOf {
253
12
                        alts: expected,
254
12
                        none: "fields"
255
12
                    }
256
12
                )
257
            }
258
8
            Error::MissingStructField { field, ref outer } => {
259
8
                write!(f, "Unexpected missing field named {}", Identifier(field))?;
260

            
261
8
                match outer {
262
4
                    Some(outer) => write!(f, " in {}", Identifier(outer)),
263
4
                    None => Ok(()),
264
                }
265
            }
266
8
            Error::DuplicateStructField { field, ref outer } => {
267
8
                write!(f, "Unexpected duplicate field named {}", Identifier(field))?;
268

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

            
294
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
295
pub struct Position {
296
    pub line: usize,
297
    pub col: usize,
298
}
299

            
300
impl Position {
301
106551
    pub(crate) fn from_src_end(src: &str) -> Position {
302
1921644
        let line = 1 + src.chars().filter(|&c| c == '\n').count();
303
965560
        let col = 1 + src.chars().rev().take_while(|&c| c != '\n').count();
304
106551

            
305
106551
        Self { line, col }
306
106551
    }
307
}
308

            
309
impl fmt::Display for Position {
310
1370
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311
1370
        write!(f, "{}:{}", self.line, self.col)
312
1370
    }
313
}
314

            
315
impl ser::Error for Error {
316
    #[cold]
317
14
    fn custom<T: fmt::Display>(msg: T) -> Self {
318
14
        Error::Message(msg.to_string())
319
14
    }
320
}
321

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

            
328
    #[cold]
329
17685
    fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
330
17685
        // Invalid type and invalid value are merged given their similarity in ron
331
17685
        Self::invalid_value(unexp, exp)
332
17685
    }
333

            
334
    #[cold]
335
18785
    fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
336
        struct UnexpectedSerdeTypeValue<'a>(de::Unexpected<'a>);
337

            
338
        impl<'a> fmt::Display for UnexpectedSerdeTypeValue<'a> {
339
18785
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340
18785
                match self.0 {
341
12
                    de::Unexpected::Bool(b) => write!(f, "the boolean `{}`", b),
342
4384
                    de::Unexpected::Unsigned(i) => write!(f, "the unsigned integer `{}`", i),
343
                    de::Unexpected::Signed(i) => write!(f, "the signed integer `{}`", i),
344
                    de::Unexpected::Float(n) => write!(f, "the floating point number `{}`", n),
345
                    de::Unexpected::Char(c) => write!(f, "the UTF-8 character `{}`", c),
346
3288
                    de::Unexpected::Str(s) => write!(f, "the string {:?}", s),
347
274
                    de::Unexpected::Bytes(b) => write!(f, "the byte string b\"{}\"", {
348
274
                        b.iter()
349
1096
                            .flat_map(|c| std::ascii::escape_default(*c))
350
274
                            .map(char::from)
351
274
                            .collect::<String>()
352
274
                    }),
353
3014
                    de::Unexpected::Unit => write!(f, "a unit value"),
354
                    de::Unexpected::Option => write!(f, "an optional value"),
355
                    de::Unexpected::NewtypeStruct => write!(f, "a newtype struct"),
356
1918
                    de::Unexpected::Seq => write!(f, "a sequence"),
357
5206
                    de::Unexpected::Map => write!(f, "a map"),
358
4
                    de::Unexpected::Enum => write!(f, "an enum"),
359
                    de::Unexpected::UnitVariant => write!(f, "a unit variant"),
360
                    de::Unexpected::NewtypeVariant => write!(f, "a newtype variant"),
361
                    de::Unexpected::TupleVariant => write!(f, "a tuple variant"),
362
                    de::Unexpected::StructVariant => write!(f, "a struct variant"),
363
685
                    de::Unexpected::Other(other) => f.write_str(other),
364
                }
365
18785
            }
366
        }
367

            
368
18785
        Error::InvalidValueForType {
369
18785
            expected: exp.to_string(),
370
18785
            found: UnexpectedSerdeTypeValue(unexp).to_string(),
371
18785
        }
372
18785
    }
373

            
374
    #[cold]
375
560
    fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self {
376
560
        Error::ExpectedDifferentLength {
377
560
            expected: exp.to_string(),
378
560
            found: len,
379
560
        }
380
560
    }
381

            
382
    #[cold]
383
826
    fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
384
826
        Error::NoSuchEnumVariant {
385
826
            expected,
386
826
            found: variant.to_string(),
387
826
            outer: None,
388
826
        }
389
826
    }
390

            
391
    #[cold]
392
2196
    fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
393
2196
        Error::NoSuchStructField {
394
2196
            expected,
395
2196
            found: field.to_string(),
396
2196
            outer: None,
397
2196
        }
398
2196
    }
399

            
400
    #[cold]
401
3840
    fn missing_field(field: &'static str) -> Self {
402
3840
        Error::MissingStructField { field, outer: None }
403
3840
    }
404

            
405
    #[cold]
406
1922
    fn duplicate_field(field: &'static str) -> Self {
407
1922
        Error::DuplicateStructField { field, outer: None }
408
1922
    }
409
}
410

            
411
impl StdError for SpannedError {}
412
impl StdError for Error {}
413

            
414
impl From<Utf8Error> for Error {
415
548
    fn from(e: Utf8Error) -> Self {
416
548
        Error::Utf8Error(e)
417
548
    }
418
}
419

            
420
impl From<fmt::Error> for Error {
421
4
    fn from(_: fmt::Error) -> Self {
422
4
        Error::Fmt
423
4
    }
424
}
425

            
426
impl From<io::Error> for Error {
427
826
    fn from(e: io::Error) -> Self {
428
826
        Error::Io(e.to_string())
429
826
    }
430
}
431

            
432
impl From<SpannedError> for Error {
433
8
    fn from(e: SpannedError) -> Self {
434
8
        e.code
435
8
    }
436
}
437

            
438
struct OneOf {
439
    alts: &'static [&'static str],
440
    none: &'static str,
441
}
442

            
443
impl fmt::Display for OneOf {
444
20
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445
20
        match self.alts {
446
20
            [] => write!(f, "there are no {}", self.none),
447
4
            [a1] => write!(f, "expected {} instead", Identifier(a1)),
448
4
            [a1, a2] => write!(
449
4
                f,
450
4
                "expected either {} or {} instead",
451
4
                Identifier(a1),
452
4
                Identifier(a2)
453
4
            ),
454
4
            [a1, ref alts @ .., an] => {
455
4
                write!(f, "expected one of {}", Identifier(a1))?;
456

            
457
8
                for alt in alts {
458
4
                    write!(f, ", {}", Identifier(alt))?;
459
                }
460

            
461
4
                write!(f, ", or {} instead", Identifier(an))
462
            }
463
        }
464
20
    }
465
}
466

            
467
struct Identifier<'a>(&'a str);
468

            
469
impl<'a> fmt::Display for Identifier<'a> {
470
100
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471
100
        if self.0.is_empty() || !self.0.chars().all(is_ident_raw_char) {
472
4
            return write!(f, "{:?}_[invalid identifier]", self.0);
473
96
        }
474
96

            
475
96
        let mut chars = self.0.chars();
476
96

            
477
96
        if !chars.next().map_or(false, is_ident_first_char) || !chars.all(is_xid_continue) {
478
24
            write!(f, "`r#{}`", self.0)
479
        } else {
480
72
            write!(f, "`{}`", self.0)
481
        }
482
100
    }
483
}
484

            
485
#[cfg(test)]
486
mod tests {
487
    use serde::{de::Error as DeError, de::Unexpected, ser::Error as SerError};
488

            
489
    use super::{Error, Position, SpannedError};
490

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

            
682
240
    fn check_error_message<T: std::fmt::Display>(err: &T, msg: &str) {
683
240
        assert_eq!(format!("{}", err), msg);
684
240
    }
685

            
686
    #[test]
687
4
    fn spanned_error_into_code() {
688
4
        assert_eq!(
689
4
            Error::from(SpannedError {
690
4
                code: Error::Eof,
691
4
                position: Position { line: 1, col: 1 }
692
4
            }),
693
4
            Error::Eof
694
4
        );
695
4
        assert_eq!(
696
4
            Error::from(SpannedError {
697
4
                code: Error::ExpectedRawValue,
698
4
                position: Position { line: 1, col: 1 }
699
4
            }),
700
4
            Error::ExpectedRawValue
701
4
        );
702
4
    }
703
}