1#![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#[repr(transparent)]
27#[derive(Copy, Clone, PartialEq)]
28pub struct Error(NonZeroCInt);
29
30pub 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}