tikv_jemalloc_ctl/
error.rs

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