dope-core 0.23.0

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

use crate::driver::schedule::app;

#[derive(Clone, Copy, Eq, PartialEq)]
#[repr(u8)]
pub enum Flow {
    Batch,
    Yield,
}

#[must_use = "delegated admission must authorize exactly one transition"]
pub struct Delegated<'call, 'turn, 'd> {
    call: marker::PhantomData<fn(&'call mut ()) -> &'call mut ()>,
    brand: marker::PhantomData<app::Permit<'turn, 'd>>,
}

#[must_use = "delegated admission receipts must be settled"]
pub struct Receipt<'turn, 'd> {
    permit: app::Permit<'turn, 'd>,
}

pub trait Ready: Sized {
    type Item;

    fn rearm(self);

    fn take(self) -> Self::Item;
}

pub struct Checkpoint<T, Take, Rearm> {
    take: Take,
    rearm: Rearm,
    item: marker::PhantomData<fn() -> T>,
}

#[derive(Clone, Copy)]
#[repr(transparent)]
pub struct Step<'turn, 'd> {
    work: app::Work<'turn, 'd>,
}

impl Delegated<'_, '_, '_> {
    pub fn run<R>(self, f: impl FnOnce() -> R) -> R {
        f()
    }
}

impl<'turn, 'd> Receipt<'turn, 'd> {
    pub const fn direct(permit: app::Permit<'turn, 'd>) -> Self {
        Self { permit }
    }

    pub fn delegate<R>(
        permit: app::Permit<'turn, 'd>,
        run: impl for<'call> FnOnce(Delegated<'call, 'turn, 'd>) -> R,
    ) -> (R, Self) {
        let result = run(Delegated {
            call: marker::PhantomData,
            brand: marker::PhantomData,
        });
        (result, Self { permit })
    }

    pub fn settle(self, flow: Flow) -> Flow {
        self.permit.run(|| flow)
    }
}

impl<T, Take, Rearm> Checkpoint<T, Take, Rearm>
where
    Take: FnOnce() -> T,
    Rearm: FnOnce(),
{
    pub const fn new(take: Take, rearm: Rearm) -> Self {
        Self {
            take,
            rearm,
            item: marker::PhantomData,
        }
    }
}

impl<T, Take, Rearm> Ready for Checkpoint<T, Take, Rearm>
where
    Take: FnOnce() -> T,
    Rearm: FnOnce(),
{
    type Item = T;

    fn rearm(self) {
        (self.rearm)();
    }

    fn take(self) -> Self::Item {
        (self.take)()
    }
}

impl<'turn, 'd> Step<'turn, 'd> {
    pub const fn new(work: app::Work<'turn, 'd>) -> Self {
        Self { work }
    }

    pub fn batch<R: Ready>(self, ready: R) -> Option<R::Item> {
        match self.work.permit() {
            Some(permit) => Some(permit.run(|| ready.take())),
            None => {
                ready.rearm();
                None
            }
        }
    }
}

const _: () = {
    assert!(mem::size_of::<Flow>() == 1);
    assert!(mem::size_of::<Delegated<'static, 'static, 'static>>() == 0);
    assert!(mem::size_of::<Receipt<'static, 'static>>() == 0);
    assert!(mem::size_of::<Step<'static, 'static>>() == mem::size_of::<usize>());
};