dope-core 0.21.0

Owned native I/O and completion driver for dope
Documentation
use std::marker;

use o3::{mem, mem::lease};

use crate::{
    driver,
    driver::schedule::ready,
    io::fd::{handles, identity, slots},
};

#[repr(transparent)]
pub(super) struct Lease<'d, P: Phase>
where
    Retire<'d, P>: mem::Return<Item = P::Id<'d>>,
{
    inner: mem::Lease<Retire<'d, P>, lease::Open>,
}

pub(super) enum Active {}
pub(super) enum Creating {}
pub(super) enum Unopened {}

pub(super) trait Phase {
    type Id<'d>: Copy;
}

pub(super) struct Retire<'d, P> {
    driver: driver::Reference<'d>,
    phase: marker::PhantomData<P>,
}

impl<'d> mem::Return for Retire<'d, Active> {
    type Item = identity::Identity<'d>;

    fn return_item(self, id: Self::Item) {
        self.driver.descriptors().retire(id);
    }
}

impl Phase for Active {
    type Id<'d> = identity::Identity<'d>;
}

impl<'d> mem::Return for Retire<'d, Creating> {
    type Item = identity::Identity<'d, handles::OutboundSlot>;

    fn return_item(self, id: Self::Item) {
        self.driver.descriptors().creating(id);
    }
}

impl Phase for Creating {
    type Id<'d> = identity::Identity<'d, handles::OutboundSlot>;
}

impl<'d> mem::Return for Retire<'d, Unopened> {
    type Item = identity::Identity<'d, handles::OutboundSlot>;

    fn return_item(self, id: Self::Item) {
        self.driver.descriptors().unopened(id);
    }
}

impl Phase for Unopened {
    type Id<'d> = identity::Identity<'d, handles::OutboundSlot>;
}

impl<'d, P: Phase> Lease<'d, P>
where
    Retire<'d, P>: mem::Return<Item = P::Id<'d>>,
{
    fn new(driver: driver::Reference<'d>, id: P::Id<'d>) -> Self {
        Self {
            inner: mem::Lease::open(
                Retire {
                    driver,
                    phase: marker::PhantomData,
                },
                id,
            ),
        }
    }

    pub(super) fn driver(&self) -> driver::Reference<'d> {
        self.inner.sink().driver
    }
}

impl<'d> Lease<'d, Active> {
    pub(super) fn from_claim(id: identity::Identity<'d>, driver: driver::Reference<'d>) -> Self {
        Self::new(driver, id)
    }

    pub(super) fn from_slot(slot: slots::ReservedSlot<'d>, driver: driver::Reference<'d>) -> Self {
        Self::new(driver, slot.into_inner().into_id())
    }

    pub(super) fn slot_ref(&self) -> &handles::PhysicalSlot {
        self.inner.item().slot_ref()
    }

    pub(super) fn slot(&self) -> handles::PhysicalSlot {
        self.inner.item().slot()
    }

    pub(super) fn ready_handle(&self) -> ready::Handle<'d> {
        self.driver().ready().handle(*self.inner.item())
    }
}

impl<'d> Lease<'d, Unopened> {
    pub(super) fn from_claim(
        id: identity::Identity<'d, handles::OutboundSlot>,
        driver: driver::Reference<'d>,
    ) -> Self {
        Self::new(driver, id)
    }

    pub(super) fn begin(self) -> Lease<'d, Creating> {
        let (sink, id) = self.inner.into_parts();
        sink.driver.outbound().begin_create(id.slot());
        Lease::new(sink.driver, id)
    }

    pub(super) fn outbound(&self) -> handles::OutboundSlot {
        self.inner.item().slot()
    }
}

impl<'d> Lease<'d, Creating> {
    pub(super) fn activate(self) -> Lease<'d, Active> {
        let (sink, id) = self.inner.into_parts();
        Lease::new(sink.driver, id.physical())
    }

    pub(super) fn ready_handle(&self) -> ready::Handle<'d> {
        self.driver().ready().handle(self.inner.item().physical())
    }

    pub(super) fn slot(&self) -> handles::PhysicalSlot {
        self.inner.item().slot().physical()
    }
}

const _: () = {
    use std::mem::{align_of, size_of};

    assert!(
        size_of::<Lease<'static, Active>>()
            == size_of::<(driver::Reference<'static>, identity::Identity<'static>)>()
    );
    assert!(
        align_of::<Lease<'static, Active>>()
            == align_of::<(driver::Reference<'static>, identity::Identity<'static>)>()
    );
};