use std::{ops, time};
use o3::base::time::Positive;
use crate::{
executor::{
self, drain,
drive::{self, clock},
root, session,
},
shutdown,
};
#[repr(transparent)]
pub struct App<'app, 'life: 'app, 'd: 'life, D: executor::raw::Layout<'d>, Q = ()> {
pub(crate) access: session::access::Access<'app, 'life, 'd, D, Q>,
}
impl<'app, 'life: 'app, 'd: 'life, D, Q> App<'app, 'life, 'd, D, Q>
where
D: executor::raw::App<'d>,
Q: executor::Startup,
{
pub fn drive<R>(&mut self, root: R) -> Result<R::Output, drive::Error>
where
R: root::Root<'d>,
{
self.access
.reborrow()
.drive(clock::wall(), root, drive::tick)
}
pub fn run(self) -> Result<shutdown::Requested<Q>, drive::Error> {
self.access.run()?;
Ok(shutdown::Requested::new())
}
pub fn drive_until<R>(
self,
root: R,
) -> Result<ops::ControlFlow<R::Output, shutdown::Requested<Q>>, drive::Error>
where
R: root::Root<'d>,
{
Ok(self
.access
.drive_until(root)?
.map_continue(|()| shutdown::Requested::new()))
}
pub fn drive_for<R>(
&mut self,
timeout: time::Duration,
root: R,
) -> Result<R::Output, drive::Error>
where
R: root::Root<'d>,
{
let source = clock::Bound::until(clock::wall(), timeout)?;
self.access.reborrow().drive(source, root, drive::timeout)
}
pub fn run_for(self, timeout: time::Duration) -> Result<shutdown::Requested<Q>, drive::Error> {
self.access.run_for(timeout)?;
Ok(shutdown::Requested::new())
}
pub fn run_drain(self, timeout: Positive) -> Result<drain::Report<Q>, drive::Error>
where
D: executor::raw::Drain<'d>,
{
let outcome = self.access.run_drain(timeout)?;
Ok(drain::Report::new(shutdown::Requested::new(), outcome))
}
pub fn drive_drain<R>(
self,
timeout: Positive,
root: R,
) -> Result<ops::ControlFlow<R::Output, drain::Report<Q>>, drive::Error>
where
D: executor::raw::Drain<'d>,
R: root::Root<'d>,
{
Ok(self
.access
.drive_drain(timeout, root)?
.map_continue(|outcome| drain::Report::new(shutdown::Requested::new(), outcome)))
}
}
impl<'app, 'life: 'app, 'd: 'life, D, Q> ops::Deref for App<'app, 'life, 'd, D, Q>
where
D: executor::raw::Layout<'d>,
{
type Target = session::access::Access<'app, 'life, 'd, D, Q>;
fn deref(&self) -> &Self::Target {
&self.access
}
}
impl<'d, D: executor::raw::Layout<'d>, Q> ops::DerefMut for App<'_, '_, 'd, D, Q> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.access
}
}