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