1 use std::ptr::null_mut;
2 use std::os::unix::io::RawFd;
3 use libc::{c_int, timeval};
4 use {Errno, Result};
5 use sys::time::TimeVal;
6 
7 pub const FD_SETSIZE: RawFd = 1024;
8 
9 #[cfg(any(target_os = "macos", target_os = "ios"))]
10 #[repr(C)]
11 #[derive(Clone)]
12 pub struct FdSet {
13     bits: [i32; FD_SETSIZE as usize / 32]
14 }
15 
16 #[cfg(any(target_os = "macos", target_os = "ios"))]
17 const BITS: usize = 32;
18 
19 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
20 #[repr(C)]
21 #[derive(Clone)]
22 pub struct FdSet {
23     bits: [u64; FD_SETSIZE as usize / 64]
24 }
25 
26 #[cfg(not(any(target_os = "macos", target_os = "ios")))]
27 const BITS: usize = 64;
28 
29 impl FdSet {
new() -> FdSet30     pub fn new() -> FdSet {
31         FdSet {
32             bits: [0; FD_SETSIZE as usize / BITS]
33         }
34     }
35 
insert(&mut self, fd: RawFd)36     pub fn insert(&mut self, fd: RawFd) {
37         let fd = fd as usize;
38         self.bits[fd / BITS] |= 1 << (fd % BITS);
39     }
40 
remove(&mut self, fd: RawFd)41     pub fn remove(&mut self, fd: RawFd) {
42         let fd = fd as usize;
43         self.bits[fd / BITS] &= !(1 << (fd % BITS));
44     }
45 
contains(&self, fd: RawFd) -> bool46     pub fn contains(&self, fd: RawFd) -> bool {
47         let fd = fd as usize;
48         self.bits[fd / BITS] & (1 << (fd % BITS)) > 0
49     }
50 
clear(&mut self)51     pub fn clear(&mut self) {
52         for bits in &mut self.bits {
53             *bits = 0
54         }
55     }
56 }
57 
58 mod ffi {
59     use libc::{c_int, timeval};
60     use super::FdSet;
61 
62     extern {
select(nfds: c_int, readfds: *mut FdSet, writefds: *mut FdSet, errorfds: *mut FdSet, timeout: *mut timeval) -> c_int63         pub fn select(nfds: c_int,
64                       readfds: *mut FdSet,
65                       writefds: *mut FdSet,
66                       errorfds: *mut FdSet,
67                       timeout: *mut timeval) -> c_int;
68     }
69 }
70 
select(nfds: c_int, readfds: Option<&mut FdSet>, writefds: Option<&mut FdSet>, errorfds: Option<&mut FdSet>, timeout: Option<&mut TimeVal>) -> Result<c_int>71 pub fn select(nfds: c_int,
72               readfds: Option<&mut FdSet>,
73               writefds: Option<&mut FdSet>,
74               errorfds: Option<&mut FdSet>,
75               timeout: Option<&mut TimeVal>) -> Result<c_int> {
76     let readfds = readfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
77     let writefds = writefds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
78     let errorfds = errorfds.map(|set| set as *mut FdSet).unwrap_or(null_mut());
79     let timeout = timeout.map(|tv| tv as *mut TimeVal as *mut timeval)
80                          .unwrap_or(null_mut());
81 
82     let res = unsafe {
83         ffi::select(nfds, readfds, writefds, errorfds, timeout)
84     };
85 
86     Errno::result(res)
87 }
88