1use core::alloc::{Layout, LayoutError};
4use core::fmt;
5
6#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum StorageError {
9 AllocError(Layout),
11 CapacityLimit,
13 LayoutError(LayoutError),
15 ProtectionError,
17 Unsupported,
19}
20
21impl StorageError {
22 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 #[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#[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 pub fn as_str(&self) -> &'static str {
76 "Update error"
77 }
78
79 pub fn error(&self) -> &StorageError {
81 &self.error
82 }
83
84 pub fn into_value(self) -> T {
86 self.value
87 }
88
89 #[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 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}