use std::{future::Future, time::Duration};
use crate::{
call::Call,
inline_static_ref,
memory::scope::LocalScopeExt,
prelude::{AsyncGcFrame, JlrsResult, Target, Value},
};
pub trait Register: 'static + Send {
fn register(frame: AsyncGcFrame) -> impl Future<Output = JlrsResult<()>>;
}
pub trait AsyncTask: 'static + Send {
type Output: 'static + Send;
fn run(self, frame: AsyncGcFrame) -> impl Future<Output = Self::Output>;
}
impl<A, U> AsyncTask for A
where
A: AsyncFnOnce(AsyncGcFrame) -> U + Send + 'static,
U: Send + 'static,
{
type Output = U;
fn run(self, frame: AsyncGcFrame) -> impl Future<Output = Self::Output> {
self(frame)
}
}
pub trait PersistentTask: 'static + Send {
type State<'state>;
type Input: 'static + Send;
type Output: 'static + Send;
const CHANNEL_CAPACITY: usize = 0;
fn init<'task>(
&mut self,
frame: AsyncGcFrame<'task>,
) -> impl Future<Output = JlrsResult<Self::State<'task>>>;
fn run<'frame, 'task: 'frame>(
&mut self,
frame: AsyncGcFrame<'frame>,
state: &mut Self::State<'task>,
input: Self::Input,
) -> impl Future<Output = Self::Output>;
fn exit<'task>(
&mut self,
_frame: AsyncGcFrame<'task>,
_state: &mut Self::State<'task>,
) -> impl Future<Output = ()> {
async {}
}
}
pub fn sleep<'scope, 'data, Tgt: Target<'scope>>(target: &Tgt, duration: Duration) {
unsafe {
let millis = duration.as_millis();
if millis == 0 {
return;
}
target.with_local_scope::<_, 1>(|target, mut frame| {
let secs = duration.as_millis() as usize as f64 / 1000.;
let secs = Value::new(&mut frame, secs);
let func: Value<'_, '_> =
inline_static_ref!(SLEEP, Value<'static, 'static>, "Base.sleep", target);
func.call(target, [secs]).expect("sleep threw an exception");
})
}
}