monoio/driver/
util.rs

1use std::{ffi::CString, io, path::Path};
2
3#[allow(unused_variables)]
4pub(super) fn cstr(p: &Path) -> io::Result<CString> {
5    #[cfg(unix)]
6    {
7        use std::os::unix::ffi::OsStrExt;
8        Ok(CString::new(p.as_os_str().as_bytes())?)
9    }
10    #[cfg(windows)]
11    if let Some(s) = p.as_os_str().to_str() {
12        Ok(CString::new(s)?)
13    } else {
14        Err(io::Error::new(
15            io::ErrorKind::InvalidInput,
16            "invalid utf-8: corrupt contents",
17        ))
18    }
19}
20
21// Convert Duration to Timespec
22// It's strange that io_uring does not impl From<Duration> for Timespec.
23#[cfg(all(target_os = "linux", feature = "iouring"))]
24pub(super) fn timespec(duration: std::time::Duration) -> io_uring::types::Timespec {
25    io_uring::types::Timespec::new()
26        .sec(duration.as_secs())
27        .nsec(duration.subsec_nanos())
28}
29
30/// Do syscall and return Result<T, std::io::Error>
31/// If use syscall@FD or syscall@NON_FD, the return value is wrapped in MaybeFd. The `MaybeFd` is
32/// designed to close the fd when it is dropped.
33/// If use syscall@RAW, the return value is raw value. The requirement to explicitly add @RAW is to
34/// avoid misuse.
35#[cfg(unix)]
36#[macro_export]
37macro_rules! syscall {
38    ($fn: ident @FD ( $($arg: expr),* $(,)* ) ) => {{
39        let res = unsafe { libc::$fn($($arg, )*) };
40        if res == -1 {
41            Err(std::io::Error::last_os_error())
42        } else {
43            Ok(unsafe { $crate::driver::op::MaybeFd::new_fd(res as u32) })
44        }
45    }};
46    ($fn: ident @NON_FD ( $($arg: expr),* $(,)* ) ) => {{
47        let res = unsafe { libc::$fn($($arg, )*) };
48        if res == -1 {
49            Err(std::io::Error::last_os_error())
50        } else {
51            Ok($crate::driver::op::MaybeFd::new_non_fd(res as u32))
52        }
53    }};
54    ($fn: ident @RAW ( $($arg: expr),* $(,)* ) ) => {{
55        let res = unsafe { libc::$fn($($arg, )*) };
56        if res == -1 {
57            Err(std::io::Error::last_os_error())
58        } else {
59            Ok(res)
60        }
61    }};
62}
63
64/// Do syscall and return Result<T, std::io::Error>
65/// If use syscall@FD or syscall@NON_FD, the return value is wrapped in MaybeFd. The `MaybeFd` is
66/// designed to close the fd when it is dropped.
67/// If use syscall@RAW, the return value is raw value. The requirement to explicitly add @RAW is to
68/// avoid misuse.
69#[cfg(windows)]
70#[macro_export]
71macro_rules! syscall {
72    ($fn: ident @FD ( $($arg: expr),* $(,)* ), $err_test: path, $err_value: expr) => {{
73        let res = unsafe { $fn($($arg, )*) };
74        if $err_test(&res, &$err_value) {
75            Err(std::io::Error::last_os_error())
76        } else {
77            Ok(unsafe { $crate::driver::op::MaybeFd::new_fd(res.try_into().unwrap()) })
78        }
79    }};
80    ($fn: ident @NON_FD ( $($arg: expr),* $(,)* ), $err_test: path, $err_value: expr) => {{
81        let res = unsafe { $fn($($arg, )*) };
82        if $err_test(&res, &$err_value) {
83            Err(std::io::Error::last_os_error())
84        } else {
85            Ok($crate::driver::op::MaybeFd::new_non_fd(res.try_into().unwrap()))
86        }
87    }};
88    ($fn: ident @RAW ( $($arg: expr),* $(,)* ), $err_test: path, $err_value: expr) => {{
89        let res = unsafe { $fn($($arg, )*) };
90        if $err_test(&res, &$err_value) {
91            Err(std::io::Error::last_os_error())
92        } else {
93            Ok(res.try_into().unwrap())
94        }
95    }};
96}
97
98#[cfg(all(
99    not(all(target_os = "linux", feature = "iouring")),
100    not(feature = "legacy")
101))]
102pub(crate) fn feature_panic() -> ! {
103    panic!("one of iouring and legacy features must be enabled");
104}
105
106#[cfg(all(windows, feature = "renameat"))]
107pub(crate) fn to_wide_string(str: &str) -> Vec<u16> {
108    use std::{ffi::OsStr, iter::once, os::windows::ffi::OsStrExt};
109
110    OsStr::new(str).encode_wide().chain(once(0)).collect()
111}