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}