use std::{
io::{self, IoSlice, IoSliceMut},
os::unix::io::{AsRawFd, BorrowedFd, RawFd},
pin::Pin
};
use mio::{
Interest,
Registry,
Token,
event,
};
use nix::{
libc::off_t,
sys::{
aio::{self, Aio},
event::EventFlag,
signal::SigevNotify
}
};
pub use nix::sys::aio::AioFsyncMode;
pub type ReadAt<'a> = Source<aio::AioRead<'a>>;
pub type ReadvAt<'a> = Source<aio::AioReadv<'a>>;
pub type Fsync<'a> = Source<aio::AioFsync<'a>>;
pub type WriteAt<'a> = Source<aio::AioWrite<'a>>;
pub type WritevAt<'a> = Source<aio::AioWritev<'a>>;
pub trait SourceApi {
type Output;
fn aio_return(self: Pin<&mut Self>) -> nix::Result<Self::Output>;
fn cancel(self: Pin<&mut Self>) -> nix::Result<aio::AioCancelStat>;
fn error(self: Pin<&mut Self>) -> nix::Result<()>;
fn in_progress(&self) -> bool;
#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
fn deregister_raw(&mut self);
#[cfg(feature = "tokio")]
#[cfg_attr(docsrs, doc(cfg(feature = "tokio")))]
fn register_raw(&mut self, kq: RawFd, udata: usize);
fn submit(self: Pin<&mut Self>) -> nix::Result<()>;
}
#[derive(Debug)]
pub struct Source<T>{inner: T}
impl<T: Aio> Source<T> {
pin_utils::unsafe_pinned!(inner: T);
fn _deregister_raw(&mut self) {
let sigev = SigevNotify::SigevNone;
self.inner.set_sigev_notify(sigev);
}
fn _register_raw(&mut self, kq: RawFd, udata: usize) {
let sigev = SigevNotify::SigevKeventFlags{
kq,
udata: udata as isize,
flags: EventFlag::EV_ONESHOT
};
self.inner.set_sigev_notify(sigev);
}
}
impl<T: Aio> SourceApi for Source<T> {
type Output = T::Output;
fn aio_return(self: Pin<&mut Self>) -> nix::Result<Self::Output> {
self.inner().aio_return()
}
fn cancel(self: Pin<&mut Self>) -> nix::Result<aio::AioCancelStat> {
self.inner().cancel()
}
#[cfg(feature = "tokio")]
fn deregister_raw(&mut self) {
self._deregister_raw()
}
fn error(self: Pin<&mut Self>) -> nix::Result<()> {
self.inner().error()
}
fn in_progress(&self) -> bool {
self.inner.in_progress()
}
#[cfg(feature = "tokio")]
fn register_raw(&mut self, kq: RawFd, udata: usize) {
self._register_raw(kq, udata)
}
fn submit(self: Pin<&mut Self>) -> nix::Result<()> {
self.inner().submit()
}
}
impl<T: Aio> event::Source for Source<T> {
fn register(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
assert!(interests.is_aio());
let udata = usize::from(token);
let kq = registry.as_raw_fd();
self._register_raw(kq, udata);
Ok(())
}
fn reregister(
&mut self,
registry: &Registry,
token: Token,
interests: Interest,
) -> io::Result<()> {
self.register(registry, token, interests)
}
fn deregister(
&mut self,
_registry: &Registry) -> io::Result<()>
{
self._deregister_raw();
Ok(())
}
}
impl<'a> Source<aio::AioFsync<'a>> {
pub fn fsync(fd: BorrowedFd<'a>, mode: AioFsyncMode, prio: i32) -> Self {
let inner = aio::AioFsync::new(fd, mode, prio, SigevNotify::SigevNone);
Source{inner}
}
}
impl<'a> Source<aio::AioRead<'a>> {
pub fn read_at(
fd: BorrowedFd<'a>,
offs: u64,
buf: &'a mut [u8],
prio: i32,
) -> Self
{
let inner = aio::AioRead::new(fd, offs as off_t, buf, prio,
SigevNotify::SigevNone);
Source{inner}
}
}
impl<'a> Source<aio::AioReadv<'a>> {
pub fn readv_at(
fd: BorrowedFd<'a>,
offs: u64,
bufs: &mut [IoSliceMut<'a>],
prio: i32,
) -> Self
{
let inner = aio::AioReadv::new(fd, offs as off_t, bufs, prio,
SigevNotify::SigevNone);
Source{inner}
}
}
impl<'a> Source<aio::AioWrite<'a>> {
pub fn write_at(fd: BorrowedFd<'a>, offs: u64, buf: &'a [u8], prio: i32) -> Self {
let inner = aio::AioWrite::new(fd, offs as off_t, buf, prio,
SigevNotify::SigevNone);
Source{inner}
}
}
impl<'a> Source<aio::AioWritev<'a>> {
pub fn writev_at(fd: BorrowedFd<'a>, offs: u64, bufs: &[IoSlice<'a>], prio: i32)
-> Self
{
let inner = aio::AioWritev::new(fd, offs as off_t, bufs, prio,
SigevNotify::SigevNone);
Source{inner}
}
}