/rust/registry/src/index.crates.io-1949cf8c6b5b557f/errno-0.3.14/src/lib.rs
Line | Count | Source |
1 | | //! Cross-platform interface to the `errno` variable. |
2 | | //! |
3 | | //! # Examples |
4 | | //! ``` |
5 | | //! use errno::{Errno, errno, set_errno}; |
6 | | //! |
7 | | //! // Get the current value of errno |
8 | | //! let e = errno(); |
9 | | //! |
10 | | //! // Set the current value of errno |
11 | | //! set_errno(e); |
12 | | //! |
13 | | //! // Extract the error code as an i32 |
14 | | //! let code = e.0; |
15 | | //! |
16 | | //! // Display a human-friendly error message |
17 | | //! println!("Error {}: {}", code, e); |
18 | | //! ``` |
19 | | |
20 | | #![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")] |
26 | | mod sys; |
27 | | |
28 | | use core::fmt; |
29 | | #[cfg(feature = "std")] |
30 | | use std::error::Error; |
31 | | #[cfg(feature = "std")] |
32 | | use std::io; |
33 | | |
34 | | /// Wraps a platform-specific error code. |
35 | | /// |
36 | | /// The `Display` instance maps the code to a human-readable string. It |
37 | | /// calls [`strerror_r`][1] under POSIX, and [`FormatMessageW`][2] on |
38 | | /// Windows. |
39 | | /// |
40 | | /// [1]: http://pubs.opengroup.org/onlinepubs/009695399/functions/strerror.html |
41 | | /// [2]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms679351%28v=vs.85%29.aspx |
42 | | #[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Hash)] |
43 | | pub struct Errno(pub i32); |
44 | | |
45 | | impl fmt::Debug for Errno { |
46 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
47 | 0 | sys::with_description(*self, |desc| { |
48 | 0 | fmt.debug_struct("Errno") |
49 | 0 | .field("code", &self.0) |
50 | 0 | .field("description", &desc.ok()) |
51 | 0 | .finish() |
52 | 0 | }) |
53 | 0 | } |
54 | | } |
55 | | |
56 | | impl fmt::Display for Errno { |
57 | 0 | fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { |
58 | 0 | sys::with_description(*self, |desc| match desc { |
59 | 0 | Ok(desc) => fmt.write_str(desc), |
60 | 0 | Err(fm_err) => write!( |
61 | 0 | fmt, |
62 | 0 | "OS error {} ({} returned error {})", |
63 | | self.0, |
64 | | sys::STRERROR_NAME, |
65 | | fm_err.0 |
66 | | ), |
67 | 0 | }) |
68 | 0 | } |
69 | | } |
70 | | |
71 | | impl From<Errno> for i32 { |
72 | 0 | fn from(e: Errno) -> Self { |
73 | 0 | e.0 |
74 | 0 | } |
75 | | } |
76 | | |
77 | | #[cfg(feature = "std")] |
78 | | impl Error for Errno { |
79 | | // TODO: Remove when MSRV >= 1.27 |
80 | | #[allow(deprecated)] |
81 | 0 | fn description(&self) -> &str { |
82 | 0 | "system error" |
83 | 0 | } |
84 | | } |
85 | | |
86 | | #[cfg(feature = "std")] |
87 | | impl From<Errno> for io::Error { |
88 | 0 | fn from(errno: Errno) -> Self { |
89 | 0 | io::Error::from_raw_os_error(errno.0) |
90 | 0 | } |
91 | | } |
92 | | |
93 | | /// Returns the platform-specific value of `errno`. |
94 | 0 | pub fn errno() -> Errno { |
95 | 0 | sys::errno() |
96 | 0 | } |
97 | | |
98 | | /// Sets the platform-specific value of `errno`. |
99 | 0 | pub fn set_errno(err: Errno) { |
100 | 0 | sys::set_errno(err) |
101 | 0 | } |
102 | | |
103 | | #[test] |
104 | | fn it_works() { |
105 | | let x = errno(); |
106 | | set_errno(x); |
107 | | } |
108 | | |
109 | | #[cfg(feature = "std")] |
110 | | #[test] |
111 | | fn it_works_with_to_string() { |
112 | | let x = errno(); |
113 | | let _ = x.to_string(); |
114 | | } |
115 | | |
116 | | #[cfg(feature = "std")] |
117 | | #[test] |
118 | | fn 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] |
154 | | fn 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 | | } |