moduvex_runtime/platform/
sys.rs1use std::io;
8
9#[cfg(unix)]
12use std::os::unix::io::RawFd;
13
14#[cfg(unix)]
18pub type RawSource = RawFd;
19
20#[cfg(windows)]
21pub type RawSource = windows_sys::Win32::Foundation::HANDLE;
22
23#[derive(Debug, Clone, Copy, PartialEq, Eq)]
27pub struct Interest(u8);
28
29impl Interest {
30 pub const READABLE: Interest = Interest(0b0000_0001);
32 pub const WRITABLE: Interest = Interest(0b0000_0010);
34
35 #[inline]
37 pub fn is_readable(self) -> bool {
38 self.0 & Self::READABLE.0 != 0
39 }
40
41 #[inline]
43 pub fn is_writable(self) -> bool {
44 self.0 & Self::WRITABLE.0 != 0
45 }
46
47 #[inline]
49 pub(crate) fn bits(self) -> u8 {
50 self.0
51 }
52}
53
54impl std::ops::BitOr for Interest {
55 type Output = Interest;
56 #[inline]
57 fn bitor(self, rhs: Self) -> Self::Output {
58 Interest(self.0 | rhs.0)
59 }
60}
61
62impl std::ops::BitOrAssign for Interest {
63 #[inline]
64 fn bitor_assign(&mut self, rhs: Self) {
65 self.0 |= rhs.0;
66 }
67}
68
69#[derive(Debug, Clone, Copy)]
73pub struct Event {
74 pub token: usize,
76 pub readable: bool,
78 pub writable: bool,
80}
81
82impl Event {
83 #[inline]
84 pub(crate) fn new(token: usize, readable: bool, writable: bool) -> Self {
85 Self {
86 token,
87 readable,
88 writable,
89 }
90 }
91}
92
93pub type Events = Vec<Event>;
97
98#[inline]
100pub fn events_with_capacity(cap: usize) -> Events {
101 Vec::with_capacity(cap)
102}
103
104#[cfg(unix)]
107mod unix_impl {
108 use super::*;
109 use libc::{c_int, fcntl, F_GETFL, F_SETFL, O_NONBLOCK};
110
111 pub fn set_nonblocking(fd: RawSource) -> io::Result<()> {
116 let flags = unsafe { fcntl(fd, F_GETFL) };
119 if flags == -1 {
120 return Err(io::Error::last_os_error());
121 }
122 let rc = unsafe { fcntl(fd, F_SETFL, flags | O_NONBLOCK) };
125 if rc == -1 {
126 Err(io::Error::last_os_error())
127 } else {
128 Ok(())
129 }
130 }
131
132 pub fn close_fd(fd: RawSource) -> io::Result<()> {
137 let rc = unsafe { libc::close(fd) };
141 if rc == -1 {
142 Err(io::Error::last_os_error())
143 } else {
144 Ok(())
145 }
146 }
147
148 pub fn create_pipe() -> io::Result<(RawSource, RawSource)> {
155 let mut fds: [c_int; 2] = [0; 2];
156 let rc = unsafe { libc::pipe(fds.as_mut_ptr()) };
159 if rc == -1 {
160 return Err(io::Error::last_os_error());
161 }
162 let (r, w) = (fds[0], fds[1]);
163 set_nonblocking(r)?;
164 set_nonblocking(w)?;
165 Ok((r, w))
166 }
167}
168
169#[cfg(unix)]
170pub use unix_impl::{close_fd, create_pipe, set_nonblocking};
171
172#[cfg(windows)]
175mod windows_impl {
176 use super::*;
177
178 pub fn set_nonblocking(_handle: RawSource) -> io::Result<()> {
180 Err(io::Error::new(
182 io::ErrorKind::Unsupported,
183 "not yet implemented on Windows",
184 ))
185 }
186
187 pub fn close_fd(handle: RawSource) -> io::Result<()> {
189 let ok = unsafe { windows_sys::Win32::Foundation::CloseHandle(handle) };
192 if ok == 0 {
193 Err(io::Error::last_os_error())
194 } else {
195 Ok(())
196 }
197 }
198
199 pub fn create_pipe() -> io::Result<(RawSource, RawSource)> {
201 Err(io::Error::new(
203 io::ErrorKind::Unsupported,
204 "not yet implemented on Windows",
205 ))
206 }
207}
208
209#[cfg(windows)]
210pub use windows_impl::{close_fd, create_pipe, set_nonblocking};
211
212#[cfg(test)]
215mod tests {
216 use super::*;
217
218 #[test]
219 fn interest_readable_bit() {
220 assert!(Interest::READABLE.is_readable());
221 assert!(!Interest::READABLE.is_writable());
222 }
223
224 #[test]
225 fn interest_writable_bit() {
226 assert!(Interest::WRITABLE.is_writable());
227 assert!(!Interest::WRITABLE.is_readable());
228 }
229
230 #[test]
231 fn interest_bitor() {
232 let both = Interest::READABLE | Interest::WRITABLE;
233 assert!(both.is_readable());
234 assert!(both.is_writable());
235 }
236
237 #[test]
238 fn event_fields() {
239 let e = Event::new(42, true, false);
240 assert_eq!(e.token, 42);
241 assert!(e.readable);
242 assert!(!e.writable);
243 }
244
245 #[test]
246 fn events_capacity() {
247 let ev = events_with_capacity(64);
248 assert_eq!(ev.len(), 0);
249 assert!(ev.capacity() >= 64);
250 }
251
252 #[cfg(unix)]
253 #[test]
254 fn create_pipe_returns_valid_fds() {
255 let (r, w) = create_pipe().expect("pipe creation failed");
256 let byte: u8 = 0xAB;
258 let written = unsafe { libc::write(w, &byte as *const u8 as *const _, 1) };
260 assert_eq!(written, 1);
261 let mut buf: u8 = 0;
262 let read = unsafe { libc::read(r, &mut buf as *mut u8 as *mut _, 1) };
264 assert_eq!(read, 1);
265 assert_eq!(buf, 0xAB);
266 close_fd(r).unwrap();
267 close_fd(w).unwrap();
268 }
269}