use {
crate::{layout::Layout, traits::data::type_props::SizedProps},
::core::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
write
}
};
macro_rules! impl_error {
($ty:ident) => {
#[cfg(feature = "std")]
impl ::std::error::Error for $ty {}
#[cfg(not(feature = "std"))]
#[::rustversion::since(1.81)]
impl ::core::error::Error for $ty {}
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum Error {
AllocFailed(Layout, Cause),
InvalidLayout(usize, usize, LayoutErr),
ZeroSizedLayout,
DanglingDeallocation,
GrowSmallerNewLayout(usize, usize),
ShrinkLargerNewLayout(usize, usize),
ArithmeticError(ArithErr),
CaughtUnwind,
Unsupported,
Other(&'static str)
}
impl Display for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
use Error::{
AllocFailed,
ArithmeticError,
CaughtUnwind,
DanglingDeallocation,
GrowSmallerNewLayout,
InvalidLayout,
Other,
ShrinkLargerNewLayout,
Unsupported,
ZeroSizedLayout
};
match self {
AllocFailed(l, cause) => write!(
f,
"allocation failed:\n\tlayout:\n\t\tsize: {}\n\t\talign: {}\n\tcause: {}",
l.size(),
l.align(),
cause
),
InvalidLayout(sz, aln, e) => write!(
f,
"computed invalid layout:\n\tsize: {}\n\talign: {}\n\treason: {}",
sz, aln, e
),
ZeroSizedLayout => {
write!(f, "received a zero-sized layout")
}
DanglingDeallocation => write!(f, "attempted to deallocate a dangling pointer"),
GrowSmallerNewLayout(old, new) => {
write!(f, "attempted to grow from a size of {} to a smaller size of {}", old, new)
}
ShrinkLargerNewLayout(old, new) => {
write!(f, "attempted to shrink from a size of {} to a larger size of {}", old, new)
}
ArithmeticError(overflow) => write!(f, "{}", overflow),
CaughtUnwind => {
write!(f, "unwind caught in unsupported function")
}
Unsupported => write!(f, "unsupported operation"),
Other(other) => write!(f, "{}", other)
}
}
}
impl_error! { Error }
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
#[repr(u8)]
pub enum Cause {
Unknown,
OutOfMemory,
Other(&'static str),
#[cfg(feature = "os_err_reporting")]
OSErr(i32)
}
impl Display for Cause {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
Cause::Unknown => write!(f, "unknown"),
Cause::OutOfMemory => write!(f, "out of memory"),
Cause::Other(other) => write!(f, "{}", other),
#[cfg(feature = "os_err_reporting")]
Cause::OSErr(e) => write!(f, "os error:\n\t{}", ::std::io::Error::from_raw_os_error(*e))
}
}
}
impl_error! { Cause }
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(u8)]
pub enum LayoutErr {
ZeroAlign,
NonPowerOfTwoAlign,
ExceedsMax,
ArithErr(ArithErr),
CRoundUp
}
impl Display for LayoutErr {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
LayoutErr::ZeroAlign => write!(f, "alignment is zero"),
LayoutErr::NonPowerOfTwoAlign => {
write!(f, "alignment isn't a power of two")
}
LayoutErr::ExceedsMax => write!(f, "size would overflow when rounded up to alignment"),
LayoutErr::ArithErr(overflow) => write!(f, "layout err: {}", overflow),
LayoutErr::CRoundUp => {
write!(f, "failed to round layout alignment up to a multiple of {}", usize::SZ)
}
}
}
}
impl_error! { LayoutErr }
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct ArithErr(pub usize, pub ArithOp, pub usize);
impl Display for ArithErr {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "arithmetic operation would overflow: {} {} {}", self.0, self.1, self.2)
}
}
impl_error! { ArithErr }
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(u8)]
pub enum ArithOp {
Add,
Sub,
Mul,
Div,
Rem,
Pow
}
impl Display for ArithOp {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self {
ArithOp::Add => write!(f, "+"),
ArithOp::Sub => write!(f, "-"),
ArithOp::Mul => write!(f, "*"),
ArithOp::Div => write!(f, "/"),
ArithOp::Rem => write!(f, "%"),
ArithOp::Pow => write!(f, "**")
}
}
}