1use core::{
2 alloc::Layout,
3 fmt::{Debug, Display, Formatter, Result as FmtResult},
4 ptr::NonNull
5};
6
7#[allow(clippy::module_name_repetitions)]
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10#[repr(u8)]
11pub enum AllocError {
12 AllocFailed(Layout, Cause),
16 InvalidLayout(InvLayout),
18 InvalidAlign(AlignErr),
20 ZeroSizedLayout(NonNull<u8>),
25 GrowSmallerNewLayout(usize, usize),
27 ShrinkLargerNewLayout(usize, usize),
29 ArithmeticError(ArithErr),
31 Other(&'static str)
33}
34
35impl AllocError {
36 #[allow(clippy::missing_errors_doc)]
38 #[cold]
39 #[inline(never)]
40 #[cfg_attr(not(feature = "dev"), doc(hidden))]
41 pub const fn arith_overflow(l: usize, op: ArithOp, r: usize) -> Result<usize, ArithErr> {
42 Err(ArithErr::Overflow(l, op, r))
43 }
44
45 #[allow(clippy::missing_errors_doc)]
47 #[cold]
48 #[inline(never)]
49 #[cfg_attr(not(feature = "dev"), doc(hidden))]
50 pub const fn inv_layout<Ret>(
51 sz: usize,
52 align: usize,
53 err: LayoutErr
54 ) -> Result<Ret, InvLayout> {
55 Err(InvLayout(sz, align, err))
56 }
57
58 #[cold]
60 #[inline(never)]
61 #[cfg_attr(not(feature = "dev"), doc(hidden))]
62 #[must_use]
63 pub const fn grow_smaller(old: usize, new: usize) -> AllocError {
64 AllocError::GrowSmallerNewLayout(old, new)
65 }
66
67 #[cold]
69 #[inline(never)]
70 #[cfg_attr(not(feature = "dev"), doc(hidden))]
71 #[must_use]
72 pub const fn shrink_larger(old: usize, new: usize) -> AllocError {
73 AllocError::ShrinkLargerNewLayout(old, new)
74 }
75}
76
77impl Display for AllocError {
78 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
79 use AllocError::{
80 AllocFailed,
81 ArithmeticError,
82 GrowSmallerNewLayout,
83 InvalidAlign,
84 InvalidLayout,
85 Other,
86 ShrinkLargerNewLayout,
87 ZeroSizedLayout
88 };
89
90 match self {
91 AllocFailed(l, cause) => {
92 write!(
93 f,
94 "allocation failed:\n\tlayout:\n\t\tsize: {}\n\t\talign: {}\n\tcause: {}",
95 l.size(),
96 l.align(),
97 cause
98 )
99 }
100 InvalidLayout(inv_layout) => {
101 write!(f, "{}", inv_layout)
102 }
103 InvalidAlign(inv_align) => {
104 write!(f, "{}", inv_align)
105 }
106 ZeroSizedLayout(_) => {
107 write!(f, "received a zero-sized layout")
108 }
109 GrowSmallerNewLayout(old, new) => {
110 write!(f, "attempted to grow from a size of {} to a smaller size of {}", old, new)
111 }
112 ShrinkLargerNewLayout(old, new) => {
113 write!(f, "attempted to shrink from a size of {} to a larger size of {}", old, new)
114 }
115 ArithmeticError(overflow) => {
116 write!(f, "{}", overflow)
117 }
118 Other(other) => write!(f, "{}", other)
119 }
120 }
121}
122
123#[cfg(feature = "std")]
124impl std::error::Error for AllocError {}
125
126#[derive(Debug, Copy, Clone, PartialEq, Eq)]
128#[repr(u8)]
129pub enum Cause {
130 Unknown,
135 OutOfMemory,
140 #[cfg(feature = "os_err_reporting")]
141 OSErr(i32)
145}
146
147impl Display for Cause {
148 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
149 match self {
150 Cause::Unknown => write!(f, "unknown"),
151 Cause::OutOfMemory => write!(f, "out of memory"),
152 #[cfg(feature = "os_err_reporting")]
153 Cause::OSErr(e) => write!(f, "os error:\n\t{}", e)
154 }
155 }
156}
157
158#[cfg(feature = "std")]
159impl std::error::Error for Cause {}
160
161#[derive(Debug, Clone, Copy, PartialEq, Eq)]
163pub struct InvLayout(pub usize, pub usize, pub LayoutErr);
164
165impl Display for InvLayout {
166 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
167 write!(
168 f,
169 "computed invalid layout:\n\tsize: {},\n\talign: {}\n\treason: {}",
170 self.0, self.1, self.2
171 )
172 }
173}
174
175#[cfg(feature = "std")]
176impl std::error::Error for InvLayout {}
177
178#[derive(Debug, Clone, Copy, PartialEq, Eq)]
180#[repr(u8)]
181pub enum LayoutErr {
182 Align(AlignErr),
184 ExceedsMax,
188 ArithErr(ArithErr)
190}
191
192impl Display for LayoutErr {
193 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
194 match self {
195 LayoutErr::Align(inv_align) => write!(f, "{}", inv_align),
196 LayoutErr::ExceedsMax => write!(f, "size would overflow when rounded up to alignment"),
197 LayoutErr::ArithErr(overflow) => write!(f, "layout err: {}", overflow)
198 }
199 }
200}
201
202#[cfg(feature = "std")]
203impl std::error::Error for LayoutErr {}
204
205#[derive(Debug, Clone, Copy, PartialEq, Eq)]
207#[repr(u8)]
208pub enum AlignErr {
209 ZeroAlign,
211 NonPowerOfTwoAlign(usize)
213}
214
215impl Display for AlignErr {
216 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
217 match self {
218 AlignErr::ZeroAlign => write!(f, "alignment is zero"),
219 AlignErr::NonPowerOfTwoAlign(align) => {
220 write!(f, "alignment {} isn't a power of two", align)
221 }
222 }
223 }
224}
225
226#[cfg(feature = "std")]
227impl std::error::Error for AlignErr {}
228
229#[derive(Debug, Copy, Clone, PartialEq, Eq)]
234pub enum ArithErr {
235 TooLargeRhs(usize),
237 Overflow(usize, ArithOp, usize)
239}
240
241impl Display for ArithErr {
242 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
243 match self {
244 ArithErr::TooLargeRhs(rhs) => {
245 write!(f, "right-hand side {} is too large for the operation", rhs)
246 }
247 ArithErr::Overflow(l, o, r) => {
248 write!(f, "arithmetic operation would overflow: {} {} {}", l, o, r)
249 }
250 }
251 }
252}
253
254#[cfg(feature = "std")]
255impl std::error::Error for ArithErr {}
256
257#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
259#[repr(u8)]
260pub enum ArithOp {
261 Add,
263 Sub,
265 Mul,
267 Div,
269 Rem,
271 Pow
273}
274
275impl Display for ArithOp {
276 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
277 match self {
278 ArithOp::Add => write!(f, "+"),
279 ArithOp::Sub => write!(f, "-"),
280 ArithOp::Mul => write!(f, "*"),
281 ArithOp::Div => write!(f, "/"),
282 ArithOp::Rem => write!(f, "%"),
283 ArithOp::Pow => write!(f, "**")
284 }
285 }
286}