1#[cfg(feature = "error_in_core")]
4use core::error::Error;
5#[cfg(all(not(feature = "error_in_core"), not(feature = "no_std")))]
6use std::error::Error;
7
8#[cfg(not(feature = "no_std"))]
9use std::sync::MutexGuard;
10#[cfg(not(feature = "no_std"))]
11use std::sync::PoisonError;
12
13use core::alloc::LayoutError;
14use core::fmt::Debug;
15#[cfg(any(not(feature = "no_std"), feature = "error_in_core"))]
16use core::fmt::{Display, Formatter, Result as FmtResult};
17
18use crate::range::ByteRange;
19
20#[derive(Debug)]
23pub enum LockingError {
24 Poisoned {
26 source: LockSource,
28 },
29 WouldBlock {
31 source: LockSource,
33 },
34}
35
36#[cfg(any(not(feature = "no_std"), feature = "error_in_core"))]
37impl Display for LockingError {
38 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
39 match self {
40 LockingError::Poisoned { source } => write!(
41 f,
42 "Cannot acquire lock: {}",
43 match source {
44 LockSource::BaseAddress => {
45 "base address Mutex was poisoned"
46 }
47 LockSource::AllocationTracker => "AllocationTracker Mutex was poisoned",
48 LockSource::Reference =>
49 "reference concurrent mutable access exclusion flag Mutex was poisoned",
50 }
51 ),
52 LockingError::WouldBlock { source } => write!(
53 f,
54 "Lock would block the current thread: {}",
55 match source {
56 LockSource::BaseAddress => "base address already borrowed",
57 LockSource::AllocationTracker => "AllocationTracker already borrowed",
58 LockSource::Reference => "reference already borrowed",
59 }
60 ),
61 }
62 }
63}
64
65#[cfg(any(not(feature = "no_std"), feature = "error_in_core"))]
66impl Error for LockingError {
67 fn source(&self) -> Option<&(dyn Error + 'static)> {
68 None
69 }
70}
71
72#[cfg(not(feature = "no_std"))]
73impl From<PoisonError<MutexGuard<'_, *mut u8>>> for LockingError {
74 fn from(_: PoisonError<MutexGuard<'_, *mut u8>>) -> Self {
75 LockingError::Poisoned {
76 source: LockSource::BaseAddress,
77 }
78 }
79}
80
81#[cfg(not(feature = "no_std"))]
82impl From<PoisonError<MutexGuard<'_, crate::tracker::AllocationTracker>>> for LockingError {
83 fn from(_: PoisonError<MutexGuard<'_, crate::tracker::AllocationTracker>>) -> Self {
84 LockingError::Poisoned {
85 source: LockSource::AllocationTracker,
86 }
87 }
88}
89
90#[derive(Debug)]
93pub struct RegionBorrowedError {
94 pub range: ByteRange,
96}
97
98#[cfg(any(not(feature = "no_std"), feature = "error_in_core"))]
99impl Display for RegionBorrowedError {
100 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
101 write!(
102 f,
103 "attempted to borrow already mutably borrowed memory region: {}",
104 self.range
105 )
106 }
107}
108
109#[cfg(any(not(feature = "no_std"), feature = "error_in_core"))]
110impl Error for RegionBorrowedError {
111 fn source(&self) -> Option<&(dyn Error + 'static)> {
112 None
113 }
114}
115
116#[derive(Debug)]
119#[non_exhaustive]
120pub enum ContiguousMemoryError {
121 NoStorageLeft,
124 AlreadyUsed,
126 NotContained,
129 DoubleFree,
131 Unshrinkable {
134 required_size: usize,
136 },
137 Lock(LockingError),
139 Layout(
141 LayoutError,
144 ),
145 BorrowMut(RegionBorrowedError),
147}
148
149#[derive(Debug, Clone, Copy)]
151#[non_exhaustive]
152pub enum LockSource {
153 BaseAddress,
155 AllocationTracker,
157 Reference,
160}
161
162#[cfg(any(not(feature = "no_std"), feature = "error_in_core"))]
163impl Display for ContiguousMemoryError {
164 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
165 match self {
166 ContiguousMemoryError::NoStorageLeft => {
167 write!(f, "Insufficient free storage available")
168 }
169 ContiguousMemoryError::NotContained => {
170 write!(f, "Attempted to mark a memory region that isn't contained")
171 }
172 ContiguousMemoryError::AlreadyUsed => write!(
173 f,
174 "Attempted to take a memory region that is already marked as occupied"
175 ),
176 ContiguousMemoryError::DoubleFree => write!(
177 f,
178 "Attempted to free a memory region that is already marked as free"
179 ),
180 ContiguousMemoryError::Unshrinkable {
181 required_size: min_required,
182 } => write!(
183 f,
184 "Cannot shrink memory regions; minimum required space: {} bytes",
185 min_required
186 ),
187 ContiguousMemoryError::Lock(it) => write!(f, "Poison error: {}", it),
188 ContiguousMemoryError::Layout(it) => write!(f, "Layout error: {}", it),
189 ContiguousMemoryError::BorrowMut(it) => write!(f, "Borrow mutable error: {}", it),
190 }
191 }
192}
193
194#[cfg(any(not(feature = "no_std"), feature = "error_in_core"))]
195impl Error for ContiguousMemoryError {
196 fn source(&self) -> Option<&(dyn Error + 'static)> {
197 match self {
198 ContiguousMemoryError::Layout(it) => Some(it),
199 ContiguousMemoryError::Lock(it) => Some(it),
200 _ => None,
201 }
202 }
203}
204
205impl From<LockingError> for ContiguousMemoryError {
206 fn from(layout_err: LockingError) -> Self {
207 ContiguousMemoryError::Lock(layout_err)
208 }
209}
210
211impl From<LayoutError> for ContiguousMemoryError {
212 fn from(layout_err: LayoutError) -> Self {
213 ContiguousMemoryError::Layout(layout_err)
214 }
215}