use crate::{io, PollOpt, Ready};
use libc;
use std::mem;
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::ops::{Deref, DerefMut};
use std::os::unix::io::RawFd;
use zircon;
mod awakener;
mod eventedfd;
mod handles;
mod net;
mod ready;
mod selector;
use self::eventedfd::{EventedFd, EventedFdInner};
use self::ready::assert_fuchsia_ready_repr;
pub use self::awakener::Awakener;
pub use self::handles::EventedHandle;
pub use self::net::{TcpListener, TcpStream, UdpSocket};
pub use self::ready::{zx_signals_t, FuchsiaReady};
pub use self::selector::{Events, Selector};
pub fn set_nonblock(fd: RawFd) -> io::Result<()> {
cvt(unsafe { libc::fcntl(fd, libc::F_SETFL, libc::O_NONBLOCK) }).map(|_| ())
}
unsafe fn recv_from(fd: RawFd, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
let flags = 0;
let n = cvt(libc::recv(
fd,
buf.as_mut_ptr() as *mut libc::c_void,
buf.len(),
flags,
))?;
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 8080);
Ok((n as usize, addr))
}
mod sys {
#![allow(non_camel_case_types)]
use std::os::unix::io::RawFd;
pub use zircon_sys::{zx_handle_t, zx_signals_t};
pub type fdio_ops_t = [usize; 17];
pub type atomic_int_fast32_t = usize;
#[repr(C)]
pub struct fdio_t {
pub ops: *const fdio_ops_t,
pub magic: u32,
pub refcount: atomic_int_fast32_t,
pub dupcount: u32,
pub flags: u32,
}
#[link(name = "fdio")]
extern "C" {
pub fn __fdio_fd_to_io(fd: RawFd) -> *const fdio_t;
pub fn __fdio_release(io: *const fdio_t);
pub fn __fdio_wait_begin(
io: *const fdio_t,
events: u32,
handle_out: &mut zx_handle_t,
signals_out: &mut zx_signals_t,
);
pub fn __fdio_wait_end(
io: *const fdio_t,
signals: zx_signals_t,
events_out: &mut u32,
);
}
}
fn epoll_event_to_ready(epoll: u32) -> Ready {
let epoll = epoll as i32; let mut kind = Ready::empty();
if (epoll & libc::EPOLLIN) != 0 || (epoll & libc::EPOLLPRI) != 0 {
kind = kind | Ready::readable();
}
if (epoll & libc::EPOLLOUT) != 0 {
kind = kind | Ready::writable();
}
kind
}
fn poll_opts_to_wait_async(poll_opts: PollOpt) -> zircon::WaitAsyncOpts {
if poll_opts.is_oneshot() {
zircon::WaitAsyncOpts::Once
} else {
zircon::WaitAsyncOpts::Repeating
}
}
trait IsMinusOne {
fn is_minus_one(&self) -> bool;
}
impl IsMinusOne for i32 {
fn is_minus_one(&self) -> bool {
*self == -1
}
}
impl IsMinusOne for isize {
fn is_minus_one(&self) -> bool {
*self == -1
}
}
fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
use std::io;
if t.is_minus_one() {
Err(io::Error::last_os_error())
} else {
Ok(t)
}
}
#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
struct DontDrop<T>(Option<T>);
impl<T> DontDrop<T> {
fn new(t: T) -> DontDrop<T> {
DontDrop(Some(t))
}
fn inner_ref(&self) -> &T {
self.0.as_ref().unwrap()
}
fn inner_mut(&mut self) -> &mut T {
self.0.as_mut().unwrap()
}
}
impl<T> Deref for DontDrop<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.inner_ref()
}
}
impl<T> DerefMut for DontDrop<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.inner_mut()
}
}
impl<T> Drop for DontDrop<T> {
fn drop(&mut self) {
let inner = self.0.take();
mem::forget(inner);
}
}