#[cfg(all(feature = "error_in_core"))]
use core::error::Error;
#[cfg(all(not(feature = "error_in_core"), feature = "std"))]
use std::error::Error;
#[cfg(feature = "std")]
use std::sync::MutexGuard;
#[cfg(feature = "std")]
use std::sync::PoisonError;
use core::alloc::LayoutError;
use core::fmt::Debug;
#[cfg(any(feature = "std", feature = "error_in_core"))]
use core::fmt::{Display, Formatter, Result as FmtResult};
use crate::range::ByteRange;
#[derive(Debug)]
pub enum LockingError {
Poisoned {
source: LockSource,
},
WouldBlock,
}
#[cfg(any(feature = "std", feature = "error_in_core"))]
impl Display for LockingError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
LockingError::Poisoned { source: which } => match which {
LockSource::BaseAddress => {
write!(f, "Cannot acquire lock: base address Mutex was poisoned")
}
LockSource::AllocationTracker => write!(
f,
"Cannot acquire lock: AllocationTracker Mutex was poisoned"
),
LockSource::Reference => write!(
f,
"Cannot acquire lock: reference concurrent mutable access exclusion flag Mutex was poisoned"
)
},
LockingError::WouldBlock => write!(f, "Lock would be block"),
}
}
}
#[cfg(any(feature = "std", feature = "error_in_core"))]
impl Error for LockingError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
}
#[cfg(feature = "std")]
impl From<PoisonError<MutexGuard<'_, *mut u8>>> for LockingError {
fn from(_: PoisonError<MutexGuard<'_, *mut u8>>) -> Self {
LockingError::Poisoned {
source: LockSource::BaseAddress,
}
}
}
#[cfg(feature = "std")]
impl From<PoisonError<MutexGuard<'_, crate::tracker::AllocationTracker>>> for LockingError {
fn from(_: PoisonError<MutexGuard<'_, crate::tracker::AllocationTracker>>) -> Self {
LockingError::Poisoned {
source: LockSource::AllocationTracker,
}
}
}
#[cfg(feature = "std")]
impl<T> From<std::sync::TryLockError<T>> for LockingError
where
LockingError: From<PoisonError<T>>,
{
fn from(value: std::sync::TryLockError<T>) -> Self {
match value {
std::sync::TryLockError::Poisoned(poison_err) => LockingError::from(poison_err),
std::sync::TryLockError::WouldBlock => LockingError::WouldBlock,
}
}
}
#[derive(Debug)]
pub struct RegionBorrowed {
pub range: ByteRange,
}
#[cfg(any(feature = "std", feature = "error_in_core"))]
impl Display for RegionBorrowed {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(
f,
"attempted to borrow already mutably borrowed memory region: {}",
self.range
)
}
}
#[cfg(any(feature = "std", feature = "error_in_core"))]
impl Error for RegionBorrowed {
fn source(&self) -> Option<&(dyn Error + 'static)> {
None
}
}
#[derive(Debug)]
#[non_exhaustive]
pub enum ContiguousMemoryError {
NoStorageLeft,
AlreadyUsed,
NotContained,
DoubleFree,
Unshrinkable {
required_size: usize,
},
Lock(LockingError),
TrackerInUse,
Layout(
LayoutError,
),
BorrowMut(RegionBorrowed),
}
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub enum LockSource {
BaseAddress,
AllocationTracker,
Reference,
}
#[cfg(any(feature = "std", feature = "error_in_core"))]
impl Display for ContiguousMemoryError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
ContiguousMemoryError::NoStorageLeft => {
write!(f, "Insufficient free storage available")
}
ContiguousMemoryError::NotContained => {
write!(f, "Attempted to mark a memory region that isn't contained")
}
ContiguousMemoryError::AlreadyUsed => write!(
f,
"Attempted to take a memory region that is already marked as occupied"
),
ContiguousMemoryError::DoubleFree => write!(
f,
"Attempted to free a memory region that is already marked as free"
),
ContiguousMemoryError::Unshrinkable {
required_size: min_required,
} => write!(
f,
"Cannot shrink memory regions; minimum required space: {} bytes",
min_required
),
ContiguousMemoryError::Lock(it) => write!(f, "Poison error: {}", it),
ContiguousMemoryError::TrackerInUse => {
write!(f, "Cannot borrow AllocationTracker: it is already in use")
}
ContiguousMemoryError::Layout(it) => write!(f, "Layout error: {}", it),
ContiguousMemoryError::BorrowMut(it) => write!(f, "Borrow mutable error: {}", it),
}
}
}
#[cfg(any(feature = "std", feature = "error_in_core"))]
impl Error for ContiguousMemoryError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
ContiguousMemoryError::Layout(it) => Some(it),
ContiguousMemoryError::Lock(it) => Some(it),
_ => None,
}
}
}
impl From<LockingError> for ContiguousMemoryError {
fn from(layout_err: LockingError) -> Self {
ContiguousMemoryError::Lock(layout_err)
}
}
impl From<LayoutError> for ContiguousMemoryError {
fn from(layout_err: LayoutError) -> Self {
ContiguousMemoryError::Layout(layout_err)
}
}