1#![cfg_attr(not(feature = "std"), no_std)]
21
22#[cfg_attr(unix, path = "unix.rs")]
23#[cfg_attr(windows, path = "windows.rs")]
24#[cfg_attr(target_os = "wasi", path = "wasi.rs")]
25#[cfg_attr(target_os = "hermit", path = "hermit.rs")]
26mod sys;
27
28use core::fmt;
29#[cfg(feature = "std")]
30use std::error::Error;
31#[cfg(feature = "std")]
32use std::io;
33
34#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Hash)]
43pub struct Errno(pub i32);
44
45impl fmt::Debug for Errno {
46 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
47 sys::with_description(*self, |desc| {
48 fmt.debug_struct("Errno")
49 .field("code", &self.0)
50 .field("description", &desc.ok())
51 .finish()
52 })
53 }
54}
55
56impl fmt::Display for Errno {
57 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
58 sys::with_description(*self, |desc| match desc {
59 Ok(desc) => fmt.write_str(desc),
60 Err(fm_err) => write!(
61 fmt,
62 "OS error {} ({} returned error {})",
63 self.0,
64 sys::STRERROR_NAME,
65 fm_err.0
66 ),
67 })
68 }
69}
70
71impl From<Errno> for i32 {
72 fn from(e: Errno) -> Self {
73 e.0
74 }
75}
76
77#[cfg(feature = "std")]
78impl Error for Errno {
79 #[allow(deprecated)]
81 fn description(&self) -> &str {
82 "system error"
83 }
84}
85
86#[cfg(feature = "std")]
87impl From<Errno> for io::Error {
88 fn from(errno: Errno) -> Self {
89 io::Error::from_raw_os_error(errno.0)
90 }
91}
92
93pub fn errno() -> Errno {
95 sys::errno()
96}
97
98pub fn set_errno(err: Errno) {
100 sys::set_errno(err)
101}
102
103#[test]
104fn it_works() {
105 let x = errno();
106 set_errno(x);
107}
108
109#[cfg(feature = "std")]
110#[test]
111fn it_works_with_to_string() {
112 let x = errno();
113 let _ = x.to_string();
114}
115
116#[cfg(feature = "std")]
117#[test]
118fn check_description() {
119 let expect = if cfg!(windows) {
120 "Incorrect function."
121 } else if cfg!(target_os = "illumos") {
122 "Not owner"
123 } else if cfg!(target_os = "wasi") || cfg!(target_os = "emscripten") {
124 "Argument list too long"
125 } else if cfg!(target_os = "haiku") {
126 "Operation not allowed"
127 } else if cfg!(target_os = "vxworks") {
128 "operation not permitted"
129 } else {
130 "Operation not permitted"
131 };
132
133 let errno_code = if cfg!(target_os = "haiku") {
134 -2147483633
135 } else if cfg!(target_os = "hurd") {
136 1073741825
137 } else {
138 1
139 };
140 set_errno(Errno(errno_code));
141
142 assert_eq!(errno().to_string(), expect);
143 assert_eq!(
144 format!("{:?}", errno()),
145 format!(
146 "Errno {{ code: {}, description: Some({:?}) }}",
147 errno_code, expect
148 )
149 );
150}
151
152#[cfg(feature = "std")]
153#[test]
154fn check_error_into_errno() {
155 const ERROR_CODE: i32 = 1;
156
157 let error = io::Error::from_raw_os_error(ERROR_CODE);
158 let new_error: io::Error = Errno(ERROR_CODE).into();
159 assert_eq!(error.kind(), new_error.kind());
160}