ringbahn 0.0.0-experimental.3

an experimental safe API for io-uring
Documentation
use std::ffi::CString;
use std::mem::{self, ManuallyDrop};
use std::os::unix::io::RawFd;
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::ptr;

use super::{Event, Cancellation};

pub struct Statx {
    pub statx: Box<libc::statx>,
    path: Option<CString>,
    dfd: RawFd,
    flags: i32,
    mask: u32,
}

impl Statx {
    pub fn new(path: Option<impl AsRef<Path>>, dfd: RawFd, flags: i32, mask: u32) -> Statx {
        let path = path.map(|path| {
            CString::new(path.as_ref().as_os_str().as_bytes()).expect("invalid path")
        });
        Statx {
            statx: unsafe { Box::new(mem::zeroed()) },
            path, dfd, flags, mask,
        }
    }
}

impl Event for Statx {
    unsafe fn prepare(&mut self, sqe: &mut iou::SubmissionQueueEvent<'_>) {
        let statx = &mut *self.statx as *mut libc::statx;
        let path = self.path.as_ref().map_or(ptr::null(), |cstring| cstring.as_ptr());
        let flags = self.flags | if self.path.is_some() { libc::AT_EMPTY_PATH } else { 0 };
        uring_sys::io_uring_prep_statx(sqe.raw_mut(), self.dfd, path, flags, self.mask, statx);
    }

    fn cancellation(this: &mut ManuallyDrop<Self>) -> Cancellation {
        unsafe fn callback(statx: *mut (), path: usize) {
            use std::alloc::{dealloc, Layout};
            let statx: *mut u8 = statx as _;
            let path: *mut u8 = path as _;
            dealloc(statx as *mut u8, Layout::new::<libc::statx>());
            if path != ptr::null_mut() {
                // TODO: deallocate the path
            }
        }

        let statx = &mut *this.statx as *mut libc::statx as *mut ();
        let path = this.path.as_ref().map_or(ptr::null(), |cstring| cstring.as_ptr());
        Cancellation::new(statx, path as usize, callback)
   }
}