io_ring 0.0.2

liburing wrapper
Documentation
#![no_std]

use core::{ptr::NonNull, time::Duration};

use rustix::{
    io::{Errno, Result},
    io_uring::{io_uring_params, Timespec},
};
use sys::io_uring;

mod sys;

pub struct IoRing {
    ring: io_uring,
}

pub use rustix::{
    fd::RawFd,
    io_uring::{
        addr3_struct, addr_len_struct, addr_or_splice_off_in_union, buf_union, cmd_op_struct,
        io_uring_ptr, io_uring_user_data, ioprio_union, len_union, off_or_addr2_union,
        op_flags_union, splice_fd_in_or_file_index_union, Advice, AtFlags, IoringAcceptFlags,
        IoringAsyncCancelFlags, IoringCqeFlags, IoringFsyncFlags, IoringMsgringCmds,
        IoringMsgringFlags, IoringOp, IoringPollFlags, IoringRecvFlags, IoringSendFlags,
        IoringSqeFlags, IoringTimeoutFlags, OFlags, ReadWriteFlags, RecvFlags, RenameFlags,
        SendFlags, SocketFlags, SpliceFlags,
    },
};
pub use sys::{io_uring_cqe, io_uring_sqe};

impl IoRing {
    pub fn new(entries: u32) -> Result<IoRing> {
        unsafe {
            let mut ring = core::mem::zeroed::<io_uring>();
            let mut p = core::mem::zeroed::<io_uring_params>();
            to_result(sys::io_uring_queue_init_params(entries, &mut ring, &mut p))?;
            Ok(IoRing { ring })
        }
    }

    pub unsafe fn push(&mut self, op: io_uring_sqe) -> Result<()> {
        let Some(sqe) = self.get_sqe() else {
            return Err(Errno::AGAIN);
        };
        sqe.as_ptr().write(op);
        Ok(())
    }

    pub fn submit_and_wait(&mut self, timeout: Duration) -> Result<io_uring_cqe> {
        unsafe {
            let mut cqe = core::ptr::null_mut();
            let mut ts = Timespec {
                tv_sec: timeout.as_secs() as _,
                tv_nsec: timeout.subsec_nanos() as _,
            };
            to_result(sys::io_uring_submit_and_wait_timeout(
                &mut self.ring,
                &mut cqe,
                1,
                &mut ts,
                core::ptr::null_mut(),
            ))?;
            let cqe = cqe.read();
            sys::io_uring_cq_advance(&mut self.ring, 1);
            Ok(cqe)
        }
    }

    fn get_sqe(&mut self) -> Option<NonNull<io_uring_sqe>> {
        unsafe { NonNull::new(sys::io_uring_get_sqe(&mut self.ring)) }
    }
}

impl Drop for IoRing {
    fn drop(&mut self) {
        unsafe { sys::io_uring_queue_exit(&mut self.ring) }
    }
}

fn to_result(code: i32) -> Result<u32> {
    if code.is_negative() {
        Err(Errno::from_raw_os_error(-code))
    } else {
        Ok(code as _)
    }
}