deser_core/error.rs
1//! Error interface.
2use alloc::borrow::Cow;
3use alloc::boxed::Box;
4use alloc::format;
5use alloc::string::String;
6use alloc::vec::Vec;
7use core::any::{Any, TypeId};
8use core::fmt;
9
10use crate::{Position, State};
11
12/// Describes the kind of error.
13///
14/// The kind determines the [`ErrorCategory`] of an error (see
15/// [`Error::category`]): the formats fail with [`Syntax`](Self::Syntax),
16/// [`EndOfFile`](Self::EndOfFile) and [`LimitExceeded`](Self::LimitExceeded)
17/// if the input is not well-formed, the values with the kinds of the
18/// [`Data`](ErrorCategory::Data) category if it is well-formed but does
19/// not fit them.
20///
21/// More kinds may be added in the future.
22#[derive(Debug, Eq, PartialEq, Copy, Clone)]
23#[non_exhaustive]
24pub enum ErrorKind {
25 /// The input is not well-formed.
26 ///
27 /// This covers what the grammar of the format rejects (including data
28 /// after the end of the input and input that is not validly encoded)
29 /// and documents that are invalid in the format (like an unknown
30 /// alias in YAML or rows of different lengths in CSV).
31 Syntax,
32 /// The input ended before the value was complete or is empty.
33 EndOfFile,
34 /// A limit was exceeded (see [`Limits`](crate::de::Limits)), like the
35 /// depth of nesting or the length of the input.
36 LimitExceeded,
37 /// A value has a type that is not expected (like a string where a
38 /// number is expected).
39 InvalidType,
40 /// A value has the type that is expected but is invalid (like text
41 /// that is not a number where a number is expected, or a value that a
42 /// validator rejects).
43 InvalidValue,
44 /// A number is out of the range of the type it's converted to.
45 OutOfRange,
46 /// A sequence or bytes have a length that is not expected.
47 WrongLength,
48 /// A field (or the tag of an enum) is missing.
49 MissingField,
50 /// A field is not known (see `#[deser(deny_unknown_fields)]`).
51 UnknownField,
52 /// A variant of an enum is not known, or no variant of an untagged
53 /// enum matches.
54 UnknownVariant,
55 /// A key is given more than once (see
56 /// [`DuplicateKeys`](crate::de::DuplicateKeys)).
57 DuplicateKey,
58 /// A type or value cannot be represented: the format does not support
59 /// it, or the type cannot be deserialized from what the format
60 /// provides (like a `&str` from a string that is not borrowed).
61 UnsupportedType,
62 /// An API is used in a way that is not supported, for instance a
63 /// stream that failed is used again or a serializer receives events
64 /// that do not form a value.
65 InvalidState,
66 /// deser is set up wrongly, for instance the variants of an open enum
67 /// are not registered or two of them have the same name. These are
68 /// bugs in the program, not problems of the input.
69 Configuration,
70 /// Reading or writing failed (see `deser::io`). The IO error is
71 /// the [`source`](core::error::Error::source) of the error.
72 Io,
73 /// An error which has none of the other kinds.
74 ///
75 /// The category of these errors depends on where they come from (see
76 /// [`Error::category`]).
77 Custom,
78}
79
80impl ErrorKind {
81 /// Returns `true` if a value rejects what it's given.
82 ///
83 /// The fallbacks which try another representation of a value if it's
84 /// rejected (like the text of a number) check this. These are the
85 /// kinds of the errors of values, apart from numbers that are out of
86 /// range and missing fields.
87 #[inline]
88 pub(crate) fn is_rejection(self) -> bool {
89 matches!(
90 self,
91 ErrorKind::InvalidType
92 | ErrorKind::InvalidValue
93 | ErrorKind::UnknownField
94 | ErrorKind::UnknownVariant
95 | ErrorKind::DuplicateKey
96 | ErrorKind::Custom
97 )
98 }
99}
100
101/// Describes the category of an error, see [`Error::category`].
102///
103/// The categories tell apart whether the input was not well-formed or did
104/// not fit the values it was deserialized into. For instance an HTTP
105/// server would answer requests that fail with errors of the
106/// [`Syntax`](Self::Syntax) and [`Eof`](Self::Eof) categories with
107/// `400 Bad Request` and the ones of the [`Data`](Self::Data) category
108/// with `422 Unprocessable Entity`.
109///
110/// More categories may be added in the future.
111#[derive(Debug, Eq, PartialEq, Copy, Clone)]
112#[non_exhaustive]
113pub enum ErrorCategory {
114 /// The input is not well-formed ([`ErrorKind::Syntax`]).
115 Syntax,
116 /// The input ended early ([`ErrorKind::EndOfFile`]).
117 Eof,
118 /// The input is well-formed but does not fit the values, or a value
119 /// cannot be serialized.
120 Data,
121 /// A limit was exceeded ([`ErrorKind::LimitExceeded`]).
122 Limit,
123 /// A type or value cannot be represented
124 /// ([`ErrorKind::UnsupportedType`]).
125 Unsupported,
126 /// An API was used in a way that is not supported
127 /// ([`ErrorKind::InvalidState`]) or deser is set up wrongly
128 /// ([`ErrorKind::Configuration`]).
129 Usage,
130 /// Reading or writing failed ([`ErrorKind::Io`]).
131 Io,
132}
133
134/// Additional information attached to an [`Error`].
135///
136/// Besides the location in the input, which is built into errors, layers
137/// and other code can attach typed values to errors with
138/// [`Error::set_attachment`] and retrieve them with
139/// [`Error::attachment`]. An error holds at most one attachment per type.
140/// For instance the `deser-path` crate attaches the path of the value an
141/// error refers to.
142///
143/// Attachments can contribute to the [`Display`](fmt::Display) output of
144/// the error with [`fmt_context`](Self::fmt_context).
145///
146/// ```
147/// use std::fmt;
148/// use deser::{Error, ErrorAttachment, ErrorKind};
149///
150/// #[derive(Debug)]
151/// struct FileName(String);
152///
153/// impl ErrorAttachment for FileName {
154/// fn fmt_context(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155/// write!(f, " in {}", self.0)
156/// }
157/// }
158///
159/// let mut err = Error::with_position(ErrorKind::InvalidType, "unexpected string", 12, 2, 5);
160/// err.set_attachment(FileName("config.json".into()));
161/// assert_eq!(err.attachment::<FileName>().unwrap().0, "config.json");
162/// assert_eq!(
163/// err.to_string(),
164/// "InvalidType: unexpected string at line 2 column 5 in config.json"
165/// );
166/// ```
167pub trait ErrorAttachment: Any + fmt::Debug + Send + Sync {
168 /// Writes the attachment as part of the error message.
169 ///
170 /// The output is appended to the message and the location of the
171 /// error, so it typically starts with a space. By default attachments
172 /// are not shown.
173 fn fmt_context(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
174 let _ = f;
175 Ok(())
176 }
177}
178
179/// Adds context to errors, see [`State::add_error_context`](crate::State::add_error_context).
180///
181/// This is typically implemented by the extension type which holds the
182/// information that is attached to errors.
183pub trait ErrorContext: 'static {
184 /// Adds context to an error.
185 ///
186 /// This is invoked with the state as it was when the error happened.
187 /// Context that is already attached to the error should not be
188 /// replaced.
189 fn add_context(err: &mut Error, state: &State);
190}
191
192/// The message of the result that requests a raw value, identified by its
193/// address (see `Error::raw_request`).
194static RAW_REQUEST: &str = "raw value requested outside of a deserialization";
195
196/// An error for deser.
197///
198/// Besides a kind and a message an error can carry context: the location
199/// in the input it refers to (see [`offset`](Self::offset),
200/// [`line`](Self::line) and [`column`](Self::column)) and typed
201/// attachments (see [`ErrorAttachment`]). The context is part of the
202/// [`Display`](fmt::Display) output:
203///
204/// ```
205/// use deser::{Error, ErrorKind};
206///
207/// let err = Error::with_position(ErrorKind::InvalidType, "unexpected string", 12, 2, 5);
208/// assert_eq!(
209/// err.to_string(),
210/// "InvalidType: unexpected string at line 2 column 5"
211/// );
212/// ```
213///
214/// Errors raised while deserializing a value (for instance by a
215/// [`Sink`](crate::de::Sink)) get the context attached by the
216/// [`DeserializeDriver`](crate::de::DeserializeDriver): the start of the
217/// input range of the event (see [`State::input_range`](crate::State::input_range))
218/// and the context of the types registered with
219/// [`State::add_error_context`](crate::State::add_error_context). Formats
220/// resolve the offsets into lines and columns.
221///
222/// # Multiple Errors
223///
224/// An error can hold multiple errors, for instance if deserialization
225/// continued after an error to report all problems of the input at once
226/// (see [`State::set_collect_errors`](crate::State::set_collect_errors)).
227/// The accessors ([`kind`](Self::kind), [`message`](Self::message), the
228/// location and the attachments) refer to the first of them, all of them
229/// are iterated with [`errors`](Self::errors). The
230/// [`Display`](fmt::Display) output mentions how many more errors there
231/// are, with the alternate flag (`{:#}`) it lists all of them, one per
232/// line:
233///
234/// ```
235/// use deser::{Error, ErrorKind};
236///
237/// let mut err = Error::from_errors([
238/// Error::with_offset(ErrorKind::MissingField, "missing field `a`", 0),
239/// Error::with_offset(ErrorKind::InvalidType, "unexpected string", 9),
240/// ])
241/// .unwrap();
242/// err.resolve_position(b"{\n \"b\": \"x\"}");
243/// assert_eq!(err.errors().count(), 2);
244/// assert_eq!(err.kind(), ErrorKind::MissingField);
245/// assert_eq!(
246/// err.to_string(),
247/// "MissingField: missing field `a` at line 1 column 1 \
248/// (and 1 more error)"
249/// );
250/// assert_eq!(
251/// format!("{:#}", err),
252/// "MissingField: missing field `a` at line 1 column 1\n\
253/// InvalidType: unexpected string at line 2 column 8"
254/// );
255/// ```
256pub struct Error {
257 // boxed so that results stay small. Errors are rare but results are
258 // passed around for every single value.
259 inner: Box<ErrorInner>,
260}
261
262enum ErrorInner {
263 Single(ErrorData),
264 // at least two errors, all of them are single errors. The first one
265 // is the error the accessors refer to.
266 Multiple(Vec<Error>),
267}
268
269#[derive(Debug)]
270struct ErrorData {
271 kind: ErrorKind,
272 msg: Cow<'static, str>,
273 source: Option<Box<dyn core::error::Error + Send + Sync>>,
274 offset: Option<usize>,
275 // line and column (1-based)
276 line_column: Option<(usize, usize)>,
277 // in the order they were attached, at most one per type
278 attachments: Vec<Attachment>,
279 // `true` once the driver attached the context of the current event.
280 has_context: bool,
281 // `true` once the error was collected (see `CollectedErrors`)
282 collected: bool,
283}
284
285#[derive(Debug)]
286struct Attachment {
287 // Invariant: the type of the value
288 type_id: TypeId,
289 value: Box<dyn ErrorAttachment>,
290}
291
292impl Error {
293 /// Creates a new error.
294 #[cold]
295 pub fn new<M: Into<Cow<'static, str>>>(kind: ErrorKind, msg: M) -> Error {
296 Error {
297 inner: Box::new(ErrorInner::Single(ErrorData {
298 kind,
299 msg: msg.into(),
300 source: None,
301 offset: None,
302 line_column: None,
303 attachments: Vec::new(),
304 has_context: false,
305 collected: false,
306 })),
307 }
308 }
309
310 /// Creates a new error at a byte offset in the input (see
311 /// [`set_offset`](Self::set_offset)).
312 #[cold]
313 pub fn with_offset<M: Into<Cow<'static, str>>>(
314 kind: ErrorKind,
315 msg: M,
316 offset: usize,
317 ) -> Error {
318 let mut err = Error::new(kind, msg);
319 err.set_offset(offset);
320 err
321 }
322
323 /// Creates a new error at a byte offset with its line and column (see
324 /// [`set_position`](Self::set_position)).
325 #[cold]
326 pub fn with_position<M: Into<Cow<'static, str>>>(
327 kind: ErrorKind,
328 msg: M,
329 offset: usize,
330 line: usize,
331 column: usize,
332 ) -> Error {
333 let mut err = Error::new(kind, msg);
334 err.set_position(offset, line, column);
335 err
336 }
337
338 /// Combines errors into one.
339 ///
340 /// Errors that hold multiple errors are flattened: errors do not nest
341 /// (see [`errors`](Self::errors)). Returns `None` if there are no
342 /// errors.
343 pub fn from_errors<I: IntoIterator<Item = Error>>(errors: I) -> Option<Error> {
344 let mut errors = errors.into_iter();
345 let mut rv = errors.next()?;
346 for err in errors {
347 rv.push_error(err);
348 }
349 Some(rv)
350 }
351
352 /// Creates the error for a value that is serialized while another one
353 /// is only partially written.
354 ///
355 /// Stream serializers return this once they are
356 /// [in progress](crate::ser::StreamSerializer::in_progress) and are asked
357 /// to serialize another value.
358 #[cold]
359 pub fn in_progress() -> Error {
360 Error::new(
361 ErrorKind::InvalidState,
362 "a value was only partially written, the stream cannot continue",
363 )
364 }
365
366 /// Adds an error to this error.
367 ///
368 /// If the error that is added holds multiple errors, they are added
369 /// individually: errors do not nest (see [`errors`](Self::errors)).
370 pub(crate) fn push_error(&mut self, err: Error) {
371 let errors = self.make_multiple();
372 match *err.inner {
373 ErrorInner::Single(data) => errors.push(Error {
374 inner: Box::new(ErrorInner::Single(data)),
375 }),
376 ErrorInner::Multiple(others) => errors.extend(others),
377 }
378 }
379
380 /// Turns the error into one that holds multiple errors.
381 fn make_multiple(&mut self) -> &mut Vec<Error> {
382 if let ErrorInner::Single(_) = *self.inner {
383 let first = core::mem::replace(&mut *self.inner, ErrorInner::Multiple(Vec::new()));
384 if let ErrorInner::Multiple(ref mut errors) = *self.inner {
385 errors.push(Error {
386 inner: Box::new(first),
387 });
388 }
389 }
390 match *self.inner {
391 ErrorInner::Multiple(ref mut errors) => errors,
392 ErrorInner::Single(_) => unreachable!(),
393 }
394 }
395
396 /// Iterates over the errors this error holds.
397 ///
398 /// For an error that holds a single error, this is the error itself.
399 /// The errors that are returned hold a single error each.
400 pub fn errors(&self) -> impl Iterator<Item = &Error> {
401 match *self.inner {
402 ErrorInner::Single(_) => core::slice::from_ref(self).iter(),
403 ErrorInner::Multiple(ref errors) => errors.iter(),
404 }
405 }
406
407 /// Returns the data of the (first) error.
408 fn data(&self) -> &ErrorData {
409 match *self.inner {
410 ErrorInner::Single(ref data) => data,
411 ErrorInner::Multiple(ref errors) => errors[0].data(),
412 }
413 }
414
415 /// Returns the data of the (first) error mutably.
416 fn data_mut(&mut self) -> &mut ErrorData {
417 match *self.inner {
418 ErrorInner::Single(ref mut data) => data,
419 ErrorInner::Multiple(ref mut errors) => errors[0].data_mut(),
420 }
421 }
422
423 /// Applies a function to every error this error holds.
424 /// Changes every error (see [`errors`](Self::errors)).
425 pub(crate) fn for_each_mut(&mut self, mut f: impl FnMut(&mut Error)) {
426 if let ErrorInner::Multiple(ref mut errors) = *self.inner {
427 errors.iter_mut().for_each(f);
428 } else {
429 f(self)
430 }
431 }
432
433 pub(crate) fn map_each(mut self, mut f: impl FnMut(Error) -> Error) -> Error {
434 if let ErrorInner::Multiple(ref mut errors) = *self.inner {
435 for err in errors.iter_mut() {
436 let taken = core::mem::replace(err, Error::new(ErrorKind::Custom, ""));
437 *err = f(taken);
438 }
439 self
440 } else {
441 f(self)
442 }
443 }
444
445 /// Returns the number of errors this error holds that were not
446 /// collected yet.
447 pub(crate) fn uncollected_count(&self) -> usize {
448 self.errors().filter(|err| !err.data().collected).count()
449 }
450
451 /// Marks all errors this error holds as collected.
452 pub(crate) fn mark_collected(mut self) -> Error {
453 self = self.map_each(|mut err| {
454 err.data_mut().collected = true;
455 err
456 });
457 self
458 }
459
460 /// Attaches another error as source to this error.
461 pub fn set_source<E: core::error::Error + Send + Sync + 'static>(&mut self, source: E) {
462 self.data_mut().source = Some(Box::new(source));
463 }
464
465 /// Creates the result of an event that requests the next value as raw
466 /// value (see [`is_raw_request`](Self::is_raw_request)).
467 #[cold]
468 pub(crate) fn raw_request() -> Error {
469 Error::new(ErrorKind::InvalidState, RAW_REQUEST)
470 }
471
472 /// Returns `true` if this requests the next value as raw value.
473 ///
474 /// This is not an error: sinks return it from the event before a value
475 /// that deserializes into a [`Raw`](crate::ext::Raw) value of the format
476 /// that is parsed (see [`State::declare_raw_format`](crate::State::declare_raw_format)).
477 /// Deserializers of formats with raw values check the errors of events
478 /// with this. If it's `true`, the event was accepted and the format
479 /// passes on the input of the next value as
480 /// [`RawInput`](crate::ext::RawInput) rather than its events. Other
481 /// formats never see it.
482 pub fn is_raw_request(&self) -> bool {
483 match *self.inner {
484 ErrorInner::Single(ErrorData {
485 msg: Cow::Borrowed(msg),
486 ..
487 }) => core::ptr::eq(msg, RAW_REQUEST),
488 _ => false,
489 }
490 }
491
492 /// Returns the kind of the error.
493 pub fn kind(&self) -> ErrorKind {
494 self.data().kind
495 }
496
497 /// Returns the category of the error.
498 ///
499 /// The category follows from the [`kind`](Self::kind). The exception
500 /// are errors of the kind [`Custom`](ErrorKind::Custom): they are in
501 /// the [`Data`](ErrorCategory::Data) category if a value failed with them
502 /// while it was deserialized or serialized (the driver attached the
503 /// context of the event to them, see [`Error`]), and in the
504 /// [`Syntax`](ErrorCategory::Syntax) category otherwise (the format
505 /// failed with them).
506 ///
507 /// For an error that holds multiple errors this is the category of
508 /// the first one.
509 ///
510 /// ```
511 /// use deser::{Error, ErrorCategory, ErrorKind};
512 ///
513 /// let err = Error::new(ErrorKind::Syntax, "expected a comma");
514 /// assert_eq!(err.category(), ErrorCategory::Syntax);
515 /// let err = Error::new(ErrorKind::InvalidType, "unexpected string");
516 /// assert_eq!(err.category(), ErrorCategory::Data);
517 /// ```
518 pub fn category(&self) -> ErrorCategory {
519 let data = self.data();
520 match data.kind {
521 ErrorKind::Syntax => ErrorCategory::Syntax,
522 ErrorKind::EndOfFile => ErrorCategory::Eof,
523 ErrorKind::LimitExceeded => ErrorCategory::Limit,
524 ErrorKind::InvalidType
525 | ErrorKind::InvalidValue
526 | ErrorKind::OutOfRange
527 | ErrorKind::WrongLength
528 | ErrorKind::MissingField
529 | ErrorKind::UnknownField
530 | ErrorKind::UnknownVariant
531 | ErrorKind::DuplicateKey => ErrorCategory::Data,
532 ErrorKind::UnsupportedType => ErrorCategory::Unsupported,
533 ErrorKind::InvalidState | ErrorKind::Configuration => ErrorCategory::Usage,
534 ErrorKind::Io => ErrorCategory::Io,
535 ErrorKind::Custom => {
536 if data.has_context {
537 ErrorCategory::Data
538 } else {
539 ErrorCategory::Syntax
540 }
541 }
542 }
543 }
544
545 /// Returns the message of the error (without context).
546 pub fn message(&self) -> &str {
547 &self.data().msg
548 }
549
550 /// Sets the byte offset in the input the error refers to.
551 ///
552 /// A previously set line and column are discarded.
553 pub fn set_offset(&mut self, offset: usize) {
554 let data = self.data_mut();
555 data.offset = Some(offset);
556 data.line_column = None;
557 }
558
559 /// Sets the byte offset together with its line and column (1-based).
560 pub fn set_position(&mut self, offset: usize, line: usize, column: usize) {
561 let data = self.data_mut();
562 data.offset = Some(offset);
563 data.line_column = Some((line, column));
564 }
565
566 /// Resolves the offset into line and column.
567 ///
568 /// The source is the input the offset refers to. Columns are counted
569 /// in characters (bytes that are not UTF-8 continuation bytes). If the
570 /// error has no offset or already has a line and column, it's returned
571 /// unchanged. Text formats call this for the errors they return.
572 ///
573 /// ```
574 /// use deser::{Error, ErrorKind};
575 ///
576 /// let mut err = Error::with_offset(ErrorKind::InvalidValue, "bad value", 7);
577 /// err.resolve_position(b"[1,\n x]");
578 /// assert_eq!((err.line(), err.column()), (Some(2), Some(4)));
579 /// ```
580 ///
581 /// The positions of further errors (see [`errors`](Self::errors)) are
582 /// resolved as well.
583 pub fn resolve_position(&mut self, source: &[u8]) {
584 self.for_each_mut(|err| {
585 let data = err.data_mut();
586 if let (Some(offset), None) = (data.offset, data.line_column) {
587 let pos = Position::of(source, offset);
588 data.line_column = Some((pos.line, pos.column));
589 }
590 });
591 }
592
593 /// Moves the position of the error by the position of the input it
594 /// refers to.
595 ///
596 /// This is used for errors of inputs which are part of a larger input,
597 /// the base is the position of the start of the part.
598 pub(crate) fn shift_position(self, base: Position) -> Self {
599 self.map_each(|mut err| {
600 let data = err.data_mut();
601 if let Some(ref mut error_offset) = data.offset {
602 *error_offset += base.offset;
603 }
604 if let Some((ref mut error_line, ref mut error_column)) = data.line_column {
605 if *error_line == 1 {
606 *error_column += base.column - 1;
607 }
608 *error_line += base.line - 1;
609 }
610 err
611 })
612 }
613
614 /// Returns the byte offset in the input the error refers to.
615 pub fn offset(&self) -> Option<usize> {
616 self.data().offset
617 }
618
619 /// Returns the line (1-based) the error refers to.
620 pub fn line(&self) -> Option<usize> {
621 self.data().line_column.map(|x| x.0)
622 }
623
624 /// Returns the column (1-based, in characters) the error refers to.
625 pub fn column(&self) -> Option<usize> {
626 self.data().line_column.map(|x| x.1)
627 }
628
629 /// Attaches a value to the error.
630 ///
631 /// An attachment of the same type is replaced but keeps its position
632 /// in the [`Display`](fmt::Display) output. See [`ErrorAttachment`].
633 pub fn set_attachment<T: ErrorAttachment>(&mut self, value: T) {
634 let type_id = TypeId::of::<T>();
635 let value = Box::new(value);
636 let attachments = &mut self.data_mut().attachments;
637 match attachments.iter_mut().find(|x| x.type_id == type_id) {
638 Some(attachment) => attachment.value = value,
639 None => attachments.push(Attachment { type_id, value }),
640 }
641 }
642
643 /// Returns the attachment of the given type.
644 pub fn attachment<T: ErrorAttachment>(&self) -> Option<&T> {
645 let type_id = TypeId::of::<T>();
646 let attachment = self
647 .data()
648 .attachments
649 .iter()
650 .find(|x| x.type_id == type_id)?;
651 (&*attachment.value as &dyn Any).downcast_ref()
652 }
653
654 /// Returns the attachment of the given type mutably.
655 pub fn attachment_mut<T: ErrorAttachment>(&mut self) -> Option<&mut T> {
656 let type_id = TypeId::of::<T>();
657 let attachment = self
658 .data_mut()
659 .attachments
660 .iter_mut()
661 .find(|x| x.type_id == type_id)?;
662 (&mut *attachment.value as &mut dyn Any).downcast_mut()
663 }
664
665 /// Iterates over the attachments in the order they were attached.
666 pub fn attachments(&self) -> impl Iterator<Item = &dyn ErrorAttachment> {
667 self.data().attachments.iter().map(|x| &*x.value)
668 }
669
670 /// Returns `true` if the context of an event was attached.
671 pub(crate) fn has_context(&self) -> bool {
672 self.data().has_context
673 }
674
675 /// Marks the context of an event as attached.
676 pub(crate) fn set_has_context(&mut self) {
677 self.data_mut().has_context = true;
678 }
679}
680
681impl fmt::Debug for Error {
682 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
683 let data = match *self.inner {
684 ErrorInner::Single(ref data) => data,
685 ErrorInner::Multiple(ref errors) => {
686 return f.debug_tuple("Errors").field(errors).finish();
687 }
688 };
689 let mut s = f.debug_struct("Error");
690 s.field("kind", &data.kind).field("msg", &data.msg);
691 if let Some(offset) = data.offset {
692 s.field("offset", &offset);
693 }
694 if let Some((line, column)) = data.line_column {
695 s.field("line", &line).field("column", &column);
696 }
697 if !data.attachments.is_empty() {
698 s.field("attachments", &DebugAttachments(&data.attachments));
699 }
700 s.field("source", &data.source).finish()
701 }
702}
703
704impl ErrorData {
705 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
706 write!(f, "{:?}: {}", self.kind, self.msg)?;
707 match (self.line_column, self.offset) {
708 (Some((line, column)), _) => write!(f, " at line {} column {}", line, column)?,
709 (None, Some(offset)) => write!(f, " at offset {}", offset)?,
710 (None, None) => {}
711 }
712 for attachment in self.attachments.iter() {
713 attachment.value.fmt_context(f)?;
714 }
715 Ok(())
716 }
717}
718
719impl fmt::Display for Error {
720 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
721 let errors = match *self.inner {
722 ErrorInner::Single(ref data) => return data.fmt(f),
723 ErrorInner::Multiple(ref errors) => errors,
724 };
725 errors[0].data().fmt(f)?;
726 if f.alternate() {
727 for err in &errors[1..] {
728 writeln!(f)?;
729 err.data().fmt(f)?;
730 }
731 } else if errors.len() == 2 {
732 write!(f, " (and 1 more error)")?;
733 } else {
734 write!(f, " (and {} more errors)", errors.len() - 1)?;
735 }
736 Ok(())
737 }
738}
739
740struct DebugAttachments<'a>(&'a [Attachment]);
741
742impl fmt::Debug for DebugAttachments<'_> {
743 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
744 f.debug_list()
745 .entries(self.0.iter().map(|x| &x.value))
746 .finish()
747 }
748}
749
750#[cfg(feature = "std")]
751impl From<std::io::Error> for Error {
752 fn from(err: std::io::Error) -> Error {
753 let mut rv = Error::new(ErrorKind::Io, err.to_string());
754 rv.set_source(err);
755 rv
756 }
757}
758
759impl core::error::Error for Error {
760 fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
761 self.data().source.as_ref().map(|err| err.as_ref() as _)
762 }
763}
764
765/// Creates an error that is thrown away.
766///
767/// While errors are discarded (see `State::discard_errors`) the common
768/// errors are created with this instead of building a message nobody reads.
769#[cold]
770#[inline(never)]
771pub(crate) fn discarded_error(kind: ErrorKind) -> Error {
772 Error::new(kind, "discarded error")
773}
774
775/// Creates the error for a value that failed to convert or validate.
776#[cold]
777pub(crate) fn conversion_error<E: fmt::Display>(err: E) -> Error {
778 Error::new(ErrorKind::InvalidValue, format!("invalid value: {}", err))
779}
780
781/// Creates the error for an unknown variant.
782///
783/// `tag` is the name that was given (if it can be a name), `type_name` the
784/// name of the enum and `names` are the names of the variants.
785#[cold]
786pub fn unknown_variant(tag: Option<&str>, type_name: &str, names: &[&str]) -> Error {
787 let mut msg = String::from("unknown variant");
788 if let Some(tag) = tag {
789 msg.push_str(" `");
790 msg.push_str(tag);
791 msg.push('`');
792 }
793 msg.push_str(" of ");
794 msg.push_str(type_name);
795 push_expected(&mut msg, names, "variants");
796 Error::new(ErrorKind::UnknownVariant, msg)
797}
798
799/// Appends the expected names to an error message.
800///
801/// `what` is what the names are, for the message if there are none.
802pub(crate) fn push_expected(msg: &mut String, names: &[&str], what: &str) {
803 match names {
804 [] => {
805 msg.push_str(", there are no ");
806 msg.push_str(what);
807 }
808 [name] => {
809 msg.push_str(", expected `");
810 msg.push_str(name);
811 msg.push('`');
812 }
813 [first, second] => {
814 msg.push_str(", expected `");
815 msg.push_str(first);
816 msg.push_str("` or `");
817 msg.push_str(second);
818 msg.push('`');
819 }
820 names => {
821 msg.push_str(", expected one of ");
822 for (idx, name) in names.iter().enumerate() {
823 if idx > 0 {
824 msg.push_str(", ");
825 }
826 msg.push('`');
827 msg.push_str(name);
828 msg.push('`');
829 }
830 }
831 }
832}