product-os-async-executor 0.0.20

Product OS : Async Executor provides a set of tools to handle async execution generically so that the desired async library (e.g. tokio, smol) to be used can be chosen at compile time.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
//! # Product OS : Async Executor
//!
//! Product OS : Async Executor provides a set of tools to handle async execution generically
//! so that the desired async library (e.g. tokio, smol, async-std) can be chosen at compile time.
//!
//! ## Features
//!
//! - **Generic Executor Traits**: Define common interfaces for working with different async runtimes
//! - **Runtime Support**: Out-of-the-box support for Tokio, Smol, and Async-std
//! - **Timer Support**: One-time and interval timers that work across runtimes
//! - **Async I/O Traits**: `AsyncRead` and `AsyncWrite` traits for cross-runtime I/O
//! - **No-std Support**: Works in `no_std` environments with alloc
//!
//! ## Examples
//!
//! ### Using with Tokio
//!
//! ```rust,no_run
//! # #[cfg(feature = "exec_tokio")]
//! # {
//! use product_os_async_executor::{Executor, ExecutorPerform, TokioExecutor};
//!
//! #[tokio::main]
//! async fn main() {
//!     // Create an executor context
//!     let executor = TokioExecutor::context().await.unwrap();
//!     
//!     // Spawn a task
//!     let result = TokioExecutor::spawn_in_context(async {
//!         42
//!     }).await;
//!     
//!     assert!(result.is_ok());
//! }
//! # }
//! ```
//!
//! ### Using Timers
//!
//! ```rust,no_run
//! # #[cfg(feature = "exec_tokio")]
//! # {
//! use product_os_async_executor::{Timer, TokioExecutor};
//!
//! #[tokio::main]
//! async fn main() {
//!     let mut timer = TokioExecutor::interval(100).await;
//!     let _ = timer.tick().await; // Waits ~100ms
//! }
//! # }
//! ```
//!
//! ## Feature Flags
//!
//! - `exec_tokio`: Enable Tokio executor support
//! - `exec_smol`: Enable Smol executor support
//! - `exec_async_std`: Enable Async-std executor support (deprecated)
//! - `exec_embassy`: Enable Embassy executor support (embedded)
//! - `moment`: Enable time abstraction utilities
//! - `hyper_executor`: Enable Hyper executor integration
//!
#![no_std]
#![warn(missing_docs)]
#![warn(clippy::all)]
#![warn(clippy::pedantic)]
#![warn(clippy::nursery)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::must_use_candidate)]
#![allow(async_fn_in_trait)]

extern crate alloc;

#[cfg(feature = "exec_tokio")]
mod tokio;
#[cfg(feature = "exec_tokio")]
pub use tokio::TokioExecutor;

#[cfg(feature = "exec_smol")]
mod smol;
#[cfg(feature = "exec_smol")]
pub use smol::SmolExecutor;

#[cfg(feature = "exec_async_std")]
mod async_std;
#[cfg(feature = "exec_async_std")]
#[allow(deprecated)]
pub use async_std::AsyncStdExecutor;

#[cfg(feature = "exec_embassy")]
mod embassy;
#[cfg(feature = "exec_embassy")]
pub use embassy::EmbassyExecutor;

/// Async read/write traits for cross-runtime I/O operations.
///
/// This module provides `AsyncRead` and `AsyncWrite` traits that work across
/// different async runtimes, along with utilities for buffered I/O.
pub mod read_write;

/// Sleep trait for cross-runtime sleeping.
///
/// This module defines the `Sleep` trait which provides a runtime-agnostic
/// interface for sleeping. It is intended to be implemented by downstream
/// crates for their specific runtime.
pub mod sleep;

/// Time abstraction utilities for testable time operations.
///
/// The `Moment` struct allows you to abstract time operations, making it easier
/// to test code that depends on the current time.
pub mod moment;

use alloc::boxed::Box;
use alloc::sync::Arc;
use core::future::Future;
use core::pin::Pin;

// Specific chrono re-exports for common types
pub use chrono::Duration as ChronoDuration;
pub use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc};

