jemalloc_ctl/
error.rs

1//! Error type
2#![cfg_attr(
3    feature = "cargo-clippy",
4    allow(clippy::cast_sign_loss, clippy::cast_possible_wrap)
5)]
6
7use crate::{fmt, num, result};
8use libc::c_int;
9
10pub trait NonZeroT {
11    type T;
12}
13impl NonZeroT for i32 {
14    type T = num::NonZeroU32;
15}
16impl NonZeroT for i64 {
17    type T = num::NonZeroU64;
18}
19
20pub type NonZeroCInt = <c_int as NonZeroT>::T;
21
22/// Errors of the `jemalloc_sys::mallct`-family of functions.
23///
24/// The `jemalloc-sys` crate: `mallctl`, `mallctlnametomib`, and `mallctlbymib``
25/// functions return `0` on success; otherwise they return an error value.
26#[repr(transparent)]
27#[derive(Copy, Clone, PartialEq)]
28pub struct Error(NonZeroCInt);
29
30/// Result type
31pub type Result<T> = result::Result<T, Error>;
32
33impl fmt::Debug for Error {
34    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
35        let code = self.0.get() as c_int;
36        match description(code) {
37            Some(m) => write!(f, "{m}"),
38            None => write!(f, "Unknown error code: \"{code}\"."),
39        }
40    }
41}
42
43impl fmt::Display for Error {
44    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45        <Self as fmt::Debug>::fmt(self, f)
46    }
47}
48
49#[cfg(feature = "use_std")]
50use std::error::Error as StdError;
51
52#[cfg(feature = "use_std")]
53impl StdError for Error {
54    fn description(&self) -> &str {
55        match description(self.0.get() as c_int) {
56            Some(m) => m,
57            None => "Unknown error",
58        }
59    }
60    fn cause(&self) -> Option<&dyn StdError> {
61        None
62    }
63    fn source(&self) -> Option<&(dyn StdError + 'static)> {
64        None
65    }
66}
67
68fn description(code: c_int) -> Option<&'static str> {
69    match code {
70        libc::EINVAL => Some(
71            "`newp` is not `NULL`, and `newlen` is too large or too \
72             small. Alternatively, `*oldlenp` is too large or too \
73             small; in this case as much data as possible are read \
74             despite the error.",
75        ),
76        libc::ENOENT => {
77            Some("`name` or `mib` specifies an unknown/invalid value.")
78        }
79        libc::EPERM => Some(
80            "Attempt to read or write `void` value, or attempt to \
81             write read-only value.",
82        ),
83        libc::EAGAIN => Some("A memory allocation failure occurred."),
84        libc::EFAULT => Some(
85            "An interface with side effects failed in some way not \
86             directly related to `mallctl*()` read/write processing.",
87        ),
88        _ => None,
89    }
90}
91
92pub(crate) fn cvt(ret: c_int) -> Result<()> {
93    match ret {
94        0 => Ok(()),
95        v => Err(Error(unsafe { NonZeroCInt::new_unchecked(v as _) })),
96    }
97}
98
99#[cfg(test)]
100mod tests {
101    use super::*;
102
103    #[test]
104    fn size_of_result_error() {
105        use crate::mem::size_of;
106        assert_eq!(size_of::<Result<()>>(), size_of::<Error>());
107        assert_eq!(size_of::<Error>(), size_of::<libc::c_int>());
108    }
109}