Skip to main content

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