1*8a420dd1SPaolo Bonzini // SPDX-License-Identifier: GPL-2.0-or-later
2*8a420dd1SPaolo Bonzini
3*8a420dd1SPaolo Bonzini //! Utility functions to convert `errno` to and from
4*8a420dd1SPaolo Bonzini //! [`io::Error`]/[`io::Result`]
5*8a420dd1SPaolo Bonzini //!
6*8a420dd1SPaolo Bonzini //! QEMU C functions often have a "positive success/negative `errno`" calling
7*8a420dd1SPaolo Bonzini //! convention. This module provides functions to portably convert an integer
8*8a420dd1SPaolo Bonzini //! into an [`io::Result`] and back.
9*8a420dd1SPaolo Bonzini
10*8a420dd1SPaolo Bonzini use std::{convert::TryFrom, io, io::ErrorKind};
11*8a420dd1SPaolo Bonzini
12*8a420dd1SPaolo Bonzini /// An `errno` value that can be converted into an [`io::Error`]
13*8a420dd1SPaolo Bonzini pub struct Errno(pub u16);
14*8a420dd1SPaolo Bonzini
15*8a420dd1SPaolo Bonzini // On Unix, from_raw_os_error takes an errno value and OS errors
16*8a420dd1SPaolo Bonzini // are printed using strerror. On Windows however it takes a
17*8a420dd1SPaolo Bonzini // GetLastError() value; therefore we need to convert errno values
18*8a420dd1SPaolo Bonzini // into io::Error by hand. This is the same mapping that the
19*8a420dd1SPaolo Bonzini // standard library uses to retrieve the kind of OS errors
20*8a420dd1SPaolo Bonzini // (`std::sys::pal::unix::decode_error_kind`).
21*8a420dd1SPaolo Bonzini impl From<Errno> for ErrorKind {
from(value: Errno) -> ErrorKind22*8a420dd1SPaolo Bonzini fn from(value: Errno) -> ErrorKind {
23*8a420dd1SPaolo Bonzini use ErrorKind::*;
24*8a420dd1SPaolo Bonzini let Errno(errno) = value;
25*8a420dd1SPaolo Bonzini match i32::from(errno) {
26*8a420dd1SPaolo Bonzini libc::EPERM | libc::EACCES => PermissionDenied,
27*8a420dd1SPaolo Bonzini libc::ENOENT => NotFound,
28*8a420dd1SPaolo Bonzini libc::EINTR => Interrupted,
29*8a420dd1SPaolo Bonzini x if x == libc::EAGAIN || x == libc::EWOULDBLOCK => WouldBlock,
30*8a420dd1SPaolo Bonzini libc::ENOMEM => OutOfMemory,
31*8a420dd1SPaolo Bonzini libc::EEXIST => AlreadyExists,
32*8a420dd1SPaolo Bonzini libc::EINVAL => InvalidInput,
33*8a420dd1SPaolo Bonzini libc::EPIPE => BrokenPipe,
34*8a420dd1SPaolo Bonzini libc::EADDRINUSE => AddrInUse,
35*8a420dd1SPaolo Bonzini libc::EADDRNOTAVAIL => AddrNotAvailable,
36*8a420dd1SPaolo Bonzini libc::ECONNABORTED => ConnectionAborted,
37*8a420dd1SPaolo Bonzini libc::ECONNREFUSED => ConnectionRefused,
38*8a420dd1SPaolo Bonzini libc::ECONNRESET => ConnectionReset,
39*8a420dd1SPaolo Bonzini libc::ENOTCONN => NotConnected,
40*8a420dd1SPaolo Bonzini libc::ENOTSUP => Unsupported,
41*8a420dd1SPaolo Bonzini libc::ETIMEDOUT => TimedOut,
42*8a420dd1SPaolo Bonzini _ => Other,
43*8a420dd1SPaolo Bonzini }
44*8a420dd1SPaolo Bonzini }
45*8a420dd1SPaolo Bonzini }
46*8a420dd1SPaolo Bonzini
47*8a420dd1SPaolo Bonzini // This is used on Windows for all io::Errors, but also on Unix if the
48*8a420dd1SPaolo Bonzini // io::Error does not have a raw OS error. This is the reversed
49*8a420dd1SPaolo Bonzini // mapping of the above; EIO is returned for unknown ErrorKinds.
50*8a420dd1SPaolo Bonzini impl From<io::ErrorKind> for Errno {
from(value: io::ErrorKind) -> Errno51*8a420dd1SPaolo Bonzini fn from(value: io::ErrorKind) -> Errno {
52*8a420dd1SPaolo Bonzini use ErrorKind::*;
53*8a420dd1SPaolo Bonzini let errno = match value {
54*8a420dd1SPaolo Bonzini // can be both EPERM or EACCES :( pick one
55*8a420dd1SPaolo Bonzini PermissionDenied => libc::EPERM,
56*8a420dd1SPaolo Bonzini NotFound => libc::ENOENT,
57*8a420dd1SPaolo Bonzini Interrupted => libc::EINTR,
58*8a420dd1SPaolo Bonzini WouldBlock => libc::EAGAIN,
59*8a420dd1SPaolo Bonzini OutOfMemory => libc::ENOMEM,
60*8a420dd1SPaolo Bonzini AlreadyExists => libc::EEXIST,
61*8a420dd1SPaolo Bonzini InvalidInput => libc::EINVAL,
62*8a420dd1SPaolo Bonzini BrokenPipe => libc::EPIPE,
63*8a420dd1SPaolo Bonzini AddrInUse => libc::EADDRINUSE,
64*8a420dd1SPaolo Bonzini AddrNotAvailable => libc::EADDRNOTAVAIL,
65*8a420dd1SPaolo Bonzini ConnectionAborted => libc::ECONNABORTED,
66*8a420dd1SPaolo Bonzini ConnectionRefused => libc::ECONNREFUSED,
67*8a420dd1SPaolo Bonzini ConnectionReset => libc::ECONNRESET,
68*8a420dd1SPaolo Bonzini NotConnected => libc::ENOTCONN,
69*8a420dd1SPaolo Bonzini Unsupported => libc::ENOTSUP,
70*8a420dd1SPaolo Bonzini TimedOut => libc::ETIMEDOUT,
71*8a420dd1SPaolo Bonzini _ => libc::EIO,
72*8a420dd1SPaolo Bonzini };
73*8a420dd1SPaolo Bonzini Errno(errno as u16)
74*8a420dd1SPaolo Bonzini }
75*8a420dd1SPaolo Bonzini }
76*8a420dd1SPaolo Bonzini
77*8a420dd1SPaolo Bonzini impl From<Errno> for io::Error {
78*8a420dd1SPaolo Bonzini #[cfg(unix)]
from(value: Errno) -> io::Error79*8a420dd1SPaolo Bonzini fn from(value: Errno) -> io::Error {
80*8a420dd1SPaolo Bonzini let Errno(errno) = value;
81*8a420dd1SPaolo Bonzini io::Error::from_raw_os_error(errno.into())
82*8a420dd1SPaolo Bonzini }
83*8a420dd1SPaolo Bonzini
84*8a420dd1SPaolo Bonzini #[cfg(windows)]
from(value: Errno) -> io::Error85*8a420dd1SPaolo Bonzini fn from(value: Errno) -> io::Error {
86*8a420dd1SPaolo Bonzini let error_kind: ErrorKind = value.into();
87*8a420dd1SPaolo Bonzini error_kind.into()
88*8a420dd1SPaolo Bonzini }
89*8a420dd1SPaolo Bonzini }
90*8a420dd1SPaolo Bonzini
91*8a420dd1SPaolo Bonzini impl From<io::Error> for Errno {
from(value: io::Error) -> Errno92*8a420dd1SPaolo Bonzini fn from(value: io::Error) -> Errno {
93*8a420dd1SPaolo Bonzini if cfg!(unix) {
94*8a420dd1SPaolo Bonzini if let Some(errno) = value.raw_os_error() {
95*8a420dd1SPaolo Bonzini return Errno(u16::try_from(errno).unwrap());
96*8a420dd1SPaolo Bonzini }
97*8a420dd1SPaolo Bonzini }
98*8a420dd1SPaolo Bonzini value.kind().into()
99*8a420dd1SPaolo Bonzini }
100*8a420dd1SPaolo Bonzini }
101*8a420dd1SPaolo Bonzini
102*8a420dd1SPaolo Bonzini /// Internal traits; used to enable [`into_io_result`] and [`into_neg_errno`]
103*8a420dd1SPaolo Bonzini /// for the "right" set of types.
104*8a420dd1SPaolo Bonzini mod traits {
105*8a420dd1SPaolo Bonzini use super::Errno;
106*8a420dd1SPaolo Bonzini
107*8a420dd1SPaolo Bonzini /// A signed type that can be converted into an
108*8a420dd1SPaolo Bonzini /// [`io::Result`](std::io::Result)
109*8a420dd1SPaolo Bonzini pub trait GetErrno {
110*8a420dd1SPaolo Bonzini /// Unsigned variant of `Self`, used as the type for the `Ok` case.
111*8a420dd1SPaolo Bonzini type Out;
112*8a420dd1SPaolo Bonzini
113*8a420dd1SPaolo Bonzini /// Return `Ok(self)` if positive, `Err(Errno(-self))` if negative
into_errno_result(self) -> Result<Self::Out, Errno>114*8a420dd1SPaolo Bonzini fn into_errno_result(self) -> Result<Self::Out, Errno>;
115*8a420dd1SPaolo Bonzini }
116*8a420dd1SPaolo Bonzini
117*8a420dd1SPaolo Bonzini /// A type that can be taken out of an [`io::Result`](std::io::Result) and
118*8a420dd1SPaolo Bonzini /// converted into "positive success/negative `errno`" convention.
119*8a420dd1SPaolo Bonzini pub trait MergeErrno {
120*8a420dd1SPaolo Bonzini /// Signed variant of `Self`, used as the return type of
121*8a420dd1SPaolo Bonzini /// [`into_neg_errno`](super::into_neg_errno).
122*8a420dd1SPaolo Bonzini type Out: From<u16> + std::ops::Neg<Output = Self::Out>;
123*8a420dd1SPaolo Bonzini
124*8a420dd1SPaolo Bonzini /// Return `self`, asserting that it is in range
map_ok(self) -> Self::Out125*8a420dd1SPaolo Bonzini fn map_ok(self) -> Self::Out;
126*8a420dd1SPaolo Bonzini }
127*8a420dd1SPaolo Bonzini
128*8a420dd1SPaolo Bonzini macro_rules! get_errno {
129*8a420dd1SPaolo Bonzini ($t:ty, $out:ty) => {
130*8a420dd1SPaolo Bonzini impl GetErrno for $t {
131*8a420dd1SPaolo Bonzini type Out = $out;
132*8a420dd1SPaolo Bonzini fn into_errno_result(self) -> Result<Self::Out, Errno> {
133*8a420dd1SPaolo Bonzini match self {
134*8a420dd1SPaolo Bonzini 0.. => Ok(self as $out),
135*8a420dd1SPaolo Bonzini -65535..=-1 => Err(Errno(-self as u16)),
136*8a420dd1SPaolo Bonzini _ => panic!("{self} is not a negative errno"),
137*8a420dd1SPaolo Bonzini }
138*8a420dd1SPaolo Bonzini }
139*8a420dd1SPaolo Bonzini }
140*8a420dd1SPaolo Bonzini };
141*8a420dd1SPaolo Bonzini }
142*8a420dd1SPaolo Bonzini
143*8a420dd1SPaolo Bonzini get_errno!(i32, u32);
144*8a420dd1SPaolo Bonzini get_errno!(i64, u64);
145*8a420dd1SPaolo Bonzini get_errno!(isize, usize);
146*8a420dd1SPaolo Bonzini
147*8a420dd1SPaolo Bonzini macro_rules! merge_errno {
148*8a420dd1SPaolo Bonzini ($t:ty, $out:ty) => {
149*8a420dd1SPaolo Bonzini impl MergeErrno for $t {
150*8a420dd1SPaolo Bonzini type Out = $out;
151*8a420dd1SPaolo Bonzini fn map_ok(self) -> Self::Out {
152*8a420dd1SPaolo Bonzini self.try_into().unwrap()
153*8a420dd1SPaolo Bonzini }
154*8a420dd1SPaolo Bonzini }
155*8a420dd1SPaolo Bonzini };
156*8a420dd1SPaolo Bonzini }
157*8a420dd1SPaolo Bonzini
158*8a420dd1SPaolo Bonzini merge_errno!(u8, i32);
159*8a420dd1SPaolo Bonzini merge_errno!(u16, i32);
160*8a420dd1SPaolo Bonzini merge_errno!(u32, i32);
161*8a420dd1SPaolo Bonzini merge_errno!(u64, i64);
162*8a420dd1SPaolo Bonzini
163*8a420dd1SPaolo Bonzini impl MergeErrno for () {
164*8a420dd1SPaolo Bonzini type Out = i32;
map_ok(self) -> i32165*8a420dd1SPaolo Bonzini fn map_ok(self) -> i32 {
166*8a420dd1SPaolo Bonzini 0
167*8a420dd1SPaolo Bonzini }
168*8a420dd1SPaolo Bonzini }
169*8a420dd1SPaolo Bonzini }
170*8a420dd1SPaolo Bonzini
171*8a420dd1SPaolo Bonzini use traits::{GetErrno, MergeErrno};
172*8a420dd1SPaolo Bonzini
173*8a420dd1SPaolo Bonzini /// Convert an integer value into a [`io::Result`].
174*8a420dd1SPaolo Bonzini ///
175*8a420dd1SPaolo Bonzini /// Positive values are turned into an `Ok` result; negative values
176*8a420dd1SPaolo Bonzini /// are interpreted as negated `errno` and turned into an `Err`.
177*8a420dd1SPaolo Bonzini ///
178*8a420dd1SPaolo Bonzini /// ```
179*8a420dd1SPaolo Bonzini /// # use qemu_api::errno::into_io_result;
180*8a420dd1SPaolo Bonzini /// # use std::io::ErrorKind;
181*8a420dd1SPaolo Bonzini /// let ok = into_io_result(1i32).unwrap();
182*8a420dd1SPaolo Bonzini /// assert_eq!(ok, 1u32);
183*8a420dd1SPaolo Bonzini ///
184*8a420dd1SPaolo Bonzini /// let err = into_io_result(-1i32).unwrap_err(); // -EPERM
185*8a420dd1SPaolo Bonzini /// assert_eq!(err.kind(), ErrorKind::PermissionDenied);
186*8a420dd1SPaolo Bonzini /// ```
187*8a420dd1SPaolo Bonzini ///
188*8a420dd1SPaolo Bonzini /// # Panics
189*8a420dd1SPaolo Bonzini ///
190*8a420dd1SPaolo Bonzini /// Since the result is an unsigned integer, negative values must
191*8a420dd1SPaolo Bonzini /// be close to 0; values that are too far away are considered
192*8a420dd1SPaolo Bonzini /// likely overflows and will panic:
193*8a420dd1SPaolo Bonzini ///
194*8a420dd1SPaolo Bonzini /// ```should_panic
195*8a420dd1SPaolo Bonzini /// # use qemu_api::errno::into_io_result;
196*8a420dd1SPaolo Bonzini /// # #[allow(dead_code)]
197*8a420dd1SPaolo Bonzini /// let err = into_io_result(-0x1234_5678i32); // panic
198*8a420dd1SPaolo Bonzini /// ```
into_io_result<T: GetErrno>(value: T) -> io::Result<T::Out>199*8a420dd1SPaolo Bonzini pub fn into_io_result<T: GetErrno>(value: T) -> io::Result<T::Out> {
200*8a420dd1SPaolo Bonzini value.into_errno_result().map_err(Into::into)
201*8a420dd1SPaolo Bonzini }
202*8a420dd1SPaolo Bonzini
203*8a420dd1SPaolo Bonzini /// Convert a [`Result`] into an integer value, using negative `errno`
204*8a420dd1SPaolo Bonzini /// values to report errors.
205*8a420dd1SPaolo Bonzini ///
206*8a420dd1SPaolo Bonzini /// ```
207*8a420dd1SPaolo Bonzini /// # use qemu_api::errno::into_neg_errno;
208*8a420dd1SPaolo Bonzini /// # use std::io::{self, ErrorKind};
209*8a420dd1SPaolo Bonzini /// let ok: io::Result<()> = Ok(());
210*8a420dd1SPaolo Bonzini /// assert_eq!(into_neg_errno(ok), 0);
211*8a420dd1SPaolo Bonzini ///
212*8a420dd1SPaolo Bonzini /// let err: io::Result<()> = Err(ErrorKind::InvalidInput.into());
213*8a420dd1SPaolo Bonzini /// assert_eq!(into_neg_errno(err), -22); // -EINVAL
214*8a420dd1SPaolo Bonzini /// ```
215*8a420dd1SPaolo Bonzini ///
216*8a420dd1SPaolo Bonzini /// Since this module also provides the ability to convert [`io::Error`]
217*8a420dd1SPaolo Bonzini /// to an `errno` value, [`io::Result`] is the most commonly used type
218*8a420dd1SPaolo Bonzini /// for the argument of this function:
219*8a420dd1SPaolo Bonzini ///
220*8a420dd1SPaolo Bonzini /// # Panics
221*8a420dd1SPaolo Bonzini ///
222*8a420dd1SPaolo Bonzini /// Since the result is a signed integer, integer `Ok` values must remain
223*8a420dd1SPaolo Bonzini /// positive:
224*8a420dd1SPaolo Bonzini ///
225*8a420dd1SPaolo Bonzini /// ```should_panic
226*8a420dd1SPaolo Bonzini /// # use qemu_api::errno::into_neg_errno;
227*8a420dd1SPaolo Bonzini /// # use std::io;
228*8a420dd1SPaolo Bonzini /// let err: io::Result<u32> = Ok(0x8899_AABB);
229*8a420dd1SPaolo Bonzini /// into_neg_errno(err) // panic
230*8a420dd1SPaolo Bonzini /// # ;
231*8a420dd1SPaolo Bonzini /// ```
into_neg_errno<T: MergeErrno, E: Into<Errno>>(value: Result<T, E>) -> T::Out232*8a420dd1SPaolo Bonzini pub fn into_neg_errno<T: MergeErrno, E: Into<Errno>>(value: Result<T, E>) -> T::Out {
233*8a420dd1SPaolo Bonzini match value {
234*8a420dd1SPaolo Bonzini Ok(x) => x.map_ok(),
235*8a420dd1SPaolo Bonzini Err(err) => -T::Out::from(err.into().0),
236*8a420dd1SPaolo Bonzini }
237*8a420dd1SPaolo Bonzini }
238*8a420dd1SPaolo Bonzini
239*8a420dd1SPaolo Bonzini #[cfg(test)]
240*8a420dd1SPaolo Bonzini mod tests {
241*8a420dd1SPaolo Bonzini use std::io::ErrorKind;
242*8a420dd1SPaolo Bonzini
243*8a420dd1SPaolo Bonzini use super::*;
244*8a420dd1SPaolo Bonzini use crate::assert_match;
245*8a420dd1SPaolo Bonzini
246*8a420dd1SPaolo Bonzini #[test]
test_from_u8()247*8a420dd1SPaolo Bonzini pub fn test_from_u8() {
248*8a420dd1SPaolo Bonzini let ok: io::Result<_> = Ok(42u8);
249*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(ok), 42);
250*8a420dd1SPaolo Bonzini
251*8a420dd1SPaolo Bonzini let err: io::Result<u8> = Err(io::ErrorKind::PermissionDenied.into());
252*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(err), -1);
253*8a420dd1SPaolo Bonzini
254*8a420dd1SPaolo Bonzini if cfg!(unix) {
255*8a420dd1SPaolo Bonzini let os_err: io::Result<u8> = Err(io::Error::from_raw_os_error(10));
256*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(os_err), -10);
257*8a420dd1SPaolo Bonzini }
258*8a420dd1SPaolo Bonzini }
259*8a420dd1SPaolo Bonzini
260*8a420dd1SPaolo Bonzini #[test]
test_from_u16()261*8a420dd1SPaolo Bonzini pub fn test_from_u16() {
262*8a420dd1SPaolo Bonzini let ok: io::Result<_> = Ok(1234u16);
263*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(ok), 1234);
264*8a420dd1SPaolo Bonzini
265*8a420dd1SPaolo Bonzini let err: io::Result<u16> = Err(io::ErrorKind::PermissionDenied.into());
266*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(err), -1);
267*8a420dd1SPaolo Bonzini
268*8a420dd1SPaolo Bonzini if cfg!(unix) {
269*8a420dd1SPaolo Bonzini let os_err: io::Result<u16> = Err(io::Error::from_raw_os_error(10));
270*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(os_err), -10);
271*8a420dd1SPaolo Bonzini }
272*8a420dd1SPaolo Bonzini }
273*8a420dd1SPaolo Bonzini
274*8a420dd1SPaolo Bonzini #[test]
test_i32()275*8a420dd1SPaolo Bonzini pub fn test_i32() {
276*8a420dd1SPaolo Bonzini assert_match!(into_io_result(1234i32), Ok(1234));
277*8a420dd1SPaolo Bonzini
278*8a420dd1SPaolo Bonzini let err = into_io_result(-1i32).unwrap_err();
279*8a420dd1SPaolo Bonzini #[cfg(unix)]
280*8a420dd1SPaolo Bonzini assert_match!(err.raw_os_error(), Some(1));
281*8a420dd1SPaolo Bonzini assert_match!(err.kind(), ErrorKind::PermissionDenied);
282*8a420dd1SPaolo Bonzini }
283*8a420dd1SPaolo Bonzini
284*8a420dd1SPaolo Bonzini #[test]
test_from_u32()285*8a420dd1SPaolo Bonzini pub fn test_from_u32() {
286*8a420dd1SPaolo Bonzini let ok: io::Result<_> = Ok(1234u32);
287*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(ok), 1234);
288*8a420dd1SPaolo Bonzini
289*8a420dd1SPaolo Bonzini let err: io::Result<u32> = Err(io::ErrorKind::PermissionDenied.into());
290*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(err), -1);
291*8a420dd1SPaolo Bonzini
292*8a420dd1SPaolo Bonzini if cfg!(unix) {
293*8a420dd1SPaolo Bonzini let os_err: io::Result<u32> = Err(io::Error::from_raw_os_error(10));
294*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(os_err), -10);
295*8a420dd1SPaolo Bonzini }
296*8a420dd1SPaolo Bonzini }
297*8a420dd1SPaolo Bonzini
298*8a420dd1SPaolo Bonzini #[test]
test_i64()299*8a420dd1SPaolo Bonzini pub fn test_i64() {
300*8a420dd1SPaolo Bonzini assert_match!(into_io_result(1234i64), Ok(1234));
301*8a420dd1SPaolo Bonzini
302*8a420dd1SPaolo Bonzini let err = into_io_result(-22i64).unwrap_err();
303*8a420dd1SPaolo Bonzini #[cfg(unix)]
304*8a420dd1SPaolo Bonzini assert_match!(err.raw_os_error(), Some(22));
305*8a420dd1SPaolo Bonzini assert_match!(err.kind(), ErrorKind::InvalidInput);
306*8a420dd1SPaolo Bonzini }
307*8a420dd1SPaolo Bonzini
308*8a420dd1SPaolo Bonzini #[test]
test_from_u64()309*8a420dd1SPaolo Bonzini pub fn test_from_u64() {
310*8a420dd1SPaolo Bonzini let ok: io::Result<_> = Ok(1234u64);
311*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(ok), 1234);
312*8a420dd1SPaolo Bonzini
313*8a420dd1SPaolo Bonzini let err: io::Result<u64> = Err(io::ErrorKind::InvalidInput.into());
314*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(err), -22);
315*8a420dd1SPaolo Bonzini
316*8a420dd1SPaolo Bonzini if cfg!(unix) {
317*8a420dd1SPaolo Bonzini let os_err: io::Result<u64> = Err(io::Error::from_raw_os_error(6));
318*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(os_err), -6);
319*8a420dd1SPaolo Bonzini }
320*8a420dd1SPaolo Bonzini }
321*8a420dd1SPaolo Bonzini
322*8a420dd1SPaolo Bonzini #[test]
test_isize()323*8a420dd1SPaolo Bonzini pub fn test_isize() {
324*8a420dd1SPaolo Bonzini assert_match!(into_io_result(1234isize), Ok(1234));
325*8a420dd1SPaolo Bonzini
326*8a420dd1SPaolo Bonzini let err = into_io_result(-4isize).unwrap_err();
327*8a420dd1SPaolo Bonzini #[cfg(unix)]
328*8a420dd1SPaolo Bonzini assert_match!(err.raw_os_error(), Some(4));
329*8a420dd1SPaolo Bonzini assert_match!(err.kind(), ErrorKind::Interrupted);
330*8a420dd1SPaolo Bonzini }
331*8a420dd1SPaolo Bonzini
332*8a420dd1SPaolo Bonzini #[test]
test_from_unit()333*8a420dd1SPaolo Bonzini pub fn test_from_unit() {
334*8a420dd1SPaolo Bonzini let ok: io::Result<_> = Ok(());
335*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(ok), 0);
336*8a420dd1SPaolo Bonzini
337*8a420dd1SPaolo Bonzini let err: io::Result<()> = Err(io::ErrorKind::OutOfMemory.into());
338*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(err), -12);
339*8a420dd1SPaolo Bonzini
340*8a420dd1SPaolo Bonzini if cfg!(unix) {
341*8a420dd1SPaolo Bonzini let os_err: io::Result<()> = Err(io::Error::from_raw_os_error(2));
342*8a420dd1SPaolo Bonzini assert_eq!(into_neg_errno(os_err), -2);
343*8a420dd1SPaolo Bonzini }
344*8a420dd1SPaolo Bonzini }
345*8a420dd1SPaolo Bonzini }
346