flex_alloc/
error.rs

1//! Error handling.
2
3use core::alloc::{Layout, LayoutError};
4use core::fmt;
5
6/// An enumeration of error types raised by storage implementations.
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum StorageError {
9    /// A memory allocation failed.
10    AllocError(Layout),
11    /// The limit of the current allocation was reached.
12    CapacityLimit,
13    /// The provided layout was not allocatable.
14    LayoutError(LayoutError),
15    /// Memory protection failed.
16    ProtectionError,
17    /// The requested operation is not supported for this storage.
18    Unsupported,
19}
20
21impl StorageError {
22    /// Generic description of this error.
23    pub fn as_str(&self) -> &'static str {
24        match self {
25            Self::AllocError(_) => "Allocation error",
26            Self::CapacityLimit => "Exceeded storage capacity limit",
27            Self::LayoutError(_) => "Layout error",
28            Self::ProtectionError => "Memory protection failed",
29            Self::Unsupported => "Unsupported",
30        }
31    }
32
33    /// Generate a panic with this error as the reason.
34    #[cold]
35    #[inline(never)]
36    pub fn panic(self) -> ! {
37        if let Self::AllocError(layout) = self {
38            crate::alloc::handle_alloc_error(layout);
39        } else {
40            panic!("{}", self.as_str())
41        }
42    }
43}
44
45impl fmt::Display for StorageError {
46    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47        f.write_str(self.as_str())
48    }
49}
50
51impl From<LayoutError> for StorageError {
52    fn from(err: LayoutError) -> Self {
53        Self::LayoutError(err)
54    }
55}
56
57#[cfg(feature = "std")]
58impl std::error::Error for StorageError {}
59
60/// An error raised by collection update operations when appropriate
61/// storage was not available. Includes an associated value that
62/// could not be stored or converted.
63#[derive(Clone)]
64pub struct UpdateError<T> {
65    pub(crate) error: StorageError,
66    pub(crate) value: T,
67}
68
69impl<T> UpdateError<T> {
70    pub(crate) fn new(error: StorageError, value: T) -> Self {
71        Self { error, value }
72    }
73
74    /// Generic description of this error
75    pub fn as_str(&self) -> &'static str {
76        "Update error"
77    }
78
79    /// Get a reference to the contained `StorageError`
80    pub fn error(&self) -> &StorageError {
81        &self.error
82    }
83
84    /// Unwrap the inner value of this error
85    pub fn into_value(self) -> T {
86        self.value
87    }
88
89    /// Generate a panic with this error as the reason
90    #[cold]
91    #[inline(never)]
92    pub fn panic(self) -> ! {
93        panic!("{}: {}", self.as_str(), self.error.as_str());
94    }
95}
96
97impl<T> fmt::Debug for UpdateError<T> {
98    #[inline]
99    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
100        f.debug_struct("UpdateError")
101            .field("error", &self.error)
102            .finish_non_exhaustive()
103    }
104}
105
106impl<T> fmt::Display for UpdateError<T> {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        f.write_fmt(format_args!("{}: {}", self.as_str(), self.error))
109    }
110}
111
112#[cfg(feature = "std")]
113impl<T> std::error::Error for UpdateError<T> {}
114
115#[cfg(test)]
116mod tests {
117    use super::StorageError;
118    use core::alloc::Layout;
119
120    #[test]
121    #[should_panic(expected = "memory allocation of 8 bytes failed")]
122    fn alloc_error_panic() {
123        // When testing, crate::alloc::handle_alloc_error is replaced with an
124        // explicit panic. This is because #[should_panic] does not currently
125        // capture the panic that is started in the standard out-of-memory handler.
126        let a = StorageError::AllocError(Layout::new::<usize>());
127        a.panic();
128    }
129
130    #[test]
131    #[should_panic(expected = "Layout error")]
132    fn layout_error_panic() {
133        let err = Layout::from_size_align(0, 3).expect_err("expected layout error");
134        let a = StorageError::LayoutError(err);
135        a.panic();
136    }
137}