arc_slice/
error.rs

1//! Error types used in fallible allocation and buffer resizing.
2
3use core::fmt;
4
5pub(crate) use private::AllocErrorImpl;
6
7/// The memory allocator returned an error.
8#[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/// Error which can occur when trying to reserve additional capacity for a mutable buffer.
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub enum TryReserveError {
20    /// The buffer reference is not unique.
21    ///
22    /// Occurs when the same buffer is referenced by multiple [`ArcSliceMut`]s.
23    ///
24    /// [`ArcSliceMut`]: crate::ArcSliceMut
25    NotUnique,
26    /// The buffer doesn't support reservation.
27    Unsupported,
28    /// The memory allocator returned an error.
29    AllocError,
30    /// The required capacity exceeds the buffer maximum (usually isize::MAX bytes).
31    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}