bsd_errnos/
lib.rs

1//! Error numbers for BSDs.
2
3#![cfg(any(
4    target_os = "macos",
5    target_os = "ios",
6    target_os = "watchos",
7    target_os = "tvos",
8    target_os = "freebsd",
9    target_os = "dragonfly",
10    target_os = "openbsd",
11    target_os = "netbsd"
12))]
13#![cfg_attr(all(not(doc), not(feature = "std")), no_std)]
14
15#[cfg_attr(
16    any(
17        target_os = "macos",
18        target_os = "ios",
19        target_os = "watchos",
20        target_os = "tvos"
21    ),
22    path = "apple.rs"
23)]
24#[cfg_attr(target_os = "freebsd", path = "freebsd.rs")]
25#[cfg_attr(target_os = "dragonfly", path = "dragonfly.rs")]
26#[cfg_attr(target_os = "openbsd", path = "openbsd.rs")]
27#[cfg_attr(target_os = "netbsd", path = "netbsd.rs")]
28mod errno;
29
30pub use errno::*;
31
32#[link(name = "c")]
33extern "C" {
34    #[cfg_attr(target_os = "dragonfly", link_name = "__errno_location")]
35    #[cfg_attr(
36        any(target_os = "netbsd", target_os = "openbsd"),
37        link_name = "__errno"
38    )]
39    fn __error() -> *mut i32;
40}
41
42/// Error number representation.
43#[repr(transparent)]
44#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
45pub struct Errno(pub(crate) i32);
46
47impl Errno {
48    /// Returns a new `Errno` from the given integer.
49    #[inline]
50    pub const fn new(num: i32) -> Self {
51        Self(num)
52    }
53
54    /// Converts `Errno` into the under underlining integer.
55    #[inline]
56    pub const fn into_raw(self) -> i32 {
57        self.0
58    }
59
60    /// Returns `true` if the error code is in valid range (lower than 4096)
61    #[inline]
62    pub const fn is_valid(&self) -> bool {
63        self.0 < 4096
64    }
65
66    /// Returns a new `Errno` from a syscall's result.
67    #[inline(always)]
68    pub fn from_ret(value: usize) -> ::core::result::Result<usize, Errno> {
69        if value > -4096isize as usize {
70            ::core::result::Result::Err(Self(-(value as i32)))
71        } else {
72            ::core::result::Result::Ok(value)
73        }
74    }
75
76    /// Returns the name of the error if it's known. Generally the name of the constant.
77    pub fn name(&self) -> ::core::option::Option<&'static str> {
78        self.name_and_description().map(|x| x.0)
79    }
80
81    /// Returns a description of the error if it's known.
82    pub fn description(&self) -> ::core::option::Option<&'static str> {
83        self.name_and_description().map(|x| x.1)
84    }
85
86    /// Returns a new `Errno` if the given error is generated from a system error.
87    /// None otherwise.
88    #[cfg(any(doc, feature = "std"))]
89    #[inline]
90    pub fn from_io_error(err: ::std::io::Error) -> ::core::option::Option<Self> {
91        err.raw_os_error().map(Self)
92    }
93
94    /// Returns a new `Errno` from last OS error.
95    pub fn last_os_error() -> Self {
96        Self(unsafe { *__error() })
97    }
98
99    /// Returns an iterator `ErrnoIter` over all the known error numbers.
100    #[cfg(any(doc, feature = "iter"))]
101    #[inline]
102    pub fn iter() -> ErrnoIter {
103        ErrnoIter(Self::ALL.iter())
104    }
105}
106
107impl ::core::fmt::Display for Errno {
108    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
109        match self.name_and_description() {
110            Some((name, desc)) => {
111                write!(f, "{} {} ({})", -self.0, name, desc)
112            }
113            None => {
114                if self.is_valid() {
115                    write!(f, "{}", -self.0)
116                } else {
117                    write!(f, "Unknown errno {:#x}", self.0)
118                }
119            }
120        }
121    }
122}
123
124impl ::core::fmt::Debug for Errno {
125    fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result {
126        match self.name() {
127            ::core::option::Option::Some(name) => f.write_str(name),
128            ::core::option::Option::None => write!(f, "Errno({})", self.0),
129        }
130    }
131}
132
133#[cfg(any(doc, feature = "std"))]
134impl ::core::convert::From<Errno> for ::std::io::Error {
135    #[inline]
136    fn from(value: Errno) -> Self {
137        ::std::io::Error::from_raw_os_error(value.into_raw())
138    }
139}
140
141#[cfg(any(doc, feature = "std"))]
142impl ::std::error::Error for Errno {}
143
144#[cfg(any(doc, feature = "iter"))]
145/// Iterator over all possible error numbers.
146pub struct ErrnoIter(::core::slice::Iter<'static, i32>);
147
148#[cfg(any(doc, feature = "iter"))]
149impl ::core::iter::Iterator for ErrnoIter {
150    type Item = Errno;
151
152    #[inline]
153    fn next(&mut self) -> ::core::option::Option<Self::Item> {
154        self.0.next().copied().map(Errno)
155    }
156
157    #[inline]
158    fn size_hint(&self) -> (usize, ::core::option::Option<usize>) {
159        self.0.size_hint()
160    }
161
162    #[inline]
163    fn count(self) -> usize
164    where
165        Self: Sized,
166    {
167        self.0.count()
168    }
169
170    #[inline]
171    fn last(self) -> ::core::option::Option<Self::Item>
172    where
173        Self: Sized,
174    {
175        self.0.last().copied().map(Errno)
176    }
177
178    fn nth(&mut self, n: usize) -> ::core::option::Option<Self::Item> {
179        self.0.nth(n).copied().map(Errno)
180    }
181}
182
183#[cfg(any(doc, feature = "iter"))]
184impl ::core::iter::ExactSizeIterator for ErrnoIter {
185    #[inline]
186    fn len(&self) -> usize {
187        self.0.len()
188    }
189}
190
191#[cfg(any(doc, feature = "iter"))]
192impl ::core::iter::DoubleEndedIterator for ErrnoIter {
193    #[inline]
194    fn next_back(&mut self) -> ::core::option::Option<Self::Item> {
195        self.0.next_back().copied().map(Errno)
196    }
197
198    #[inline]
199    fn nth_back(&mut self, n: usize) -> ::core::option::Option<Self::Item> {
200        self.0.nth_back(n).copied().map(Errno)
201    }
202}