1#![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#[repr(transparent)]
44#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
45pub struct Errno(pub(crate) i32);
46
47impl Errno {
48 #[inline]
50 pub const fn new(num: i32) -> Self {
51 Self(num)
52 }
53
54 #[inline]
56 pub const fn into_raw(self) -> i32 {
57 self.0
58 }
59
60 #[inline]
62 pub const fn is_valid(&self) -> bool {
63 self.0 < 4096
64 }
65
66 #[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 pub fn name(&self) -> ::core::option::Option<&'static str> {
78 self.name_and_description().map(|x| x.0)
79 }
80
81 pub fn description(&self) -> ::core::option::Option<&'static str> {
83 self.name_and_description().map(|x| x.1)
84 }
85
86 #[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 pub fn last_os_error() -> Self {
96 Self(unsafe { *__error() })
97 }
98
99 #[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"))]
145pub 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}