1#![forbid(unsafe_code)]
4#![warn(missing_docs, missing_debug_implementations, rust_2018_idioms)]
5#![no_std]
6extern crate alloc;
7
8use alloc::boxed::Box;
9use async_trait::async_trait;
10use core::{fmt, future::Future, ops::Deref, pin::Pin};
11
12pub struct LocalExecutorError(pub Pin<Box<dyn Future<Output = ()>>>);
15
16impl fmt::Debug for LocalExecutorError {
17 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18 f.debug_tuple("LocalExecutorError")
19 .field(&"Future")
20 .finish()
21 }
22}
23
24pub trait FullExecutor: Executor + BlockingExecutor {}
26
27pub trait Executor {
29 fn block_on(&self, f: Pin<Box<dyn Future<Output = ()>>>);
31
32 fn spawn(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) -> Box<dyn Task>;
34
35 fn spawn_local(
37 &self,
38 f: Pin<Box<dyn Future<Output = ()>>>,
39 ) -> Result<Box<dyn Task>, LocalExecutorError> {
40 Err(LocalExecutorError(f))
41 }
42}
43
44#[async_trait]
46pub trait BlockingExecutor {
47 async fn spawn_blocking(&self, f: Box<dyn FnOnce() + Send + 'static>);
49}
50
51impl<E: Deref + Sync> FullExecutor for E where E::Target: FullExecutor + Sync {}
52
53impl<E: Deref + Sync> Executor for E
54where
55 E::Target: Executor + Sync,
56{
57 fn block_on(&self, f: Pin<Box<dyn Future<Output = ()>>>) {
58 self.deref().block_on(f)
59 }
60
61 fn spawn(&self, f: Pin<Box<dyn Future<Output = ()> + Send>>) -> Box<dyn Task> {
62 self.deref().spawn(f)
63 }
64
65 fn spawn_local(
66 &self,
67 f: Pin<Box<dyn Future<Output = ()>>>,
68 ) -> Result<Box<dyn Task>, LocalExecutorError> {
69 self.deref().spawn_local(f)
70 }
71}
72
73#[async_trait]
74impl<E: Deref + Sync> BlockingExecutor for E
75where
76 E::Target: BlockingExecutor + Sync,
77{
78 async fn spawn_blocking(&self, f: Box<dyn FnOnce() + Send + 'static>) {
79 self.deref().spawn_blocking(f).await
80 }
81}
82
83#[async_trait(?Send)]
85pub trait Task: Future<Output = ()> {
86 async fn cancel(self: Box<Self>) -> Option<()>;
91}