spawns-compat 0.2.2

Async runtime detections for thread context task spawner
Documentation
use linkme::distributed_slice;
use spawns_core::{Compat, Task, COMPATS};
use std::boxed::Box;

#[distributed_slice(COMPATS)]
pub static TOKIO: Compat = Compat::Local(tokio_local);

fn tokio_spawn(task: Task) {
    let Task { future, .. } = task;
    let handle = tokio::runtime::Handle::current();
    handle.spawn(Box::into_pin(future));
}

fn tokio_local() -> Option<fn(Task)> {
    tokio::runtime::Handle::try_current()
        .ok()
        .map(|_| tokio_spawn as fn(Task))
}

#[cfg(test)]
#[cfg(feature = "tokio")]
mod tests {
    use spawns_core::*;

    #[tokio::test]
    async fn spawn_one() {
        let handle = spawn(async { 5 });
        let result = handle.await.unwrap();
        assert_eq!(result, 5);
    }

    #[tokio::test]
    async fn spawn_cascading() {
        #[allow(clippy::async_yields_async)]
        let handle = spawn(async { spawn(async { id() }) });
        let handle = handle.await.unwrap();
        let id = handle.id();
        assert_eq!(handle.await.unwrap(), id);
    }

    #[tokio::test]
    async fn spawn_interleaving() {
        #[allow(clippy::async_yields_async)]
        let handle = spawn(async { tokio::spawn(async { spawn(async { id() }) }) });
        let handle = handle.await.unwrap().await.unwrap();
        let id = handle.id();
        assert_eq!(handle.await.unwrap(), id);
    }

    #[tokio::test]
    async fn spawn_into_tokio() {
        #[allow(clippy::async_yields_async)]
        let handle = spawn(async { tokio::spawn(async { try_id() }) });
        let handle = handle.await.unwrap();
        assert_eq!(handle.await.unwrap(), None);
    }
}