1use core::{
2 convert::Infallible,
3 fmt::{self, Debug, Display, Write},
4};
5#[cfg(error_generic_member_access)]
6use std::error::Request;
7
8use crate::{Context, Error, StdError, error::ContextError};
9
10mod ext {
11 use super::*;
12
13 pub trait StdError {
14 fn ext_context<C>(self, context: C) -> Error
15 where
16 C: Display + Send + Sync + 'static;
17 }
18
19 #[cfg(feature = "std")]
20 impl<E> StdError for E
21 where
22 E: std::error::Error + Send + Sync + 'static,
23 {
24 fn ext_context<C>(self, context: C) -> Error
25 where
26 C: Display + Send + Sync + 'static,
27 {
28 let backtrace = backtrace_if_absent!(&self);
29 Error::from_context(context, self, backtrace)
30 }
31 }
32
33 impl StdError for Error {
34 fn ext_context<C>(self, context: C) -> Error
35 where
36 C: Display + Send + Sync + 'static,
37 {
38 self.context(context)
39 }
40 }
41}
42
43impl<T, E> Context<T, E> for Result<T, E>
44where
45 E: ext::StdError + Send + Sync + 'static,
46{
47 fn context<C>(self, context: C) -> Result<T, Error>
48 where
49 C: Display + Send + Sync + 'static,
50 {
51 match self {
54 Ok(ok) => Ok(ok),
55 Err(error) => Err(error.ext_context(context)),
56 }
57 }
58
59 fn with_context<C, F>(self, context: F) -> Result<T, Error>
60 where
61 C: Display + Send + Sync + 'static,
62 F: FnOnce() -> C,
63 {
64 match self {
65 Ok(ok) => Ok(ok),
66 Err(error) => Err(error.ext_context(context())),
67 }
68 }
69}
70
71impl<T> Context<T, Infallible> for Option<T> {
92 fn context<C>(self, context: C) -> Result<T, Error>
93 where
94 C: Display + Send + Sync + 'static,
95 {
96 match self {
99 Some(ok) => Ok(ok),
100 None => Err(Error::from_display(context, backtrace!())),
101 }
102 }
103
104 fn with_context<C, F>(self, context: F) -> Result<T, Error>
105 where
106 C: Display + Send + Sync + 'static,
107 F: FnOnce() -> C,
108 {
109 match self {
110 Some(ok) => Ok(ok),
111 None => Err(Error::from_display(context(), backtrace!())),
112 }
113 }
114}
115
116impl<C, E> Debug for ContextError<C, E>
117where
118 C: Display,
119 E: Debug,
120{
121 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
122 f.debug_struct("Error")
123 .field("context", &Quoted(&self.context))
124 .field("source", &self.error)
125 .finish()
126 }
127}
128
129impl<C, E> Display for ContextError<C, E>
130where
131 C: Display,
132{
133 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
134 Display::fmt(&self.context, f)
135 }
136}
137
138impl<C, E> StdError for ContextError<C, E>
139where
140 C: Display,
141 E: StdError + 'static,
142{
143 fn source(&self) -> Option<&(dyn StdError + 'static)> {
144 Some(&self.error)
145 }
146
147 #[cfg(error_generic_member_access)]
148 fn provide<'a>(&'a self, request: &mut Request<'a>) {
149 StdError::provide(&self.error, request);
150 }
151}
152
153impl<C> StdError for ContextError<C, Error>
154where
155 C: Display,
156{
157 fn source(&self) -> Option<&(dyn StdError + 'static)> {
158 Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) })
159 }
160
161 #[cfg(error_generic_member_access)]
162 fn provide<'a>(&'a self, request: &mut Request<'a>) {
163 Error::provide(&self.error, request);
164 }
165}
166
167struct Quoted<C>(C);
168
169impl<C> Debug for Quoted<C>
170where
171 C: Display,
172{
173 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
174 formatter.write_char('"')?;
175 Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?;
176 formatter.write_char('"')?;
177 Ok(())
178 }
179}
180
181impl Write for Quoted<&mut fmt::Formatter<'_>> {
182 fn write_str(&mut self, s: &str) -> fmt::Result {
183 Display::fmt(&s.escape_debug(), self.0)
184 }
185}
186
187pub(crate) mod private {
188 use super::*;
189
190 pub trait Sealed {}
191
192 impl<T, E> Sealed for Result<T, E> where E: ext::StdError {}
193 impl<T> Sealed for Option<T> {}
194}