oom_safe/
lib.rs

1//! Out-of-memory safe
2
3#![feature(allocator_api)]
4#![feature(alloc_error_hook)]
5#![feature(try_reserve_kind)]
6
7use std::alloc::Layout;
8use std::collections::TryReserveError;
9use std::error::Error;
10use std::fmt;
11
12mod sealed {
13    pub trait Sealed {}
14}
15
16mod oom;
17mod vec_ext;
18
19pub use crate::oom::catch_oom;
20pub use crate::vec_ext::{VecAllocExt, VecExt};
21
22/// The error type for allocation failure.
23#[derive(Copy, Clone)]
24#[repr(transparent)]
25pub struct AllocError(Layout);
26
27impl AllocError {
28    /// Creates a new `AllocError`.
29    #[must_use]
30    #[inline]
31    pub const fn new(layout: Layout) -> Self {
32        AllocError(layout)
33    }
34
35    /// Returns the memory layout of the `AllocError`.
36    #[must_use]
37    #[inline]
38    pub const fn layout(self) -> Layout {
39        self.0
40    }
41}
42
43impl fmt::Debug for AllocError {
44    #[inline]
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        f.debug_struct("AllocError")
47            .field("size", &self.0.size())
48            .field("align", &self.0.align())
49            .finish()
50    }
51}
52
53impl fmt::Display for AllocError {
54    #[inline]
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        write!(
57            f,
58            "failed to allocate memory by required layout {{size: {}, align: {}}}",
59            self.0.size(),
60            self.0.align()
61        )
62    }
63}
64
65impl Error for AllocError {}
66
67impl From<TryReserveError> for AllocError {
68    #[inline]
69    fn from(e: TryReserveError) -> Self {
70        use std::collections::TryReserveErrorKind;
71        match e.kind() {
72            TryReserveErrorKind::AllocError { layout, .. } => AllocError::new(layout),
73            TryReserveErrorKind::CapacityOverflow => {
74                unreachable!("unexpected capacity overflow")
75            }
76        }
77    }
78}