#![no_std]
#![feature(negative_impls)]
extern crate alloc;
use core::{future::Future, task::Poll};
use async_task::Task;
use executor::EXECUTOR;
use pros_core::error::Result;
mod executor;
mod reactor;
pub fn spawn<T>(future: impl Future<Output = T> + 'static) -> Task<T> {
executor::EXECUTOR.with(|e| e.spawn(future))
}
pub fn block_on<F: Future + 'static>(future: F) -> F::Output {
executor::EXECUTOR.with(|e| e.block_on(spawn(future)))
}
#[derive(Debug)]
pub struct SleepFuture {
target_millis: u32,
}
impl Future for SleepFuture {
type Output = ();
fn poll(
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
if self.target_millis < unsafe { pros_sys::millis() } {
Poll::Ready(())
} else {
EXECUTOR.with(|e| {
e.reactor
.borrow_mut()
.sleepers
.push(cx.waker().clone(), self.target_millis)
});
Poll::Pending
}
}
}
pub fn sleep(duration: core::time::Duration) -> SleepFuture {
SleepFuture {
target_millis: unsafe { pros_sys::millis() + duration.as_millis() as u32 },
}
}
pub trait AsyncRobot {
fn opcontrol(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
fn auto(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
fn disabled(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
fn comp_init(&mut self) -> impl Future<Output = Result> {
async { Ok(()) }
}
}
#[doc(hidden)]
#[macro_export]
macro_rules! __gen_async_exports {
($rbt:ty) => {
pub static mut ROBOT: Option<$rbt> = None;
#[doc(hidden)]
#[no_mangle]
extern "C" fn opcontrol() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::opcontrol(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before opcontrol")
}))
.unwrap();
}
#[doc(hidden)]
#[no_mangle]
extern "C" fn autonomous() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::auto(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before auto")
}))
.unwrap();
}
#[doc(hidden)]
#[no_mangle]
extern "C" fn disabled() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::disabled(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before disabled")
}))
.unwrap();
}
#[doc(hidden)]
#[no_mangle]
extern "C" fn competition_initialize() {
$crate::block_on(<$rbt as $crate::AsyncRobot>::comp_init(unsafe {
ROBOT
.as_mut()
.expect("Expected initialize to run before comp_init")
}))
.unwrap();
}
};
}
#[macro_export]
macro_rules! async_robot {
($rbt:ty) => {
$crate::__gen_async_exports!($rbt);
#[no_mangle]
extern "C" fn initialize() {
let robot = Default::default();
unsafe {
ROBOT = Some(robot);
}
}
};
($rbt:ty, $init:expr) => {
$crate::__gen_async_exports!($rbt);
#[no_mangle]
extern "C" fn initialize() {
let robot = $init;
unsafe {
ROBOT = Some(robot);
}
}
};
}