1use core::fmt;
4
5pub(crate) use private::AllocErrorImpl;
6
7#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct AllocError;
10
11impl fmt::Display for AllocError {
12 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
13 f.write_str("allocation error")
14 }
15}
16
17#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum TryReserveError {
20 NotUnique,
26 Unsupported,
28 AllocError,
30 CapacityOverflow,
32}
33
34impl From<AllocError> for TryReserveError {
35 fn from(_: AllocError) -> Self {
36 Self::AllocError
37 }
38}
39
40impl fmt::Display for TryReserveError {
41 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42 match self {
43 Self::NotUnique => f.write_str("not unique"),
44 Self::Unsupported => f.write_str("unsupported"),
45 Self::AllocError => f.write_str("allocation error"),
46 Self::CapacityOverflow => f.write_str("capacity overflow"),
47 }
48 }
49}
50
51#[cfg(feature = "std")]
52const _: () = {
53 extern crate std;
54 impl std::error::Error for AllocError {}
55 impl std::error::Error for TryReserveError {}
56};
57
58mod private {
59 use alloc::alloc::{alloc, alloc_zeroed, handle_alloc_error};
60 use core::{alloc::Layout, convert::Infallible, mem, ptr::NonNull};
61
62 use crate::{error::AllocError, utils::assert_checked};
63
64 pub trait AllocErrorImpl: Sized {
65 const FALLIBLE: bool;
66 fn forget<T>(self, x: T) -> Self {
67 mem::forget(x);
68 self
69 }
70 fn capacity_overflow() -> Self;
71 fn alloc<T, const ZEROED: bool>(layout: Layout) -> Result<NonNull<T>, Self>;
72 }
73
74 impl AllocErrorImpl for AllocError {
75 const FALLIBLE: bool = true;
76 fn capacity_overflow() -> Self {
77 Self
78 }
79 fn alloc<T, const ZEROED: bool>(layout: Layout) -> Result<NonNull<T>, Self> {
80 assert_checked(layout.size() > 0);
81 let ptr = unsafe { (if ZEROED { alloc_zeroed } else { alloc })(layout) };
82 Ok(NonNull::new(ptr).ok_or(AllocError)?.cast())
83 }
84 }
85
86 impl AllocErrorImpl for Infallible {
87 const FALLIBLE: bool = false;
88 #[cold]
89 #[inline(never)]
90 fn capacity_overflow() -> Self {
91 panic!("capacity overflow")
92 }
93 fn alloc<T, const ZEROED: bool>(layout: Layout) -> Result<NonNull<T>, Self> {
94 AllocError::alloc::<T, ZEROED>(layout).map_err(|_| handle_alloc_error(layout))
95 }
96 }
97}