1use std::{
2 error::Error as StdError,
3 fmt, io,
4 str::{self, Utf8Error},
5};
6
7use serde::{de, ser};
8use unicode_ident::is_xid_continue;
9
10use crate::parse::{is_ident_first_char, is_ident_raw_char};
11
12#[allow(clippy::module_name_repetitions)]
15#[derive(Clone, Debug, PartialEq, Eq)]
16pub struct SpannedError {
17 pub code: Error,
18 pub position: Position,
19}
20
21pub type Result<T, E = Error> = std::result::Result<T, E>;
22pub type SpannedResult<T> = std::result::Result<T, SpannedError>;
23
24#[derive(Clone, Debug, PartialEq, Eq)]
25#[non_exhaustive]
26pub 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
116impl fmt::Display for SpannedError {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 write!(f, "{}: {}", self.position, self.code)
119 }
120}
121
122impl fmt::Display for Error {
123 #[allow(clippy::too_many_lines)]
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 match *self {
126 Error::Fmt => f.write_str("Formatting RON failed"),
127 Error::Io(ref s) | Error::Message(ref s) => f.write_str(s),
128 #[allow(deprecated)]
129 Error::Base64Error(ref e) => write!(f, "Invalid base64: {}", e),
130 Error::Eof => f.write_str("Unexpected end of RON"),
131 Error::ExpectedArray => f.write_str("Expected opening `[`"),
132 Error::ExpectedArrayEnd => f.write_str("Expected closing `]`"),
133 Error::ExpectedAttribute => f.write_str("Expected an `#![enable(...)]` attribute"),
134 Error::ExpectedAttributeEnd => {
135 f.write_str("Expected closing `)]` after the enable attribute")
136 }
137 Error::ExpectedBoolean => f.write_str("Expected boolean"),
138 Error::ExpectedComma => f.write_str("Expected comma"),
139 Error::ExpectedChar => f.write_str("Expected char"),
140 Error::ExpectedByteLiteral => f.write_str("Expected byte literal"),
141 Error::ExpectedFloat => f.write_str("Expected float"),
142 Error::FloatUnderscore => f.write_str("Unexpected underscore in float"),
143 Error::ExpectedInteger => f.write_str("Expected integer"),
144 Error::ExpectedOption => f.write_str("Expected option"),
145 Error::ExpectedOptionEnd | Error::ExpectedStructLikeEnd => {
146 f.write_str("Expected closing `)`")
147 }
148 Error::ExpectedMap => f.write_str("Expected opening `{`"),
149 Error::ExpectedMapColon => f.write_str("Expected colon"),
150 Error::ExpectedMapEnd => f.write_str("Expected closing `}`"),
151 Error::ExpectedDifferentStructName {
152 expected,
153 ref found,
154 } => write!(
155 f,
156 "Expected struct {} but found {}",
157 Identifier(expected),
158 Identifier(found)
159 ),
160 Error::ExpectedStructLike => f.write_str("Expected opening `(`"),
161 Error::ExpectedNamedStructLike(name) => {
162 if name.is_empty() {
163 f.write_str("Expected only opening `(`, no name, for un-nameable struct")
164 } else {
165 write!(f, "Expected opening `(` for struct {}", Identifier(name))
166 }
167 }
168 Error::ExpectedUnit => f.write_str("Expected unit"),
169 Error::ExpectedString => f.write_str("Expected string"),
170 Error::ExpectedByteString => f.write_str("Expected byte string"),
171 Error::ExpectedStringEnd => f.write_str("Expected end of string"),
172 Error::ExpectedIdentifier => f.write_str("Expected identifier"),
173 Error::InvalidEscape(s) => f.write_str(s),
174 Error::IntegerOutOfBounds => f.write_str("Integer is out of bounds"),
175 Error::InvalidIntegerDigit { digit, base } => {
176 write!(f, "Invalid digit {:?} for base {} integers", digit, base)
177 }
178 Error::NoSuchExtension(ref name) => {
179 write!(f, "No RON extension named {}", Identifier(name))
180 }
181 Error::Utf8Error(ref e) => fmt::Display::fmt(e, f),
182 Error::UnclosedBlockComment => f.write_str("Unclosed block comment"),
183 Error::UnclosedLineComment => f.write_str(
184 "`ron::value::RawValue` cannot end in unclosed line comment, \
185 try using a block comment or adding a newline",
186 ),
187 Error::UnderscoreAtBeginning => {
188 f.write_str("Unexpected leading underscore in a number")
189 }
190 Error::UnexpectedChar(c) => write!(f, "Unexpected char {:?}", c),
191 Error::TrailingCharacters => f.write_str("Non-whitespace trailing characters"),
192 Error::InvalidValueForType {
193 ref expected,
194 ref found,
195 } => {
196 write!(f, "Expected {} but found {} instead", expected, found)
197 }
198 Error::ExpectedDifferentLength {
199 ref expected,
200 found,
201 } => {
202 write!(f, "Expected {} but found ", expected)?;
203
204 match found {
205 0 => f.write_str("zero elements")?,
206 1 => f.write_str("one element")?,
207 n => write!(f, "{} elements", n)?,
208 }
209
210 f.write_str(" instead")
211 }
212 Error::NoSuchEnumVariant {
213 expected,
214 ref found,
215 ref outer,
216 } => {
217 f.write_str("Unexpected ")?;
218
219 if outer.is_none() {
220 f.write_str("enum ")?;
221 }
222
223 write!(f, "variant named {}", Identifier(found))?;
224
225 if let Some(outer) = outer {
226 write!(f, " in enum {}", Identifier(outer))?;
227 }
228
229 write!(
230 f,
231 ", {}",
232 OneOf {
233 alts: expected,
234 none: "variants"
235 }
236 )
237 }
238 Error::NoSuchStructField {
239 expected,
240 ref found,
241 ref outer,
242 } => {
243 write!(f, "Unexpected field named {}", Identifier(found))?;
244
245 if let Some(outer) = outer {
246 write!(f, " in {}", Identifier(outer))?;
247 }
248
249 write!(
250 f,
251 ", {}",
252 OneOf {
253 alts: expected,
254 none: "fields"
255 }
256 )
257 }
258 Error::MissingStructField { field, ref outer } => {
259 write!(f, "Unexpected missing field named {}", Identifier(field))?;
260
261 match outer {
262 Some(outer) => write!(f, " in {}", Identifier(outer)),
263 None => Ok(()),
264 }
265 }
266 Error::DuplicateStructField { field, ref outer } => {
267 write!(f, "Unexpected duplicate field named {}", Identifier(field))?;
268
269 match outer {
270 Some(outer) => write!(f, " in {}", Identifier(outer)),
271 None => Ok(()),
272 }
273 }
274 Error::InvalidIdentifier(ref invalid) => write!(f, "Invalid identifier {:?}", invalid),
275 Error::SuggestRawIdentifier(ref identifier) => write!(
276 f,
277 "Found invalid std identifier {:?}, try the raw identifier `r#{}` instead",
278 identifier, identifier
279 ),
280 Error::ExpectedRawValue => f.write_str("Expected a `ron::value::RawValue`"),
281 Error::ExceededRecursionLimit => f.write_str(
282 "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \
283 and using `serde_stacker` to protect against a stack overflow",
284 ),
285 Error::ExpectedStructName(ref name) => write!(
286 f,
287 "Expected the explicit struct name {}, but none was found",
288 Identifier(name)
289 ),
290 }
291 }
292}
293
294#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
295pub struct Position {
296 pub line: usize,
297 pub col: usize,
298}
299
300impl Position {
301 pub(crate) fn from_src_end(src: &str) -> Position {
302 let line = 1 + src.chars().filter(|&c| c == '\n').count();
303 let col = 1 + src.chars().rev().take_while(|&c| c != '\n').count();
304
305 Self { line, col }
306 }
307}
308
309impl fmt::Display for Position {
310 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311 write!(f, "{}:{}", self.line, self.col)
312 }
313}
314
315impl ser::Error for Error {
316 #[cold]
317 fn custom<T: fmt::Display>(msg: T) -> Self {
318 Error::Message(msg.to_string())
319 }
320}
321
322impl de::Error for Error {
323 #[cold]
324 fn custom<T: fmt::Display>(msg: T) -> Self {
325 Error::Message(msg.to_string())
326 }
327
328 #[cold]
329 fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
330 Self::invalid_value(unexp, exp)
332 }
333
334 #[cold]
335 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 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
340 match self.0 {
341 de::Unexpected::Bool(b) => write!(f, "the boolean `{}`", b),
342 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 de::Unexpected::Str(s) => write!(f, "the string {:?}", s),
347 de::Unexpected::Bytes(b) => write!(f, "the byte string b\"{}\"", {
348 b.iter()
349 .flat_map(|c| std::ascii::escape_default(*c))
350 .map(char::from)
351 .collect::<String>()
352 }),
353 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 de::Unexpected::Seq => write!(f, "a sequence"),
357 de::Unexpected::Map => write!(f, "a map"),
358 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 de::Unexpected::Other(other) => f.write_str(other),
364 }
365 }
366 }
367
368 Error::InvalidValueForType {
369 expected: exp.to_string(),
370 found: UnexpectedSerdeTypeValue(unexp).to_string(),
371 }
372 }
373
374 #[cold]
375 fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self {
376 Error::ExpectedDifferentLength {
377 expected: exp.to_string(),
378 found: len,
379 }
380 }
381
382 #[cold]
383 fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
384 Error::NoSuchEnumVariant {
385 expected,
386 found: variant.to_string(),
387 outer: None,
388 }
389 }
390
391 #[cold]
392 fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
393 Error::NoSuchStructField {
394 expected,
395 found: field.to_string(),
396 outer: None,
397 }
398 }
399
400 #[cold]
401 fn missing_field(field: &'static str) -> Self {
402 Error::MissingStructField { field, outer: None }
403 }
404
405 #[cold]
406 fn duplicate_field(field: &'static str) -> Self {
407 Error::DuplicateStructField { field, outer: None }
408 }
409}
410
411impl StdError for SpannedError {}
412impl StdError for Error {}
413
414impl From<Utf8Error> for Error {
415 fn from(e: Utf8Error) -> Self {
416 Error::Utf8Error(e)
417 }
418}
419
420impl From<fmt::Error> for Error {
421 fn from(_: fmt::Error) -> Self {
422 Error::Fmt
423 }
424}
425
426impl From<io::Error> for Error {
427 fn from(e: io::Error) -> Self {
428 Error::Io(e.to_string())
429 }
430}
431
432impl From<SpannedError> for Error {
433 fn from(e: SpannedError) -> Self {
434 e.code
435 }
436}
437
438struct OneOf {
439 alts: &'static [&'static str],
440 none: &'static str,
441}
442
443impl fmt::Display for OneOf {
444 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
445 match self.alts {
446 [] => write!(f, "there are no {}", self.none),
447 [a1] => write!(f, "expected {} instead", Identifier(a1)),
448 [a1, a2] => write!(
449 f,
450 "expected either {} or {} instead",
451 Identifier(a1),
452 Identifier(a2)
453 ),
454 [a1, ref alts @ .., an] => {
455 write!(f, "expected one of {}", Identifier(a1))?;
456
457 for alt in alts {
458 write!(f, ", {}", Identifier(alt))?;
459 }
460
461 write!(f, ", or {} instead", Identifier(an))
462 }
463 }
464 }
465}
466
467struct Identifier<'a>(&'a str);
468
469impl<'a> fmt::Display for Identifier<'a> {
470 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
471 if self.0.is_empty() || !self.0.chars().all(is_ident_raw_char) {
472 return write!(f, "{:?}_[invalid identifier]", self.0);
473 }
474
475 let mut chars = self.0.chars();
476
477 if !chars.next().map_or(false, is_ident_first_char) || !chars.all(is_xid_continue) {
478 write!(f, "`r#{}`", self.0)
479 } else {
480 write!(f, "`{}`", self.0)
481 }
482 }
483}
484
485#[cfg(test)]
486mod 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 fn error_messages() {
493 check_error_message(&Error::from(std::fmt::Error), "Formatting RON failed");
494 check_error_message(
495 &Error::from(std::io::Error::new(
496 std::io::ErrorKind::InvalidData,
497 "my-error",
498 )),
499 "my-error",
500 );
501 check_error_message(&<Error as SerError>::custom("my-ser-error"), "my-ser-error");
502 check_error_message(&<Error as DeError>::custom("my-de-error"), "my-de-error");
503 #[allow(deprecated)]
504 check_error_message(
505 &Error::Base64Error(base64::DecodeError::InvalidPadding),
506 "Invalid base64: Invalid padding",
507 );
508 check_error_message(&Error::Eof, "Unexpected end of RON");
509 check_error_message(&Error::ExpectedArray, "Expected opening `[`");
510 check_error_message(&Error::ExpectedArrayEnd, "Expected closing `]`");
511 check_error_message(
512 &Error::ExpectedAttribute,
513 "Expected an `#![enable(...)]` attribute",
514 );
515 check_error_message(
516 &Error::ExpectedAttributeEnd,
517 "Expected closing `)]` after the enable attribute",
518 );
519 check_error_message(&Error::ExpectedBoolean, "Expected boolean");
520 check_error_message(&Error::ExpectedComma, "Expected comma");
521 check_error_message(&Error::ExpectedChar, "Expected char");
522 check_error_message(&Error::ExpectedByteLiteral, "Expected byte literal");
523 check_error_message(&Error::ExpectedFloat, "Expected float");
524 check_error_message(&Error::FloatUnderscore, "Unexpected underscore in float");
525 check_error_message(&Error::ExpectedInteger, "Expected integer");
526 check_error_message(&Error::ExpectedOption, "Expected option");
527 check_error_message(&Error::ExpectedOptionEnd, "Expected closing `)`");
528 check_error_message(&Error::ExpectedStructLikeEnd, "Expected closing `)`");
529 check_error_message(&Error::ExpectedMap, "Expected opening `{`");
530 check_error_message(&Error::ExpectedMapColon, "Expected colon");
531 check_error_message(&Error::ExpectedMapEnd, "Expected closing `}`");
532 check_error_message(
533 &Error::ExpectedDifferentStructName {
534 expected: "raw+identifier",
535 found: String::from("identifier"),
536 },
537 "Expected struct `r#raw+identifier` but found `identifier`",
538 );
539 check_error_message(&Error::ExpectedStructLike, "Expected opening `(`");
540 check_error_message(
541 &Error::ExpectedNamedStructLike(""),
542 "Expected only opening `(`, no name, for un-nameable struct",
543 );
544 check_error_message(
545 &Error::ExpectedNamedStructLike("_ident"),
546 "Expected opening `(` for struct `_ident`",
547 );
548 check_error_message(&Error::ExpectedUnit, "Expected unit");
549 check_error_message(&Error::ExpectedString, "Expected string");
550 check_error_message(&Error::ExpectedByteString, "Expected byte string");
551 check_error_message(&Error::ExpectedStringEnd, "Expected end of string");
552 check_error_message(&Error::ExpectedIdentifier, "Expected identifier");
553 check_error_message(&Error::InvalidEscape("Invalid escape"), "Invalid escape");
554 check_error_message(&Error::IntegerOutOfBounds, "Integer is out of bounds");
555 check_error_message(
556 &Error::InvalidIntegerDigit {
557 digit: 'q',
558 base: 16,
559 },
560 "Invalid digit 'q' for base 16 integers",
561 );
562 check_error_message(
563 &Error::NoSuchExtension(String::from("unknown")),
564 "No RON extension named `unknown`",
565 );
566 check_error_message(&Error::UnclosedBlockComment, "Unclosed block comment");
567 check_error_message(
568 &Error::UnclosedLineComment,
569 "`ron::value::RawValue` cannot end in unclosed line comment, \
570 try using a block comment or adding a newline",
571 );
572 check_error_message(
573 &Error::UnderscoreAtBeginning,
574 "Unexpected leading underscore in a number",
575 );
576 check_error_message(&Error::UnexpectedChar('🦀'), "Unexpected char \'🦀\'");
577 #[allow(invalid_from_utf8)]
578 check_error_message(
579 &Error::Utf8Error(std::str::from_utf8(b"error: \xff\xff\xff\xff").unwrap_err()),
580 "invalid utf-8 sequence of 1 bytes from index 7",
581 );
582 check_error_message(
583 &Error::TrailingCharacters,
584 "Non-whitespace trailing characters",
585 );
586 check_error_message(
587 &Error::invalid_value(Unexpected::Enum, &"struct `Hi`"),
588 "Expected struct `Hi` but found an enum instead",
589 );
590 check_error_message(
591 &Error::invalid_length(0, &"two bees"),
592 "Expected two bees but found zero elements instead",
593 );
594 check_error_message(
595 &Error::invalid_length(1, &"two bees"),
596 "Expected two bees but found one element instead",
597 );
598 check_error_message(
599 &Error::invalid_length(3, &"two bees"),
600 "Expected two bees but found 3 elements instead",
601 );
602 check_error_message(
603 &Error::unknown_variant("unknown", &[]),
604 "Unexpected enum variant named `unknown`, there are no variants",
605 );
606 check_error_message(
607 &Error::NoSuchEnumVariant {
608 expected: &["A", "B+C"],
609 found: String::from("D"),
610 outer: Some(String::from("E")),
611 },
612 "Unexpected variant named `D` in enum `E`, \
613 expected either `A` or `r#B+C` instead",
614 );
615 check_error_message(
616 &Error::unknown_field("unknown", &[]),
617 "Unexpected field named `unknown`, there are no fields",
618 );
619 check_error_message(
620 &Error::NoSuchStructField {
621 expected: &["a"],
622 found: String::from("b"),
623 outer: Some(String::from("S")),
624 },
625 "Unexpected field named `b` in `S`, expected `a` instead",
626 );
627 check_error_message(
628 &Error::NoSuchStructField {
629 expected: &["a", "b+c", "d"],
630 found: String::from("e"),
631 outer: Some(String::from("S")),
632 },
633 "Unexpected field named `e` in `S`, \
634 expected one of `a`, `r#b+c`, or `d` instead",
635 );
636 check_error_message(
637 &Error::missing_field("a"),
638 "Unexpected missing field named `a`",
639 );
640 check_error_message(
641 &Error::MissingStructField {
642 field: "",
643 outer: Some(String::from("S+T")),
644 },
645 "Unexpected missing field named \"\"_[invalid identifier] in `r#S+T`",
646 );
647 check_error_message(
648 &Error::duplicate_field("a"),
649 "Unexpected duplicate field named `a`",
650 );
651 check_error_message(
652 &Error::DuplicateStructField {
653 field: "b+c",
654 outer: Some(String::from("S+T")),
655 },
656 "Unexpected duplicate field named `r#b+c` in `r#S+T`",
657 );
658 check_error_message(
659 &Error::InvalidIdentifier(String::from("why+🦀+not")),
660 "Invalid identifier \"why+🦀+not\"",
661 );
662 check_error_message(
663 &Error::SuggestRawIdentifier(String::from("raw+ident")),
664 "Found invalid std identifier \"raw+ident\", \
665 try the raw identifier `r#raw+ident` instead",
666 );
667 check_error_message(
668 &Error::ExpectedRawValue,
669 "Expected a `ron::value::RawValue`",
670 );
671 check_error_message(
672 &Error::ExceededRecursionLimit,
673 "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \
674 and using `serde_stacker` to protect against a stack overflow",
675 );
676 check_error_message(
677 &Error::ExpectedStructName(String::from("Struct")),
678 "Expected the explicit struct name `Struct`, but none was found",
679 );
680 }
681
682 fn check_error_message<T: std::fmt::Display>(err: &T, msg: &str) {
683 assert_eq!(format!("{}", err), msg);
684 }
685
686 #[test]
687 fn spanned_error_into_code() {
688 assert_eq!(
689 Error::from(SpannedError {
690 code: Error::Eof,
691 position: Position { line: 1, col: 1 }
692 }),
693 Error::Eof
694 );
695 assert_eq!(
696 Error::from(SpannedError {
697 code: Error::ExpectedRawValue,
698 position: Position { line: 1, col: 1 }
699 }),
700 Error::ExpectedRawValue
701 );
702 }
703}