1use alloc::string::{String, ToString};
2use core::{
3 fmt,
4 str::{self, Utf8Error},
5};
6
7use serde::{
8 de,
9 ser::{self, StdError},
10};
11use unicode_ident::is_xid_continue;
12
13use crate::parse::{is_ident_first_char, is_ident_raw_char};
14
15#[cfg(feature = "std")]
16use std::io;
17
18#[allow(clippy::module_name_repetitions)]
21#[derive(Clone, Debug, PartialEq, Eq)]
22pub struct SpannedError {
23 pub code: Error,
24 pub span: Span,
25}
26
27pub type Result<T, E = Error> = core::result::Result<T, E>;
28pub type SpannedResult<T> = core::result::Result<T, SpannedError>;
29
30#[derive(Clone, Debug, PartialEq, Eq)]
31#[non_exhaustive]
32pub enum Error {
33 Fmt,
34 Io(String),
35 Message(String),
36 Eof,
37 ExpectedArray,
38 ExpectedArrayEnd,
39 ExpectedAttribute,
40 ExpectedAttributeEnd,
41 ExpectedBoolean,
42 ExpectedComma,
43 ExpectedChar,
44 ExpectedByteLiteral,
45 ExpectedFloat,
46 FloatUnderscore,
47 ExpectedInteger,
48 ExpectedOption,
49 ExpectedOptionEnd,
50 ExpectedMap,
51 ExpectedMapColon,
52 ExpectedMapEnd,
53 ExpectedDifferentStructName {
54 expected: &'static str,
55 found: String,
56 },
57 ExpectedStructLike,
58 ExpectedNamedStructLike(&'static str),
59 ExpectedStructLikeEnd,
60 ExpectedUnit,
61 ExpectedString,
62 ExpectedByteString,
63 ExpectedStringEnd,
64 ExpectedIdentifier,
65
66 InvalidEscape(&'static str),
67
68 IntegerOutOfBounds,
69 InvalidIntegerDigit {
70 digit: char,
71 base: u8,
72 },
73
74 NoSuchExtension(String),
75
76 UnclosedBlockComment,
77 UnclosedLineComment,
78 UnderscoreAtBeginning,
79 UnexpectedChar(char),
80
81 Utf8Error(Utf8Error),
82 TrailingCharacters,
83
84 InvalidValueForType {
85 expected: String,
86 found: String,
87 },
88 ExpectedDifferentLength {
89 expected: String,
90 found: usize,
91 },
92 NoSuchEnumVariant {
93 expected: &'static [&'static str],
94 found: String,
95 outer: Option<String>,
96 },
97 NoSuchStructField {
98 expected: &'static [&'static str],
99 found: String,
100 outer: Option<String>,
101 },
102 MissingStructField {
103 field: &'static str,
104 outer: Option<String>,
105 },
106 DuplicateStructField {
107 field: &'static str,
108 outer: Option<String>,
109 },
110 InvalidIdentifier(String),
111 SuggestRawIdentifier(String),
112 ExpectedRawValue,
113 ExceededRecursionLimit,
114 ExpectedStructName(String),
115 ExpectedRangeSyntax,
116}
117
118impl fmt::Display for SpannedError {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
120 write!(f, "{}: {}", self.span, self.code)
121 }
122}
123
124impl fmt::Display for Error {
125 #[allow(clippy::too_many_lines)]
126 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
127 match *self {
128 Error::Fmt => f.write_str("Formatting RON failed"),
129 Error::Io(ref s) | Error::Message(ref s) => f.write_str(s),
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 Error::ExpectedRangeSyntax => f.write_str("Expected `..` or `..=` for range syntax"),
291 }
292 }
293}
294
295#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
296pub struct Position {
297 pub line: usize,
298 pub col: usize,
299}
300
301impl Position {
302 pub(crate) fn from_src_end(src: &str) -> Position {
303 let line = 1 + src.chars().filter(|&c| c == '\n').count();
304 let col = 1 + src.chars().rev().take_while(|&c| c != '\n').count();
305
306 Self { line, col }
307 }
308}
309
310impl fmt::Display for Position {
311 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
312 write!(f, "{}:{}", self.line, self.col)
313 }
314}
315
316#[derive(Clone, Debug, PartialEq, Eq)]
317pub struct Span {
321 pub start: Position,
322 pub end: Position,
323}
324
325impl fmt::Display for Span {
326 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
327 if self.start == self.end {
328 write!(f, "{}", self.start)
329 } else {
330 write!(f, "{}-{}", self.start, self.end)
331 }
332 }
333}
334
335impl ser::Error for Error {
336 #[cold]
337 fn custom<T: fmt::Display>(msg: T) -> Self {
338 Error::Message(msg.to_string())
339 }
340}
341
342impl de::Error for Error {
343 #[cold]
344 fn custom<T: fmt::Display>(msg: T) -> Self {
345 Error::Message(msg.to_string())
346 }
347
348 #[cold]
349 fn invalid_type(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
350 Self::invalid_value(unexp, exp)
352 }
353
354 #[cold]
355 fn invalid_value(unexp: de::Unexpected, exp: &dyn de::Expected) -> Self {
356 struct UnexpectedSerdeTypeValue<'a>(de::Unexpected<'a>);
357
358 impl<'a> fmt::Display for UnexpectedSerdeTypeValue<'a> {
359 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
360 match self.0 {
361 de::Unexpected::Bool(b) => write!(f, "the boolean `{}`", b),
362 de::Unexpected::Unsigned(i) => write!(f, "the unsigned integer `{}`", i),
363 de::Unexpected::Signed(i) => write!(f, "the signed integer `{}`", i),
364 de::Unexpected::Float(n) => write!(f, "the floating point number `{}`", n),
365 de::Unexpected::Char(c) => write!(f, "the UTF-8 character `{}`", c),
366 de::Unexpected::Str(s) => write!(f, "the string {:?}", s),
367 de::Unexpected::Bytes(b) => write!(f, "the byte string b\"{}\"", {
368 b.iter()
369 .flat_map(|c| core::ascii::escape_default(*c))
370 .map(char::from)
371 .collect::<String>()
372 }),
373 de::Unexpected::Unit => write!(f, "a unit value"),
374 de::Unexpected::Option => write!(f, "an optional value"),
375 de::Unexpected::NewtypeStruct => write!(f, "a newtype struct"),
376 de::Unexpected::Seq => write!(f, "a sequence"),
377 de::Unexpected::Map => write!(f, "a map"),
378 de::Unexpected::Enum => write!(f, "an enum"),
379 de::Unexpected::UnitVariant => write!(f, "a unit variant"),
380 de::Unexpected::NewtypeVariant => write!(f, "a newtype variant"),
381 de::Unexpected::TupleVariant => write!(f, "a tuple variant"),
382 de::Unexpected::StructVariant => write!(f, "a struct variant"),
383 de::Unexpected::Other(other) => f.write_str(other),
384 }
385 }
386 }
387
388 Error::InvalidValueForType {
389 expected: exp.to_string(),
390 found: UnexpectedSerdeTypeValue(unexp).to_string(),
391 }
392 }
393
394 #[cold]
395 fn invalid_length(len: usize, exp: &dyn de::Expected) -> Self {
396 Error::ExpectedDifferentLength {
397 expected: exp.to_string(),
398 found: len,
399 }
400 }
401
402 #[cold]
403 fn unknown_variant(variant: &str, expected: &'static [&'static str]) -> Self {
404 Error::NoSuchEnumVariant {
405 expected,
406 found: variant.to_string(),
407 outer: None,
408 }
409 }
410
411 #[cold]
412 fn unknown_field(field: &str, expected: &'static [&'static str]) -> Self {
413 Error::NoSuchStructField {
414 expected,
415 found: field.to_string(),
416 outer: None,
417 }
418 }
419
420 #[cold]
421 fn missing_field(field: &'static str) -> Self {
422 Error::MissingStructField { field, outer: None }
423 }
424
425 #[cold]
426 fn duplicate_field(field: &'static str) -> Self {
427 Error::DuplicateStructField { field, outer: None }
428 }
429}
430
431impl StdError for SpannedError {}
432
433impl StdError for Error {}
434
435impl From<Utf8Error> for Error {
436 fn from(e: Utf8Error) -> Self {
437 Error::Utf8Error(e)
438 }
439}
440
441impl From<fmt::Error> for Error {
442 fn from(_: fmt::Error) -> Self {
443 Error::Fmt
444 }
445}
446
447#[cfg(feature = "std")]
448impl From<io::Error> for Error {
449 fn from(e: io::Error) -> Self {
450 Error::Io(e.to_string())
451 }
452}
453
454impl From<SpannedError> for Error {
455 fn from(e: SpannedError) -> Self {
456 e.code
457 }
458}
459
460struct OneOf {
461 alts: &'static [&'static str],
462 none: &'static str,
463}
464
465impl fmt::Display for OneOf {
466 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467 match self.alts {
468 [] => write!(f, "there are no {}", self.none),
469 [a1] => write!(f, "expected {} instead", Identifier(a1)),
470 [a1, a2] => write!(
471 f,
472 "expected either {} or {} instead",
473 Identifier(a1),
474 Identifier(a2)
475 ),
476 [a1, ref alts @ .., an] => {
477 write!(f, "expected one of {}", Identifier(a1))?;
478
479 for alt in alts {
480 write!(f, ", {}", Identifier(alt))?;
481 }
482
483 write!(f, ", or {} instead", Identifier(an))
484 }
485 }
486 }
487}
488
489struct Identifier<'a>(&'a str);
490
491impl<'a> fmt::Display for Identifier<'a> {
492 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493 if self.0.is_empty() || !self.0.chars().all(is_ident_raw_char) {
494 return write!(f, "{:?}_[invalid identifier]", self.0);
495 }
496
497 let mut chars = self.0.chars();
498
499 if !chars.next().map_or(false, is_ident_first_char) || !chars.all(is_xid_continue) {
500 write!(f, "`r#{}`", self.0)
501 } else {
502 write!(f, "`{}`", self.0)
503 }
504 }
505}
506
507#[cfg(test)]
508mod tests {
509 use alloc::{format, string::String};
510
511 use serde::{de::Error as DeError, de::Unexpected, ser::Error as SerError};
512
513 use super::{Error, Position, Span, SpannedError};
514
515 #[test]
516 fn error_messages() {
517 check_error_message(&Error::from(core::fmt::Error), "Formatting RON failed");
518 #[cfg(feature = "std")]
519 check_error_message(
520 &Error::from(std::io::Error::new(
521 std::io::ErrorKind::InvalidData,
522 "my-error",
523 )),
524 "my-error",
525 );
526 check_error_message(&<Error as SerError>::custom("my-ser-error"), "my-ser-error");
527 check_error_message(&<Error as DeError>::custom("my-de-error"), "my-de-error");
528 check_error_message(&Error::Eof, "Unexpected end of RON");
529 check_error_message(&Error::ExpectedArray, "Expected opening `[`");
530 check_error_message(&Error::ExpectedArrayEnd, "Expected closing `]`");
531 check_error_message(
532 &Error::ExpectedAttribute,
533 "Expected an `#![enable(...)]` attribute",
534 );
535 check_error_message(
536 &Error::ExpectedAttributeEnd,
537 "Expected closing `)]` after the enable attribute",
538 );
539 check_error_message(&Error::ExpectedBoolean, "Expected boolean");
540 check_error_message(&Error::ExpectedComma, "Expected comma");
541 check_error_message(&Error::ExpectedChar, "Expected char");
542 check_error_message(&Error::ExpectedByteLiteral, "Expected byte literal");
543 check_error_message(&Error::ExpectedFloat, "Expected float");
544 check_error_message(&Error::FloatUnderscore, "Unexpected underscore in float");
545 check_error_message(&Error::ExpectedInteger, "Expected integer");
546 check_error_message(&Error::ExpectedOption, "Expected option");
547 check_error_message(&Error::ExpectedOptionEnd, "Expected closing `)`");
548 check_error_message(&Error::ExpectedStructLikeEnd, "Expected closing `)`");
549 check_error_message(&Error::ExpectedMap, "Expected opening `{`");
550 check_error_message(&Error::ExpectedMapColon, "Expected colon");
551 check_error_message(&Error::ExpectedMapEnd, "Expected closing `}`");
552 check_error_message(
553 &Error::ExpectedDifferentStructName {
554 expected: "raw+identifier",
555 found: String::from("identifier"),
556 },
557 "Expected struct `r#raw+identifier` but found `identifier`",
558 );
559 check_error_message(&Error::ExpectedStructLike, "Expected opening `(`");
560 check_error_message(
561 &Error::ExpectedNamedStructLike(""),
562 "Expected only opening `(`, no name, for un-nameable struct",
563 );
564 check_error_message(
565 &Error::ExpectedNamedStructLike("_ident"),
566 "Expected opening `(` for struct `_ident`",
567 );
568 check_error_message(&Error::ExpectedUnit, "Expected unit");
569 check_error_message(&Error::ExpectedString, "Expected string");
570 check_error_message(&Error::ExpectedByteString, "Expected byte string");
571 check_error_message(&Error::ExpectedStringEnd, "Expected end of string");
572 check_error_message(&Error::ExpectedIdentifier, "Expected identifier");
573 check_error_message(&Error::InvalidEscape("Invalid escape"), "Invalid escape");
574 check_error_message(&Error::IntegerOutOfBounds, "Integer is out of bounds");
575 check_error_message(
576 &Error::InvalidIntegerDigit {
577 digit: 'q',
578 base: 16,
579 },
580 "Invalid digit 'q' for base 16 integers",
581 );
582 check_error_message(
583 &Error::NoSuchExtension(String::from("unknown")),
584 "No RON extension named `unknown`",
585 );
586 check_error_message(&Error::UnclosedBlockComment, "Unclosed block comment");
587 check_error_message(
588 &Error::UnclosedLineComment,
589 "`ron::value::RawValue` cannot end in unclosed line comment, \
590 try using a block comment or adding a newline",
591 );
592 check_error_message(
593 &Error::UnderscoreAtBeginning,
594 "Unexpected leading underscore in a number",
595 );
596 check_error_message(&Error::UnexpectedChar('🦀'), "Unexpected char \'🦀\'");
597 #[allow(invalid_from_utf8)]
598 check_error_message(
599 &Error::Utf8Error(core::str::from_utf8(b"error: \xff\xff\xff\xff").unwrap_err()),
600 "invalid utf-8 sequence of 1 bytes from index 7",
601 );
602 check_error_message(
603 &Error::TrailingCharacters,
604 "Non-whitespace trailing characters",
605 );
606 check_error_message(
607 &Error::invalid_value(Unexpected::Enum, &"struct `Hi`"),
608 "Expected struct `Hi` but found an enum instead",
609 );
610 check_error_message(
611 &Error::invalid_length(0, &"two bees"),
612 "Expected two bees but found zero elements instead",
613 );
614 check_error_message(
615 &Error::invalid_length(1, &"two bees"),
616 "Expected two bees but found one element instead",
617 );
618 check_error_message(
619 &Error::invalid_length(3, &"two bees"),
620 "Expected two bees but found 3 elements instead",
621 );
622 check_error_message(
623 &Error::unknown_variant("unknown", &[]),
624 "Unexpected enum variant named `unknown`, there are no variants",
625 );
626 check_error_message(
627 &Error::NoSuchEnumVariant {
628 expected: &["A", "B+C"],
629 found: String::from("D"),
630 outer: Some(String::from("E")),
631 },
632 "Unexpected variant named `D` in enum `E`, \
633 expected either `A` or `r#B+C` instead",
634 );
635 check_error_message(
636 &Error::unknown_field("unknown", &[]),
637 "Unexpected field named `unknown`, there are no fields",
638 );
639 check_error_message(
640 &Error::NoSuchStructField {
641 expected: &["a"],
642 found: String::from("b"),
643 outer: Some(String::from("S")),
644 },
645 "Unexpected field named `b` in `S`, expected `a` instead",
646 );
647 check_error_message(
648 &Error::NoSuchStructField {
649 expected: &["a", "b+c", "d"],
650 found: String::from("e"),
651 outer: Some(String::from("S")),
652 },
653 "Unexpected field named `e` in `S`, \
654 expected one of `a`, `r#b+c`, or `d` instead",
655 );
656 check_error_message(
657 &Error::missing_field("a"),
658 "Unexpected missing field named `a`",
659 );
660 check_error_message(
661 &Error::MissingStructField {
662 field: "",
663 outer: Some(String::from("S+T")),
664 },
665 "Unexpected missing field named \"\"_[invalid identifier] in `r#S+T`",
666 );
667 check_error_message(
668 &Error::duplicate_field("a"),
669 "Unexpected duplicate field named `a`",
670 );
671 check_error_message(
672 &Error::DuplicateStructField {
673 field: "b+c",
674 outer: Some(String::from("S+T")),
675 },
676 "Unexpected duplicate field named `r#b+c` in `r#S+T`",
677 );
678 check_error_message(
679 &Error::InvalidIdentifier(String::from("why+🦀+not")),
680 "Invalid identifier \"why+🦀+not\"",
681 );
682 check_error_message(
683 &Error::SuggestRawIdentifier(String::from("raw+ident")),
684 "Found invalid std identifier \"raw+ident\", \
685 try the raw identifier `r#raw+ident` instead",
686 );
687 check_error_message(
688 &Error::ExpectedRawValue,
689 "Expected a `ron::value::RawValue`",
690 );
691 check_error_message(
692 &Error::ExceededRecursionLimit,
693 "Exceeded recursion limit, try increasing `ron::Options::recursion_limit` \
694 and using `serde_stacker` to protect against a stack overflow",
695 );
696 check_error_message(
697 &Error::ExpectedStructName(String::from("Struct")),
698 "Expected the explicit struct name `Struct`, but none was found",
699 );
700 }
701
702 fn check_error_message<T: core::fmt::Display>(err: &T, msg: &str) {
703 assert_eq!(format!("{}", err), msg);
704 }
705
706 #[test]
707 fn spanned_error_into_code() {
708 assert_eq!(
709 Error::from(SpannedError {
710 code: Error::Eof,
711 span: Span {
712 start: Position { line: 1, col: 1 },
713 end: Position { line: 1, col: 5 },
714 }
715 }),
716 Error::Eof
717 );
718 assert_eq!(
719 Error::from(SpannedError {
720 code: Error::ExpectedRawValue,
721 span: Span {
722 start: Position { line: 1, col: 1 },
723 end: Position { line: 1, col: 5 },
724 }
725 }),
726 Error::ExpectedRawValue
727 );
728 }
729}