dope-uring 0.28.0

Owned io_uring backend for dope
Documentation
use std::{mem, os::fd};

use dope_sys::{
    Errno,
    io::{
        socket,
        socket::{Socket as _, addr},
    },
    probe::{Creation, receive},
};
use fd::AsFd as _;

use crate::{Uring, sockets::probe};

pub(crate) struct Pair {
    reader: fd::OwnedFd,
    writer: fd::OwnedFd,
}

impl fd::AsFd for Pair {
    fn as_fd(&self) -> fd::BorrowedFd<'_> {
        self.reader.as_fd()
    }
}

impl Pair {
    pub(crate) fn new() -> Result<Self, Creation> {
        let kind = socket::Kind::Dgram.raw() | libc::SOCK_NONBLOCK;
        let reader = probe::bind(kind)?;
        let writer = probe::bind(kind)?;
        let mut storage = addr::Storage::<addr::Length>::empty();
        let address = addr::Addr::local::<Uring, Errno>(reader.as_fd(), &mut storage)?;
        address.try_connect::<Uring, Errno>(writer.as_fd())?;
        Ok(Self { reader, writer })
    }

    pub(crate) fn send(&self, payload: &[u8]) -> Result<(), receive::Send> {
        loop {
            match Uring::send::<{ libc::MSG_NOSIGNAL }, Errno>(self.writer.as_fd(), payload) {
                Ok(sent) => {
                    return match receive::Partial::classify(sent.len(), payload.len()) {
                        None => Ok(()),
                        Some(partial) => Err(receive::Send::Partial(partial)),
                    };
                }
                Err(error) if error.is_intr() => {}
                Err(error) => return Err(receive::Send::Syscall(error)),
            }
        }
    }
}

const _: () = assert!(mem::size_of::<Pair>() == 2 * mem::size_of::<fd::OwnedFd>());