dangerous/error/
traits.rs

1use crate::fmt;
2use crate::input::{Input, MaybeString, Span};
3
4use super::{
5    Backtrace, Context, ExpectedLength, ExpectedValid, ExpectedValue, RetryRequirement,
6    ToRetryRequirement, Value,
7};
8
9/// Auto-trait for [`WithContext`], [`ToRetryRequirement`] and
10/// `From<Expected(Value/Length/Valid)>`.
11pub trait Error<'i>:
12    WithContext<'i>
13    + ToRetryRequirement
14    + From<ExpectedValue<'i>>
15    + From<ExpectedLength<'i>>
16    + From<ExpectedValid<'i>>
17{
18}
19
20impl<'i, T> Error<'i> for T where
21    T: WithContext<'i>
22        + ToRetryRequirement
23        + From<ExpectedValue<'i>>
24        + From<ExpectedLength<'i>>
25        + From<ExpectedValid<'i>>
26{
27}
28
29/// Implemented for errors that collect [`Context`]s.
30pub trait WithContext<'i>: Sized {
31    /// If `true` indicates the error does not care about any provided contexts.
32    ///
33    /// Defaults to `false`.
34    ///
35    /// This can be used for selecting a verbose error at compile time on an
36    /// external parser if it is known this error will actually use the
37    /// collected backtrace.
38    const PASSTHROUGH: bool = false;
39
40    /// Returns `Self` with a parent [`Input`].
41    fn with_input(self, input: impl Input<'i>) -> Self;
42
43    /// Return `Self` with a context.
44    ///
45    /// This method is used for adding contexts to errors bubbling up.
46    fn with_context(self, context: impl Context) -> Self;
47}
48
49/// Required details around an error to produce a verbose report on what went
50/// wrong when processing input.
51///
52/// If you're not interested in errors of this nature and only wish to know
53/// whether or not the input was correctly processed, you'll wish to use the
54/// concrete type [`Invalid`] and all of the computations around verbose
55/// erroring will be removed in compilation.
56///
57/// [`Invalid`]: crate::Invalid
58pub trait Details<'i> {
59    /// The input in its entirety that was being processed when an error
60    /// occurred.
61    ///
62    /// The error itself will have the details and the specific section of input
63    /// that caused the error. This value simply allows us to see the bigger
64    /// picture given granular errors in a large amount of input.
65    fn input(&self) -> MaybeString<'i>;
66
67    /// The expected value, if applicable.
68    fn expected(&self) -> Option<Value<'_>>;
69
70    /// The description of what went wrong while processing the input.
71    ///
72    /// Descriptions should be simple and written in lowercase.
73    ///
74    /// # Errors
75    ///
76    /// Returns a [`fmt::Error`] if failed to write to the formatter.
77    fn description(&self, w: &mut dyn fmt::Write) -> fmt::Result;
78
79    /// The walkable [`Backtrace`] to the original context around the error
80    /// that occurred.
81    fn backtrace(&self) -> &dyn Backtrace;
82}
83
84/// Implemented for errors that aren't a first-class citizen to `dangerous` but
85/// wish to add additional information.
86///
87/// External errors are consumed with [`Input::into_external()`] or
88/// [`Reader::try_expect_external()`].
89///
90/// [`Input::into_external()`]: crate::Input::into_external()
91/// [`Reader::try_expect_external()`]: crate::Reader::try_expect_external()
92pub trait External<'i>: Sized {
93    /// The specific section of input that caused an error.
94    fn span(&self) -> Option<Span> {
95        None
96    }
97
98    /// Returns the requirement, if applicable, to retry processing the `Input`.
99    ///
100    /// [`External`] errors are designed for producers of errors and won't
101    /// expose themselves directly to consumers so they do not require
102    /// `ToRetryRequirement` implementations but can return a
103    /// [`RetryRequirement`].
104    ///
105    /// [`ToRetryRequirement`]: crate::ToRetryRequirement
106    fn retry_requirement(&self) -> Option<RetryRequirement> {
107        None
108    }
109
110    /// Pushes a child backtrace to the base error generated.
111    ///
112    /// Push from the bottom of the trace (from the source of the error) up.
113    fn push_backtrace<E>(self, error: E) -> E
114    where
115        E: WithContext<'i>,
116    {
117        error
118    }
119}