use crate::SpawnError;
use alloc::sync::Arc;
use core::pin::Pin;
use core::task::{Context, Poll};
use crate::{Executor, ExecutorPerform};
use crate::{Future, Timer};
#[cfg(feature = "exec_embassy")]
pub struct EmbassyExecutor {
spawner: Option<embassy_executor::SendSpawner>,
ticker: Option<embassy_time::Ticker>,
}
#[cfg(feature = "exec_embassy")]
impl Executor<embassy_executor::SendSpawner> for EmbassyExecutor {
async fn context() -> Result<Self, SpawnError> {
let spawner = embassy_executor::SendSpawner::for_current_executor().await;
Ok(Self {
spawner: Some(spawner),
ticker: None,
})
}
async fn set_context(&mut self, executor: embassy_executor::SendSpawner) {
self.spawner = Some(executor);
}
async fn enter_context(&self) {
}
async fn get_executor<'a>(&'a self) -> &'a embassy_executor::SendSpawner
where
embassy_executor::SendSpawner: 'a,
{
self.spawner.as_ref().expect("No executor available")
}
fn context_sync() -> Result<Self, SpawnError> {
unimplemented!("Embassy does not support synchronous executor context creation")
}
fn set_context_sync(&mut self, _executor: embassy_executor::SendSpawner) {
unimplemented!("Embassy does not support synchronous context setting")
}
fn enter_context_sync(&self) {
unimplemented!("Embassy does not support synchronous context entry")
}
fn get_executor_sync(&self) -> &embassy_executor::SendSpawner {
unimplemented!("Embassy does not support synchronous executor access")
}
}
#[cfg(feature = "exec_embassy")]
impl ExecutorPerform<embassy_executor::SendSpawner> for EmbassyExecutor {
async fn spawn_in_context<F>(
_future: F,
) -> Result<Arc<dyn crate::Task<F::Output, Output = F::Output>>, crate::SpawnError>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
let spawner = embassy_executor::SendSpawner::for_current_executor().await;
let _ = spawner;
Ok(Arc::new(Task::new()))
}
async fn spawn_from_executor<E, F>(
_executor: &E,
_future: F,
) -> Result<Arc<dyn crate::Task<F::Output, Output = F::Output>>, crate::SpawnError>
where
E: Executor<embassy_executor::SendSpawner>,
F: Future + Send + 'static,
F::Output: Send + 'static,
{
Ok(Arc::new(Task::new()))
}
async fn block_from_executor<E, F>(_executor: &E, _future: F) -> F::Output
where
E: Executor<embassy_executor::SendSpawner>,
F: Future + Send + 'static,
F::Output: Send + 'static,
{
unimplemented!("Embassy does not support blocking on futures")
}
fn spawn_in_context_sync<F>(
_future: F,
) -> Result<Arc<dyn crate::Task<F::Output, Output = F::Output>>, crate::SpawnError>
where
F: Future + Send + 'static,
F::Output: Send + 'static,
{
unimplemented!("Embassy does not support synchronous task spawning")
}
fn spawn_from_executor_sync<E, F>(
_executor: &E,
_future: F,
) -> Result<Arc<dyn crate::Task<F::Output, Output = F::Output>>, crate::SpawnError>
where
E: Executor<embassy_executor::SendSpawner>,
F: Future + Send + 'static,
F::Output: Send + 'static,
{
unimplemented!("Embassy does not support synchronous task spawning")
}
fn block_from_executor_sync<E, F>(_executor: &E, _future: F) -> F::Output
where
E: Executor<embassy_executor::SendSpawner>,
F: Future + Send + 'static,
F::Output: Send + 'static,
{
unimplemented!("Embassy does not support synchronous blocking")
}
}
#[cfg(feature = "exec_embassy")]
impl Timer for EmbassyExecutor {
async fn once(duration_millis: u32) -> Self {
let duration = embassy_time::Duration::from_millis(u64::from(duration_millis));
let ticker = embassy_time::Ticker::every(duration);
Self {
spawner: None,
ticker: Some(ticker),
}
}
async fn interval(duration_millis: u32) -> Self {
let duration = embassy_time::Duration::from_millis(u64::from(duration_millis));
let interval = embassy_time::Ticker::every(duration);
Self {
spawner: None,
ticker: Some(interval),
}
}
async fn cancel(&mut self) {
self.ticker = None;
}
fn once_sync(duration_millis: u32) -> Self {
let duration = embassy_time::Duration::from_millis(u64::from(duration_millis));
let ticker = embassy_time::Ticker::every(duration);
Self {
spawner: None,
ticker: Some(ticker),
}
}
fn interval_sync(duration_millis: u32) -> Self {
let duration = embassy_time::Duration::from_millis(u64::from(duration_millis));
let interval = embassy_time::Ticker::every(duration);
Self {
spawner: None,
ticker: Some(interval),
}
}
fn cancel_sync(&mut self) {
self.ticker = None;
}
async fn tick(&mut self) -> u32 {
match &mut self.ticker {
None => panic!("Timer has been cancelled"),
Some(ticker) => {
ticker.next().await;
0
}
}
}
}
#[cfg(feature = "exec_embassy")]
impl Clone for EmbassyExecutor {
fn clone(&self) -> Self {
Self {
spawner: self.spawner,
ticker: None,
}
}
}
#[cfg(feature = "exec_embassy")]
pub struct Task<T> {
_phantom: core::marker::PhantomData<T>,
}
#[cfg(feature = "exec_embassy")]
impl<T> Task<T> {
pub const fn new() -> Self {
Self {
_phantom: core::marker::PhantomData,
}
}
}
#[cfg(feature = "exec_embassy")]
impl<T> Future for Task<T> {
type Output = T;
fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
Poll::Pending
}
}
#[cfg(feature = "exec_embassy")]
impl<T: Send + 'static> crate::Task<T> for Task<T> {
fn output(self) -> Pin<alloc::boxed::Box<dyn Future<Output = T> + Send>> {
unimplemented!("Embassy tasks do not support retrieving output directly")
}
fn detach(self) {
}
fn drop(self) {
}
}
#[cfg(all(feature = "hyper_executor", feature = "exec_embassy"))]
impl<F> hyper::rt::Executor<F> for EmbassyExecutor
where
F: core::future::Future + Send + 'static,
F::Output: Send + 'static,
{
fn execute(&self, _fut: F) {
}
}