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}