product-os-async-executor 0.0.18

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
//! # 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
//! - `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)]

extern crate no_std_compat as std;
extern crate alloc;

use std::prelude::v1::*;


#[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;

/// 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.
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;

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

use async_trait::async_trait;
use std::sync::Arc;
use std::future::Future;

pub use chrono::*;
pub use ioslice::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 = Box<dyn core_error::Error + Send + Sync>;


/// 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;
/// }
/// # }
/// ```
#[async_trait]
pub trait Executor<X>: Send + Sync
{
    /// Creates a new executor context asynchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the executor context cannot be created.
    async fn context() -> Result<Self, futures_task::SpawnError>
    where
        Self: Sized;

    /// Sets the executor context to the provided executor.
    async fn set_context(&mut self, executor: X);

    /// Enters the executor context.
    async fn enter_context(&self);

    /// Gets a reference to the underlying executor.
    async fn get_executor(&self) -> &X;

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

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

    /// Enters the executor context synchronously.
    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());
/// }
/// # }
/// ```
#[async_trait]
pub trait ExecutorPerform<X>: Send + Sync
{
    /// Spawns a task in the current context asynchronously.
    ///
    /// # Errors
    ///
    /// Returns an error if the task cannot be spawned.
    async fn spawn_in_context<F>(future: F) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, futures_task::SpawnError>
        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.
    async fn spawn_from_executor<E, F>(executor: &E, future: F) -> Result<Arc<dyn Task<F::Output, Output = F::Output>>, futures_task::SpawnError>
        where
            E: Executor<X>,
            F: Future + Send + 'static,
            F::Output: Send + 'static;

    /// Blocks on a future using the executor.
    ///
    /// This method blocks the current thread until the future completes.
    async fn block_from_executor<E, F>(executor: &E, future: F) -> F::Output
        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>>, futures_task::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>>, futures_task::SpawnError>
        where
            E: Executor<X>,
            F: Future + Send + 'static,
            F::Output: Send + 'static;

    /// Blocks on a future using the executor synchronously.
    ///
    /// This method 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);
/// }
/// # }
/// ```
#[async_trait]
pub trait Timer: Send + Sync {
    /// Creates a one-shot timer that fires after the specified duration.
    async fn once(duration_millis: u32) -> Self;
    
    /// Creates an interval timer that fires repeatedly at the specified interval.
    async fn interval(duration_millis: u32) -> Self;

    /// Cancels the timer.
    async fn cancel(&mut self);

    /// 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.
    async fn tick(&mut self) -> u32;
}


/// 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
#[async_trait]
pub trait Task<Out>: Future
where
    Out: Send + 'static
{
    /// Consumes the task and returns its output.
    async fn output(self) -> Out;
    
    /// Detaches the task, allowing it to run independently.
    fn detach(self);
    
    /// Drops the task, cancelling it if not detached.
    fn drop(self);
}