error_stack/frame/
frame_impl.rs

1#[cfg_attr(feature = "std", allow(unused_imports))]
2use alloc::boxed::Box;
3#[cfg(nightly)]
4use core::error::{Error, Request};
5use core::{any::Any, fmt};
6
7use crate::{AttachmentKind, Context, Frame, FrameKind};
8
9/// Internal representation of a [`Frame`].
10pub(super) trait FrameImpl: Send + Sync + 'static {
11    fn kind(&self) -> FrameKind<'_>;
12
13    fn as_any(&self) -> &dyn Any;
14
15    fn as_any_mut(&mut self) -> &mut dyn Any;
16
17    /// Provide values which can then be requested.
18    #[cfg(nightly)]
19    fn provide<'a>(&'a self, request: &mut Request<'a>);
20}
21
22#[cfg(nightly)]
23impl fmt::Debug for Box<dyn FrameImpl> {
24    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
25        unreachable!()
26    }
27}
28
29#[cfg(nightly)]
30impl fmt::Display for Box<dyn FrameImpl> {
31    fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
32        unreachable!()
33    }
34}
35
36#[cfg(nightly)]
37impl Error for Box<dyn FrameImpl> {
38    fn provide<'a>(&'a self, request: &mut Request<'a>) {
39        (**self).provide(request);
40    }
41}
42
43struct ContextFrame<C> {
44    context: C,
45}
46
47impl<C: Context> FrameImpl for ContextFrame<C> {
48    fn kind(&self) -> FrameKind<'_> {
49        FrameKind::Context(&self.context)
50    }
51
52    fn as_any(&self) -> &dyn Any {
53        &self.context
54    }
55
56    fn as_any_mut(&mut self) -> &mut dyn Any {
57        &mut self.context
58    }
59
60    #[cfg(nightly)]
61    fn provide<'a>(&'a self, request: &mut Request<'a>) {
62        Context::provide(&self.context, request);
63    }
64}
65
66struct AttachmentFrame<A> {
67    attachment: A,
68}
69
70impl<A: 'static + Send + Sync> FrameImpl for AttachmentFrame<A> {
71    fn kind(&self) -> FrameKind<'_> {
72        FrameKind::Attachment(AttachmentKind::Opaque(&self.attachment))
73    }
74
75    fn as_any(&self) -> &dyn Any {
76        &self.attachment
77    }
78
79    fn as_any_mut(&mut self) -> &mut dyn Any {
80        &mut self.attachment
81    }
82
83    #[cfg(nightly)]
84    fn provide<'a>(&'a self, request: &mut Request<'a>) {
85        request.provide_ref(&self.attachment);
86    }
87}
88
89struct PrintableAttachmentFrame<A> {
90    attachment: A,
91}
92
93impl<A: 'static + fmt::Debug + fmt::Display + Send + Sync> FrameImpl
94    for PrintableAttachmentFrame<A>
95{
96    fn kind(&self) -> FrameKind<'_> {
97        FrameKind::Attachment(AttachmentKind::Printable(&self.attachment))
98    }
99
100    fn as_any(&self) -> &dyn Any {
101        &self.attachment
102    }
103
104    fn as_any_mut(&mut self) -> &mut dyn Any {
105        &mut self.attachment
106    }
107
108    #[cfg(nightly)]
109    fn provide<'a>(&'a self, request: &mut Request<'a>) {
110        request.provide_ref(&self.attachment);
111    }
112}
113
114#[cfg(feature = "anyhow")]
115struct AnyhowContext(anyhow::Error);
116
117#[cfg(feature = "anyhow")]
118impl fmt::Debug for AnyhowContext {
119    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
120        fmt::Debug::fmt(&self.0, fmt)
121    }
122}
123
124#[cfg(feature = "anyhow")]
125impl fmt::Display for AnyhowContext {
126    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
127        fmt::Display::fmt(&self.0, fmt)
128    }
129}
130
131#[cfg(feature = "anyhow")]
132impl Context for AnyhowContext {
133    #[cfg(all(nightly, feature = "std"))]
134    #[inline]
135    fn provide<'a>(&'a self, request: &mut Request<'a>) {
136        request.provide_ref(self.0.backtrace());
137    }
138}
139
140#[cfg(feature = "anyhow")]
141impl FrameImpl for AnyhowContext {
142    fn kind(&self) -> FrameKind<'_> {
143        FrameKind::Context(self)
144    }
145
146    fn as_any(&self) -> &dyn Any {
147        &self.0
148    }
149
150    fn as_any_mut(&mut self) -> &mut dyn Any {
151        &mut self.0
152    }
153
154    #[cfg(nightly)]
155    #[inline]
156    fn provide<'a>(&'a self, request: &mut Request<'a>) {
157        Context::provide(self, request);
158    }
159}
160
161#[cfg(feature = "eyre")]
162struct EyreContext(eyre::Report);
163
164#[cfg(feature = "eyre")]
165impl fmt::Debug for EyreContext {
166    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
167        fmt::Debug::fmt(&self.0, fmt)
168    }
169}
170
171#[cfg(feature = "eyre")]
172impl fmt::Display for EyreContext {
173    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
174        fmt::Display::fmt(&self.0, fmt)
175    }
176}
177
178#[cfg(feature = "eyre")]
179impl Context for EyreContext {
180    #[cfg(nightly)]
181    #[inline]
182    fn provide<'a>(&'a self, request: &mut Request<'a>) {
183        Error::provide(self.0.as_ref() as &dyn Error, request);
184    }
185}
186
187#[cfg(feature = "eyre")]
188impl FrameImpl for EyreContext {
189    fn kind(&self) -> FrameKind<'_> {
190        FrameKind::Context(self)
191    }
192
193    fn as_any(&self) -> &dyn Any {
194        &self.0
195    }
196
197    fn as_any_mut(&mut self) -> &mut dyn Any {
198        &mut self.0
199    }
200
201    #[cfg(nightly)]
202    #[inline]
203    fn provide<'a>(&'a self, request: &mut Request<'a>) {
204        Context::provide(self, request);
205    }
206}
207
208impl Frame {
209    /// Creates a frame from a [`Context`].
210    pub(crate) fn from_context<C>(context: C, sources: Box<[Self]>) -> Self
211    where
212        C: Context,
213    {
214        Self {
215            frame: Box::new(ContextFrame { context }),
216            sources,
217        }
218    }
219
220    /// Creates a frame from an attachment.
221    pub(crate) fn from_attachment<A>(attachment: A, sources: Box<[Self]>) -> Self
222    where
223        A: Send + Sync + 'static,
224    {
225        Self {
226            frame: Box::new(AttachmentFrame { attachment }),
227            sources,
228        }
229    }
230
231    /// Creates a frame from an attachment which implements [`Debug`] and [`Display`].
232    ///
233    /// [`Debug`]: core::fmt::Debug
234    /// [`Display`]: core::fmt::Display
235    pub(crate) fn from_printable_attachment<A>(attachment: A, sources: Box<[Self]>) -> Self
236    where
237        A: fmt::Display + fmt::Debug + Send + Sync + 'static,
238    {
239        Self {
240            frame: Box::new(PrintableAttachmentFrame { attachment }),
241            sources,
242        }
243    }
244
245    /// Creates a frame from an [`anyhow::Error`].
246    #[cfg(feature = "anyhow")]
247    pub(crate) fn from_anyhow(error: anyhow::Error, sources: Box<[Self]>) -> Self {
248        Self {
249            frame: Box::new(AnyhowContext(error)),
250            sources,
251        }
252    }
253
254    /// Creates a frame from an [`eyre::Report`].
255    #[cfg(feature = "eyre")]
256    pub(crate) fn from_eyre(report: eyre::Report, sources: Box<[Self]>) -> Self {
257        Self {
258            frame: Box::new(EyreContext(report)),
259            sources,
260        }
261    }
262}