/// Deprecated blanket re-export of the chrono crate.
///
/// Import chrono types directly from `chrono` or use the specific re-exports
/// from this crate's root (e.g. `DateTime`, `Utc`, `ChronoDuration`).
#[deprecated(
    since = "0.0.19",
    note = "Import chrono types directly from the `chrono` crate or use the specific re-exports (DateTime, Utc, ChronoDuration, etc.) from this crate's root."
)]
pub mod chrono_compat {
    pub use chrono::*;
}

pub use read_write::IoSlice;

/// Type alias for boxed error types that are Send + Sync.
///
/// This is used throughout the crate for error handling in async contexts.
pub type BoxError = alloc::boxed::Box<dyn core::error::Error + Send + Sync>;

/// Error type for spawn failures.
///
/// Returned when an executor is unable to spawn a task.
#[derive(Debug)]
pub struct SpawnError {
    _private: (),
}

impl SpawnError {
    /// Creates a new `SpawnError`.
    pub const fn new() -> Self {
        Self { _private: () }
    }
}

impl Default for SpawnError {
    fn default() -> Self {
        Self::new()
    }
}

impl core::fmt::Display for SpawnError {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "failed to spawn task")
    }
}

impl core::error::Error for SpawnError {}

/// Trait for managing executor contexts across different async runtimes.
///
/// This trait provides a unified interface for creating, configuring, and accessing
/// executor contexts regardless of the underlying async runtime (Tokio, Smol, etc.).
///
/// # Type Parameters
///
/// * `X` - The executor handle type specific to the runtime (e.g., `tokio::runtime::Handle`)
///
/// # Examples
///
/// ```rust,no_run
/// # #[cfg(feature = "exec_tokio")]
/// # {
/// use product_os_async_executor::{Executor, TokioExecutor};
///
/// #[tokio::main]
/// async fn main() {
///     let executor = TokioExecutor::context().await.unwrap();
///     executor.enter_context().await;
/// }
/// # }
/// ```
pub trait Executor<X>: Send + Sync {
    /// Creates a new executor context asynchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the executor context cannot be created.
    fn context() -> impl Future<Output = Result<Self, SpawnError>> + Send
    where
        Self: Sized;

    /// Sets the executor context to the provided executor.
    fn set_context(&mut self, executor: X) -> impl Future<Output = ()> + Send;

    /// Enters the executor context.
    ///
    /// Note: For some runtimes (e.g. Tokio), the context guard is dropped immediately,
    /// so this is primarily useful for runtimes that have global context state.
    fn enter_context(&self) -> impl Future<Output = ()> + Send;

    /// Gets a reference to the underlying executor.
    fn get_executor<'a>(&'a self) -> impl Future<Output = &'a X> + Send
    where
        X: 'a;

    /// Creates a new executor context synchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the executor context cannot be created.
    fn context_sync() -> Result<Self, SpawnError>
    where
        Self: Sized;

    /// Sets the executor context synchronously.
    fn set_context_sync(&mut self, executor: X);

    /// Enters the executor context synchronously.
    ///
    /// Note: For some runtimes (e.g. Tokio), the context guard is dropped immediately,
    /// so this is primarily useful for runtimes that have global context state.
    fn enter_context_sync(&self);

    /// Gets a reference to the underlying executor synchronously.
    fn get_executor_sync(&self) -> &X;
}

/// Trait for spawning and managing async tasks.
///
/// This trait provides methods for spawning tasks on an executor and blocking
/// on futures. It complements the `Executor` trait by focusing on task execution.
///
/// # Type Parameters
///
/// * `X` - The executor handle type
///
/// # Examples
///
/// ```rust,no_run
/// # #[cfg(feature = "exec_tokio")]
/// # {
/// use product_os_async_executor::{ExecutorPerform, TokioExecutor};
///
/// #[tokio::main]
/// async fn main() {
///     let task = TokioExecutor::spawn_in_context(async {
///         println!("Hello from spawned task!");
///         42
///     }).await;
///     
///     assert!(task.is_ok());
/// }
/// # }
/// ```
pub trait ExecutorPerform<X>: Send + Sync {
    /// Spawns a task in the current context asynchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the task cannot be spawned.
    fn spawn_in_context<F>(
        future: F,
    ) -> impl Future<Output = Result<Arc<dyn Task<F::Output, Output = F::Output>>, SpawnError>> + Send
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static;

