error_stack/frame/
mod.rs

1mod frame_impl;
2mod kind;
3
4#[cfg_attr(feature = "std", allow(unused_imports))]
5use alloc::boxed::Box;
6#[cfg(nightly)]
7use core::error::{self, Error};
8use core::{any::TypeId, fmt};
9
10use self::frame_impl::FrameImpl;
11pub use self::kind::{AttachmentKind, FrameKind};
12
13/// A single context or attachment inside of a [`Report`].
14///
15/// `Frame`s are organized as a singly linked list, which can be iterated by calling
16/// [`Report::frames()`]. The head contains the current context or attachment, and the tail contains
17/// the root context created by [`Report::new()`]. The next `Frame` can be accessed by requesting it
18/// by calling [`Report::request_ref()`].
19///
20/// [`Report`]: crate::Report
21/// [`Report::frames()`]: crate::Report::frames
22/// [`Report::new()`]: crate::Report::new
23/// [`Report::request_ref()`]: crate::Report::request_ref
24pub struct Frame {
25    frame: Box<dyn FrameImpl>,
26    sources: Box<[Frame]>,
27}
28
29impl Frame {
30    /// Returns a shared reference to the source of this `Frame`.
31    ///
32    /// This corresponds to the `Frame` below this one in a [`Report`].
33    ///
34    /// [`Report`]: crate::Report
35    #[must_use]
36    pub const fn sources(&self) -> &[Self] {
37        &self.sources
38    }
39
40    /// Returns a mutable reference to the sources of this `Frame`.
41    ///
42    /// This corresponds to the `Frame` below this one in a [`Report`].
43    ///
44    /// [`Report`]: crate::Report
45    #[must_use]
46    pub fn sources_mut(&mut self) -> &mut [Self] {
47        &mut self.sources
48    }
49
50    /// Returns how the `Frame` was created.
51    #[must_use]
52    pub fn kind(&self) -> FrameKind<'_> {
53        self.frame.kind()
54    }
55
56    /// Requests the reference to `T` from the `Frame` if provided.
57    #[must_use]
58    #[cfg(nightly)]
59    pub fn request_ref<T>(&self) -> Option<&T>
60    where
61        T: ?Sized + 'static,
62    {
63        error::request_ref(self.as_error())
64    }
65
66    /// Requests the value of `T` from the `Frame` if provided.
67    #[must_use]
68    #[cfg(nightly)]
69    pub fn request_value<T>(&self) -> Option<T>
70    where
71        T: 'static,
72    {
73        error::request_value(self.as_error())
74    }
75
76    /// Returns if `T` is the held context or attachment by this frame.
77    #[must_use]
78    pub fn is<T: Send + Sync + 'static>(&self) -> bool {
79        self.frame.as_any().is::<T>()
80    }
81
82    /// Downcasts this frame if the held context or attachment is the same as `T`.
83    #[must_use]
84    pub fn downcast_ref<T: Send + Sync + 'static>(&self) -> Option<&T> {
85        self.frame.as_any().downcast_ref()
86    }
87
88    /// Downcasts this frame if the held context or attachment is the same as `T`.
89    #[must_use]
90    pub fn downcast_mut<T: Send + Sync + 'static>(&mut self) -> Option<&mut T> {
91        self.frame.as_any_mut().downcast_mut()
92    }
93
94    /// Returns the [`TypeId`] of the held context or attachment by this frame.
95    #[must_use]
96    pub fn type_id(&self) -> TypeId {
97        self.frame.as_any().type_id()
98    }
99
100    #[cfg(nightly)]
101    pub(crate) fn as_error(&self) -> &impl Error {
102        &self.frame
103    }
104}
105
106impl fmt::Debug for Frame {
107    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
108        let mut debug = fmt.debug_struct("Frame");
109
110        match self.kind() {
111            FrameKind::Context(context) => {
112                debug.field("context", &context);
113                debug.finish()
114            }
115            FrameKind::Attachment(AttachmentKind::Printable(attachment)) => {
116                debug.field("attachment", &attachment);
117                debug.finish()
118            }
119            FrameKind::Attachment(AttachmentKind::Opaque(_)) => debug.finish_non_exhaustive(),
120        }
121    }
122}