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;
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}