    /// Spawns a task from an executor asynchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the task cannot be spawned.
    fn spawn_from_executor<E, F>(
        executor: &E,
        future: F,
    ) -> impl Future<Output = Result<Arc<dyn Task<F::Output, Output = F::Output>>, SpawnError>> + Send
    where
        E: Executor<X>,
        F: Future + Send + 'static,
        F::Output: Send + 'static;

    /// Blocks on a future using the executor.
    ///
    /// Blocks the current thread until the future completes.
    fn block_from_executor<E, F>(executor: &E, future: F) -> impl Future<Output = F::Output> + Send
    where
        E: Executor<X>,
        F: Future + Send + 'static,
        F::Output: Send + 'static;

    /// Spawns a task in the current context synchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the task cannot be spawned.
    fn spawn_in_context_sync<F>(
        future: F,
    ) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, SpawnError>
    where
        F: Future + Send + 'static,
        F::Output: Send + 'static;

    /// Spawns a task from an executor synchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the task cannot be spawned.
    fn spawn_from_executor_sync<E, F>(
        executor: &E,
        future: F,
    ) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, SpawnError>
    where
        E: Executor<X>,
        F: Future + Send + 'static,
        F::Output: Send + 'static;

    /// Blocks on a future using the executor synchronously.
    ///
    /// Blocks the current thread until the future completes.
    fn block_from_executor_sync<E, F>(executor: &E, future: F) -> F::Output
    where
        E: Executor<X>,
        F: Future + Send + 'static,
        F::Output: Send + 'static;
}

/// Trait for timer functionality across async runtimes.
///
/// Provides a unified interface for one-shot and interval timers that work
/// with any supported async runtime.
///
/// # Examples
///
/// ```rust,no_run
/// # #[cfg(feature = "exec_tokio")]
/// # {
/// use product_os_async_executor::{Timer, TokioExecutor};
///
/// #[tokio::main]
/// async fn main() {
///     // Create an interval timer that fires every 100ms
///     let mut timer = TokioExecutor::interval(100).await;
///     
///     // Wait for the first tick
///     let elapsed = timer.tick().await;
///     println!("Elapsed: {}ms", elapsed);
/// }
/// # }
/// ```
pub trait Timer: Send + Sync {
    /// Creates a one-shot timer that fires after the specified duration.
    fn once(duration_millis: u32) -> impl Future<Output = Self> + Send;

    /// Creates an interval timer that fires repeatedly at the specified interval.
    fn interval(duration_millis: u32) -> impl Future<Output = Self> + Send;

    /// Cancels the timer.
    fn cancel(&mut self) -> impl Future<Output = ()> + Send;

    /// Creates a one-shot timer synchronously.
    fn once_sync(duration_millis: u32) -> Self;

    /// Creates an interval timer synchronously.
    fn interval_sync(duration_millis: u32) -> Self;

    /// Cancels the timer synchronously.
    fn cancel_sync(&mut self);

    /// Waits for the next tick of the timer and returns elapsed milliseconds.
    fn tick(&mut self) -> impl Future<Output = u32> + Send;
}

/// Trait representing an async task that can be awaited.
///
/// This trait combines the `Future` trait with methods for managing task lifecycle.
///
/// # Type Parameters
///
/// * `Out` - The output type of the task
pub trait Task<Out>: Future
where
    Out: Send + 'static,
{
    /// Consumes the task and returns its output.
    fn output(self) -> Pin<Box<dyn Future<Output = Out> + Send>>;

    /// Detaches the task, allowing it to run independently.
    fn detach(self);

    /// Drops the task, cancelling it if not detached.
    fn drop(self);
}