gc_api/
error.rs

1//! To allow standard GC errors to be detected and handled no matter the implementation, this module
2//! provides a simple error type partially modeled after `std::io::Error`.
3
4use std::error;
5use std::fmt::{self, Debug, Display, Formatter};
6
7#[derive(Debug, Copy, Clone, Eq, PartialEq)]
8pub enum ErrorKind {
9    /// This error indicates that there is no longer enough memory to fill an allocation request.
10    OutOfMemory,
11    /// Unlike the out of memory error, this error indicates that a given request could never be
12    /// filled under the current configuration and may indicate a programming issue. An example of
13    /// this would be an allocation exceeding the size of the heap.
14    ///
15    /// Some GCs may choose to return OutOfMemory instead in some cases due to performance reasons.
16    AllocationTooLarge,
17    /// Used to indicate an requested alignment is unsupported. For example, some GCs may round up
18    /// to a fixed alignment for all allocations and are unable to support custom allocations larger
19    /// than the programmed amount.
20    UnsupportedAlignment,
21    /// This error indicates that an invalid state has been reached by the GC. This may be the
22    /// result of unsafe code or be produced by a GC which requires strict usage requirements.
23    IllegalState,
24    /// This error occurs when attempting to access an object that has already been garbage
25    /// collected. It should not be assumed that this error will be returned as not many garbage
26    /// collectors attempt to detect when this occurs.
27    UseAfterFree,
28    /// Any error which is not covered by another error kind.
29    Other,
30}
31
32impl Display for ErrorKind {
33    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
34        match self {
35            ErrorKind::OutOfMemory => write!(f, "Not enough memory remaining to complete request"),
36            ErrorKind::AllocationTooLarge => {
37                write!(f, "Allocation exceeds the maximum allowed size for this GC")
38            }
39            ErrorKind::UnsupportedAlignment => {
40                write!(f, "The requested allocation alignment is not supported")
41            }
42            ErrorKind::IllegalState => write!(
43                f,
44                "Attempted to enter an invalid state to complete this request"
45            ),
46            ErrorKind::UseAfterFree => {
47                write!(f, "Attempted to access an object which has been freed")
48            }
49            ErrorKind::Other => write!(
50                f,
51                "An unknown error occurred while attempting to complete the request"
52            ),
53        }
54    }
55}
56
57pub struct Error {
58    kind: ErrorKind,
59    error: Box<dyn error::Error + Send + Sync>,
60}
61
62impl Error {
63    pub fn new<E>(kind: ErrorKind, error: E) -> Self
64    where
65        E: Into<Box<dyn error::Error + Send + Sync>>,
66    {
67        Error {
68            kind,
69            error: error.into(),
70        }
71    }
72
73    pub fn kind(&self) -> ErrorKind {
74        self.kind
75    }
76}
77
78impl From<ErrorKind> for Error {
79    fn from(kind: ErrorKind) -> Self {
80        Error::new(kind, format!("{}", kind))
81    }
82}
83
84impl Debug for Error {
85    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
86        write!(f, "{:?}: {:?}", &self.kind, &self.error)
87    }
88}
89
90impl Display for Error {
91    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
92        match self.kind {
93            ErrorKind::Other => Display::fmt(&self.error, f),
94            x => write!(f, "{:?}: {}", x, &self.error),
95        }
96    }
97}