dope-uring 0.29.1

Owned io_uring backend for dope
Documentation
use dope_sys::{
    io::Close,
    kernel, memory,
    probe::{
        cleanup, session,
        session::{Closed as _, Occupied as _},
    },
    ring::{
        Owner as _,
        map::{Storage, Unmap as _},
        register::Occupied as _,
    },
    table::token,
};

use crate::{
    Ring, error,
    reactor::{register, ring::Session, sq},
};

type Occupied<T, L> = <Session<T, L> as session::Empty>::Occupied;
type Closed<T, L> = <Occupied<T, L> as Close>::State;

pub struct Released<T: token::Codec, L: memory::raw::Canary, P> {
    primary: P,
    state: State<T, L>,
}

enum State<T: token::Codec, L: memory::raw::Canary> {
    Raw(register::Closing<T>),
    Session(Closed<T, L>),
}

impl<T: token::Codec, L: memory::raw::Canary, P: Copy> cleanup::Release<P> for Released<T, L, P> {
    type Ring = Ring<T>;
    type File = register::raw::Occupied;
    type Session = Occupied<T, L>;
    type Target = sq::Fixed;

    fn raw(ring: Ring<T>, file: Self::File, primary: P) -> Result<(P, sq::Fixed), Self> {
        let slot = file.slot();
        match ring.close_file(file) {
            Ok(()) => Ok((primary, slot)),
            Err(state) => Err(Self {
                primary,
                state: State::Raw(state),
            }),
        }
    }

    fn session(session: Self::Session, primary: P) -> Result<(P, sq::Fixed), Self> {
        let slot = session.slot();
        match session.try_close() {
            Ok(()) => Ok((primary, slot)),
            Err(state) => Err(Self {
                primary,
                state: State::Session(state),
            }),
        }
    }
}

impl<T: token::Codec, L: memory::raw::Canary, P: Copy> memory::Cleanup<(P, sq::Fixed)>
    for Released<T, L, P>
{
    type Error = Storage<kernel::Errno<error::Unmap>>;

    fn primary(&self) -> (P, sq::Fixed) {
        let slot = match &self.state {
            State::Raw(state) => state.slot(),
            State::Session(state) => state.slot(),
        };
        (self.primary, slot)
    }

    fn failure(&self) -> Self::Error {
        match &self.state {
            State::Raw(state) => state.failure(),
            State::Session(state) => state.failure(),
        }
    }

    fn try_close(self, mut report: impl FnMut(Self::Error)) -> Result<(P, sq::Fixed), Self> {
        match self.state {
            State::Raw(state) => Self::finish(state, self.primary, State::Raw, &mut report),
            State::Session(state) => Self::finish(state, self.primary, State::Session, &mut report),
        }
    }
}

impl<T: token::Codec, L: memory::raw::Canary, P: Copy> Released<T, L, P> {
    fn finish<S: session::Closed<Target = sq::Fixed, Error = kernel::Errno<error::Unmap>>>(
        state: S,
        primary: P,
        retain: impl FnOnce(S) -> State<T, L>,
        report: &mut impl FnMut(Storage<kernel::Errno<error::Unmap>>),
    ) -> Result<(P, sq::Fixed), Self> {
        let slot = state.slot();
        let (owner, cause) = state.recover().into_parts();
        report(cause.into());
        let state = match owner.try_close() {
            Ok(()) => return Ok((primary, slot)),
            Err(state) => state,
        };
        Err(Self {
            primary,
            state: retain(state),
        })
    }
}