1 use crate::error::ContextError; 2 use crate::{Context, Error, StdError}; 3 use core::convert::Infallible; 4 use core::fmt::{self, Debug, Display, Write}; 5 6 #[cfg(backtrace)] 7 use std::backtrace::Backtrace; 8 9 mod ext { 10 use super::*; 11 12 pub trait StdError { ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static13 fn ext_context<C>(self, context: C) -> Error 14 where 15 C: Display + Send + Sync + 'static; 16 } 17 18 #[cfg(feature = "std")] 19 impl<E> StdError for E 20 where 21 E: std::error::Error + Send + Sync + 'static, 22 { ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static,23 fn ext_context<C>(self, context: C) -> Error 24 where 25 C: Display + Send + Sync + 'static, 26 { 27 let backtrace = backtrace_if_absent!(self); 28 Error::from_context(context, self, backtrace) 29 } 30 } 31 32 impl StdError for Error { ext_context<C>(self, context: C) -> Error where C: Display + Send + Sync + 'static,33 fn ext_context<C>(self, context: C) -> Error 34 where 35 C: Display + Send + Sync + 'static, 36 { 37 self.context(context) 38 } 39 } 40 } 41 42 impl<T, E> Context<T, E> for Result<T, E> 43 where 44 E: ext::StdError + Send + Sync + 'static, 45 { context<C>(self, context: C) -> Result<T, Error> where C: Display + Send + Sync + 'static,46 fn context<C>(self, context: C) -> Result<T, Error> 47 where 48 C: Display + Send + Sync + 'static, 49 { 50 self.map_err(|error| error.ext_context(context)) 51 } 52 with_context<C, F>(self, context: F) -> Result<T, Error> where C: Display + Send + Sync + 'static, F: FnOnce() -> C,53 fn with_context<C, F>(self, context: F) -> Result<T, Error> 54 where 55 C: Display + Send + Sync + 'static, 56 F: FnOnce() -> C, 57 { 58 self.map_err(|error| error.ext_context(context())) 59 } 60 } 61 62 /// ``` 63 /// # type T = (); 64 /// # 65 /// use anyhow::{Context, Result}; 66 /// 67 /// fn maybe_get() -> Option<T> { 68 /// # const IGNORE: &str = stringify! { 69 /// ... 70 /// # }; 71 /// # unimplemented!() 72 /// } 73 /// 74 /// fn demo() -> Result<()> { 75 /// let t = maybe_get().context("there is no T")?; 76 /// # const IGNORE: &str = stringify! { 77 /// ... 78 /// # }; 79 /// # unimplemented!() 80 /// } 81 /// ``` 82 impl<T> Context<T, Infallible> for Option<T> { context<C>(self, context: C) -> Result<T, Error> where C: Display + Send + Sync + 'static,83 fn context<C>(self, context: C) -> Result<T, Error> 84 where 85 C: Display + Send + Sync + 'static, 86 { 87 self.ok_or_else(|| Error::from_display(context, backtrace!())) 88 } 89 with_context<C, F>(self, context: F) -> Result<T, Error> where C: Display + Send + Sync + 'static, F: FnOnce() -> C,90 fn with_context<C, F>(self, context: F) -> Result<T, Error> 91 where 92 C: Display + Send + Sync + 'static, 93 F: FnOnce() -> C, 94 { 95 self.ok_or_else(|| Error::from_display(context(), backtrace!())) 96 } 97 } 98 99 impl<C, E> Debug for ContextError<C, E> 100 where 101 C: Display, 102 E: Debug, 103 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result104 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 105 f.debug_struct("Error") 106 .field("context", &Quoted(&self.context)) 107 .field("source", &self.error) 108 .finish() 109 } 110 } 111 112 impl<C, E> Display for ContextError<C, E> 113 where 114 C: Display, 115 { fmt(&self, f: &mut fmt::Formatter) -> fmt::Result116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 117 Display::fmt(&self.context, f) 118 } 119 } 120 121 impl<C, E> StdError for ContextError<C, E> 122 where 123 C: Display, 124 E: StdError + 'static, 125 { 126 #[cfg(backtrace)] backtrace(&self) -> Option<&Backtrace>127 fn backtrace(&self) -> Option<&Backtrace> { 128 self.error.backtrace() 129 } 130 source(&self) -> Option<&(dyn StdError + 'static)>131 fn source(&self) -> Option<&(dyn StdError + 'static)> { 132 Some(&self.error) 133 } 134 } 135 136 impl<C> StdError for ContextError<C, Error> 137 where 138 C: Display, 139 { 140 #[cfg(backtrace)] backtrace(&self) -> Option<&Backtrace>141 fn backtrace(&self) -> Option<&Backtrace> { 142 Some(self.error.backtrace()) 143 } 144 source(&self) -> Option<&(dyn StdError + 'static)>145 fn source(&self) -> Option<&(dyn StdError + 'static)> { 146 Some(unsafe { crate::ErrorImpl::error(self.error.inner.by_ref()) }) 147 } 148 } 149 150 struct Quoted<C>(C); 151 152 impl<C> Debug for Quoted<C> 153 where 154 C: Display, 155 { fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result156 fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 157 formatter.write_char('"')?; 158 Quoted(&mut *formatter).write_fmt(format_args!("{}", self.0))?; 159 formatter.write_char('"')?; 160 Ok(()) 161 } 162 } 163 164 impl Write for Quoted<&mut fmt::Formatter<'_>> { write_str(&mut self, s: &str) -> fmt::Result165 fn write_str(&mut self, s: &str) -> fmt::Result { 166 Display::fmt(&s.escape_debug(), self.0) 167 } 168 } 169 170 pub(crate) mod private { 171 use super::*; 172 173 pub trait Sealed {} 174 175 impl<T, E> Sealed for Result<T, E> where E: ext::StdError {} 176 impl<T> Sealed for Option<T> {} 177 } 178