use std::{marker, mem, ops, pin};
use dope_core::{
driver::{
self,
result::SubmitError,
retained::{self, flight},
route::{self, kind},
schedule,
},
io::fs,
};
use dope_runtime::executor;
use crate::app::dispatch::event;
mod activate;
mod call;
mod omit;
mod probe;
mod resume;
mod wakes;
pub use activate::Activate;
pub use call::Call;
pub use omit::Omit;
pub use probe::Probe;
pub use resume::Resume;
pub use wakes::Wakes;
pub struct Plain;
pub struct Retained;
#[repr(transparent)]
pub struct Context<'a, 'owner, 'd: 'owner, A> {
inner: retained::Context<'a, 'owner, 'd>,
access: marker::PhantomData<A>,
}
impl<'a, 'owner, 'd: 'owner> Context<'a, 'owner, 'd, Retained> {
pub fn new(inner: retained::Context<'a, 'owner, 'd>) -> Self {
Self {
inner,
access: marker::PhantomData,
}
}
pub fn narrow<A>(&mut self) -> Context<'_, 'owner, 'd, A> {
Context {
inner: self.inner.reborrow(),
access: marker::PhantomData,
}
}
pub fn reborrow(&mut self) -> Context<'_, 'owner, 'd, Retained> {
Context {
inner: self.inner.reborrow(),
access: marker::PhantomData,
}
}
pub unsafe fn submit_file<'borrow, Tag, C>(
self,
slots: &flight::Slots<'d, Tag>,
entry: fs::Submission<'borrow, 'd, Tag, C>,
) -> Result<flight::Flight<'d, C>, SubmitError>
where
'owner: 'borrow,
Tag: route::Tag,
C: kind::Flight,
{
unsafe { retained::raw::Submission::try_file(self.inner, slots, entry) }
}
}
impl<'a, 'owner, 'd: 'owner> ops::Deref for Context<'a, 'owner, 'd, Plain> {
type Target = driver::Context<'a, 'd>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, 'owner, 'd: 'owner> ops::DerefMut for Context<'a, 'owner, 'd, Plain> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
impl<'a, 'owner, 'd: 'owner> ops::Deref for Context<'a, 'owner, 'd, Retained> {
type Target = retained::Context<'a, 'owner, 'd>;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl<'a, 'owner, 'd: 'owner> ops::DerefMut for Context<'a, 'owner, 'd, Retained> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
pub trait Install<'d> {
fn install(self: pin::Pin<&mut Self>);
}
pub trait Installs<'d, M> {
fn call<'app, 'owner>(
install: executor::raw::Install<'app, 'owner, 'd, M>,
) -> executor::raw::Install<'app, 'owner, 'd, M>;
}
pub trait Projection<'d> {
type Inner;
fn inner(self: pin::Pin<&Self>) -> pin::Pin<&Self::Inner>;
fn inner_mut(self: pin::Pin<&mut Self>) -> pin::Pin<&mut Self::Inner>;
}
pub struct Projected<M>(marker::PhantomData<fn() -> M>);
impl<'d, M> Installs<'d, M> for Projected<M>
where
M: Projection<'d>,
M::Inner: Manifold<'d>,
{
fn call<'app, 'owner>(
install: executor::raw::Install<'app, 'owner, 'd, M>,
) -> executor::raw::Install<'app, 'owner, 'd, M> {
let (mut owner, proof) = install.into_parts();
let child = executor::raw::Install::new(Projection::inner_mut(owner.as_mut()), proof);
let proof = <<M::Inner as Manifold<'d>>::Install as Installs<'d, M::Inner>>::call(child)
.into_install();
executor::raw::Install::new(owner, proof)
}
}
impl<'d, M> executor::raw::Finishes<'d, M> for Projected<M>
where
M: Projection<'d>,
M::Inner: Manifold<'d>,
{
fn call<'app, 'finish, 'owner, 'epoch>(
finish: executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, M>,
) -> executor::raw::Finish<'app, 'finish, 'owner, 'epoch, 'd, M> {
let (mut owner, install, proof) = finish.into_parts();
let child =
executor::raw::Finish::new(Projection::inner_mut(owner.as_mut()), install, proof);
let (install, proof) = <<M::Inner as Manifold<'d>>::Finish as executor::raw::Finishes<
'd,
M::Inner,
>>::call(child)
.into_finish();
executor::raw::Finish::new(owner, install, proof)
}
}
impl<'d, M> Installs<'d, M> for Plain
where
M: Install<'d>,
{
fn call<'app, 'owner>(
install: executor::raw::Install<'app, 'owner, 'd, M>,
) -> executor::raw::Install<'app, 'owner, 'd, M> {
let (mut owner, proof) = install.into_parts();
Install::install(owner.as_mut());
executor::raw::Install::new(owner, proof)
}
}
pub unsafe trait Manifold<'d>: Sized {
type Route: route::App;
const ID: route::Id = <Self::Route as route::App>::ID;
const COORDS: usize;
type Dispatch: event::Set<'d, Self, Self::Route>;
type Install: Installs<'d, Self>;
type Finish: executor::raw::Finishes<'d, Self>;
type Activate: Wakes<'d, Self, Self::Route>;
type Probe: Probe<'d, Self>;
type PrePark;
type Shutdown;
unsafe fn pre_park<'a, 'turn, 'root>(
self: pin::Pin<&'a mut Self>,
turn: schedule::Turn<'turn, 'd>,
driver: &mut Context<'_, 'root, 'd, Self::PrePark>,
) -> pin::Pin<&'a mut Self>
where
Self: 'root;
fn shutdown<'a, 'turn, 'root>(
self: pin::Pin<&'a mut Self>,
turn: schedule::Turn<'turn, 'd>,
driver: &mut Context<'_, 'root, 'd, Self::Shutdown>,
) -> pin::Pin<&'a mut Self>
where
Self: 'root;
}
const _: () = {
assert!(
std::mem::size_of::<Context<'_, '_, '_, Plain>>()
== std::mem::size_of::<driver::Context<'_, '_>>()
);
assert!(
std::mem::align_of::<Context<'_, '_, '_, Plain>>()
== std::mem::align_of::<driver::Context<'_, '_>>()
);
assert!(
std::mem::size_of::<Context<'_, '_, '_, Retained>>()
== std::mem::size_of::<retained::Context<'_, '_, '_>>()
);
assert!(
std::mem::align_of::<Context<'_, '_, '_, Retained>>()
== std::mem::align_of::<retained::Context<'_, '_, '_>>()
);
};
#[repr(transparent)]
pub struct Installed<'step, 'd: 'step, T: ?Sized> {
owner: pin::Pin<&'step mut T>,
driver: marker::PhantomData<fn(&'d ()) -> &'d ()>,
}
impl<'step, 'd: 'step, T: ?Sized> Installed<'step, 'd, T> {
pub(in crate::app::dispatch::raw) fn new(owner: pin::Pin<&'step mut T>) -> Self {
Self {
owner,
driver: marker::PhantomData,
}
}
pub fn as_ref(&self) -> pin::Pin<&T> {
self.owner.as_ref()
}
pub fn as_mut(&mut self) -> pin::Pin<&mut T> {
self.owner.as_mut()
}
pub fn project<'a, U: ?Sized>(
&'a mut self,
project: impl FnOnce(pin::Pin<&'a mut T>) -> pin::Pin<&'a mut U>,
) -> Loan<'a, 'd, U> {
self.project_with(|owner| (project(owner), ())).0
}
pub fn project_with<'a, U: ?Sized, V>(
&'a mut self,
project: impl FnOnce(pin::Pin<&'a mut T>) -> (pin::Pin<&'a mut U>, V),
) -> (Loan<'a, 'd, U>, V) {
let (owner, value) = project(self.owner.as_mut());
(Loan::new(owner), value)
}
}
const _: () = {
assert!(mem::size_of::<Installed<'_, '_, ()>>() == mem::size_of::<usize>());
assert!(mem::align_of::<Installed<'_, '_, ()>>() == mem::align_of::<usize>());
assert!(mem::size_of::<Option<Installed<'_, '_, ()>>>() == mem::size_of::<usize>());
assert!(mem::align_of::<Option<Installed<'_, '_, ()>>>() == mem::align_of::<usize>());
};
#[repr(transparent)]
pub struct Loan<'step, 'd: 'step, T: ?Sized> {
owner: pin::Pin<&'step mut T>,
driver: marker::PhantomData<fn(&'d ()) -> &'d ()>,
}
impl<'step, 'd: 'step, T: ?Sized> Loan<'step, 'd, T> {
pub(in crate::app::dispatch::raw) fn new(owner: pin::Pin<&'step mut T>) -> Self {
Self {
owner,
driver: marker::PhantomData,
}
}
pub fn into_pin(self) -> pin::Pin<&'step mut T> {
self.owner
}
}
const _: () = {
assert!(mem::size_of::<Loan<'static, 'static, ()>>() == mem::size_of::<usize>());
assert!(mem::align_of::<Loan<'static, 'static, ()>>() == mem::align_of::<usize>());
assert!(mem::size_of::<Option<Loan<'static, 'static, ()>>>() == mem::size_of::<usize>());
assert!(mem::align_of::<Option<Loan<'static, 'static, ()>>>() == mem::align_of::<usize>());
};
pub unsafe trait Control<'d>: Manifold<'d> {
type View<'step>
where
Self: 'step,
'd: 'step;
fn view<'step>(owner: Installed<'step, 'd, Self>) -> Self::View<'step>
where
'd: 'step;
unsafe fn root<'step>(owner: pin::Pin<&'step mut Self>) -> Self::View<'step>
where
'd: 'step,
{
Self::view(Installed::new(owner))
}
}