//!
@@ -28,16 +28,12 @@
#[cfg(any(
- all(feature="rt_tokio", feature="rt_async-std"),
- all(feature="rt_tokio", feature="rt_smol"),
- all(feature="rt_tokio", feature="rt_glommio"),
- all(feature="rt_tokio", feature="rt_worker"),
- all(feature="rt_async-std", feature="rt_smol"),
- all(feature="rt_async-std", feature="rt_glommio"),
- all(feature="rt_async-std", feature="rt_worker"),
- all(feature="rt_smol", feature="rt_glommio"),
- all(feature="rt_smol", feature="rt_worker"),
- all(feature="rt_glommio", feature="rt_worker"),
+ all(feature="rt_tokio", any(feature="rt_async-std", feature="rt_smol", feature="rt_nio", feature="rt_glommio", feature="rt_worker" )),
+ all(feature="rt_async-std", any(feature="rt_smol", feature="rt_nio", feature="rt_glommio", feature="rt_worker", feature="rt_tokio" )),
+ all(feature="rt_smol", any(feature="rt_nio", feature="rt_glommio", feature="rt_worker", feature="rt_tokio", feature="rt_async-std")),
+ all(feature="rt_nio", any(feature="rt_glommio", feature="rt_worker", feature="rt_tokio", feature="rt_async-std", feature="rt_smol" )),
+ all(feature="rt_glommio", any(feature="rt_worker", feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio" )),
+ all(feature="rt_worker", any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio", feature="rt_glommio" )),
))] compile_error! {"
Can't activate multiple `rt_*` features at once!
"}
@@ -62,13 +58,15 @@ mod __rt__ {
pub(crate) use async_std::net::{TcpListener, TcpStream, ToSocketAddrs};
#[cfg(feature="rt_smol")]
pub(crate) use smol::net::{TcpListener, TcpStream, AsyncToSocketAddrs as ToSocketAddrs};
+ #[cfg(feature="rt_nio")]
+ pub(crate) use {nio::net::{TcpListener, TcpStream}, std::net::ToSocketAddrs};
#[cfg(feature="rt_glommio")]
pub(crate) use {glommio::net::{TcpListener, TcpStream}, std::net::ToSocketAddrs};
pub(crate) async fn bind(address: impl ToSocketAddrs) -> TcpListener {
let binded = TcpListener::bind(address);
- #[cfg(any(feature="rt_tokio",feature="rt_async-std",feature="rt_smol"))]
+ #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio"))]
let binded = binded.await;
binded.expect("Failed to bind TCP listener")
@@ -82,6 +80,8 @@ mod __rt__ {
pub(crate) async fn sleep(duration: std::time::Duration) {
smol::Timer::after(duration).await;
}
+ #[cfg(feature="rt_nio")]
+ pub(crate) use nio::time::sleep;
#[cfg(feature="rt_glommio")]
pub(crate) use glommio::timer::sleep;
@@ -91,6 +91,8 @@ mod __rt__ {
pub(crate) use async_std::io::ReadExt as AsyncRead;
#[cfg(feature="rt_smol")]
pub(crate) use futures_util::AsyncReadExt as AsyncRead;
+ #[cfg(feature="rt_nio")]
+ pub(crate) use tokio::io::AsyncReadExt as AsyncRead;
#[cfg(feature="rt_glommio")]
pub(crate) use futures_util::AsyncReadExt as AsyncRead;
@@ -100,6 +102,8 @@ mod __rt__ {
pub(crate) use async_std::io::WriteExt as AsyncWrite;
#[cfg(feature="rt_smol")]
pub(crate) use futures_util::AsyncWriteExt as AsyncWrite;
+ #[cfg(feature="rt_nio")]
+ pub(crate) use tokio::io::AsyncWriteExt as AsyncWrite;
#[cfg(feature="rt_glommio")]
pub(crate) use futures_util::AsyncWriteExt as AsyncWrite;
@@ -109,10 +113,12 @@ mod __rt__ {
pub(crate) use futures_util::select;
#[cfg(feature="rt_smol")]
pub(crate) use futures_util::select;
+ #[cfg(feature="rt_nio")]
+ pub(crate) use tokio::select;
#[cfg(feature="rt_glommio")]
pub(crate) use futures_util::select;
- #[cfg(any(feature="rt_tokio"))]
+ #[cfg(any(feature="rt_tokio", feature="rt_nio"))]
pub(crate) const fn selectable
(future: F) -> F {
future
}
@@ -121,7 +127,7 @@ mod __rt__ {
::futures_util::FutureExt::fuse(future)
}
- #[cfg(any(feature="rt_tokio",feature="rt_async-std",feature="rt_smol"))]
+ #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio"))]
mod task {
pub trait Task: std::future::Future + Send + 'static {}
impl + Send + 'static> Task for F {}
@@ -141,27 +147,45 @@ mod __rt__ {
#[cfg(feature="rt_smol")]
smol::spawn(task).detach();
+ #[cfg(feature="rt_nio")]
+ nio::spawn(task);
+
#[cfg(feature="rt_glommio")]
glommio::spawn_local(task).detach();
}
- #[cfg(feature="testing")]
- #[cfg(test)]
- pub(crate) fn block_on(future: impl std::future::Future) {
- #[cfg(feature="rt_tokio")]
- tokio::runtime::Builder::new_current_thread()
- .enable_all()
- .build().unwrap()
- .block_on(future);
-
- #[cfg(feature="rt_async-std")]
- async_std::task::block_on(future);
-
- #[cfg(feature="rt_smol")]
- smol::block_on(future);
-
- #[cfg(feature="rt_glommio")]
- glommio::LocalExecutor::default().run(future);
+ #[cfg(all(test, feature="testing"))]
+ pub(crate) mod testing {
+ pub(crate) fn block_on(future: impl std::future::Future) {
+ #[cfg(feature="rt_tokio")]
+ tokio::runtime::Builder::new_current_thread()
+ .enable_all()
+ .build().unwrap()
+ .block_on(future);
+
+ #[cfg(feature="rt_async-std")]
+ async_std::task::block_on(future);
+
+ #[cfg(feature="rt_smol")]
+ smol::block_on(future);
+
+ #[cfg(feature="rt_nio")]
+ nio::runtime::Builder::new_multi_thread()
+ .enable_all()
+ .build().unwrap()
+ .block_on(future);
+
+ #[cfg(feature="rt_glommio")]
+ glommio::LocalExecutor::default().run(future);
+ }
+
+ pub(crate) const PORT: u16 = {
+ #[cfg(feature="rt_tokio") ] {3001}
+ #[cfg(feature="rt_async-std")] {3002}
+ #[cfg(feature="rt_smol") ] {3003}
+ #[cfg(feature="rt_nio") ] {3004}
+ #[cfg(feature="rt_glommio") ] {3005}
+ };
}
}
diff --git a/ohkami/src/ohkami/mod.rs b/ohkami/src/ohkami/mod.rs
index e9f2ef4e..6d8abd62 100644
--- a/ohkami/src/ohkami/mod.rs
+++ b/ohkami/src/ohkami/mod.rs
@@ -14,7 +14,7 @@ use std::sync::Arc;
#[cfg(feature="__rt_native__")]
use crate::{__rt__, Session};
-/// # Ohkami - a robust wolf who serves your web app
+/// # Ohkami - a smart wolf who serves your web app
///
///
///
@@ -105,8 +105,9 @@ use crate::{__rt__, Session};
/// `async ({path_params}?, {FromRequest type}s...) -> {IntoResponse type}`
///
/// #### path_params:
-/// A tuple of types that implement `FromParam` trait.\
-/// If the path contains only one parameter, then you can omit the tuple.\
+/// A tuple of types that implement `FromParam` trait e.g. `(&str, usize)`.\
+/// If the path contains only one parameter, then you can omit the tuple \
+/// e.g. just `param: &str`.\
/// (In current ohkami, at most *2* path params can be handled.)
///
///
@@ -248,7 +249,7 @@ impl Ohkami {
/// - `tokio::net::ToSocketAddrs` if using `tokio`
/// - `async_std::net::ToSocketAddrs` if using `async-std`
/// - `smol::net::AsyncToSocketAddrs` if using `smol`
- /// - `std::net::ToSocketAddrs` if using `glommio`
+ /// - `std::net::ToSocketAddrs` if using `nio` or `glommio`
///
/// *note* : Keep-Alive timeout is 42 seconds and this is not
/// configureable by user (it'll be in future version...)
@@ -313,7 +314,7 @@ impl Ohkami {
__rt__::select! {
accept = __rt__::selectable(listener.accept()) => {
let (connection, addr) = {
- #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol"))] {
+ #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio"))] {
let Ok((connection, addr)) = accept else {continue};
(connection, addr)
}
@@ -453,12 +454,12 @@ mod sync {
use std::task::{Context, Poll, Waker};
use std::pin::Pin;
- #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol"))]
+ #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio"))]
use std::{sync::atomic::AtomicPtr, ptr::null_mut};
#[cfg(any(feature="rt_glommio"))]
use std::sync::Mutex;
- #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol"))]
+ #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio"))]
static WAKER: AtomicPtr = AtomicPtr::new(null_mut());
#[cfg(any(feature="rt_glommio"))]
static WAKER: Mutex> = Mutex::new(Vec::new());
@@ -477,7 +478,7 @@ mod sync {
crate::DEBUG!("[CtrlC::catch] Ready");
Poll::Ready(())
} else {
- #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol"))] {
+ #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio"))] {
let prev_waker = WAKER.swap(
Box::into_raw(Box::new(cx.waker().clone())),
Ordering::SeqCst
@@ -502,7 +503,7 @@ mod sync {
}
pub fn new() -> Self {
- #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol"))]
+ #[cfg(any(feature="rt_tokio", feature="rt_async-std", feature="rt_smol", feature="rt_nio"))]
::ctrlc::set_handler(|| {
CATCH.store(true, Ordering::SeqCst);
let waker = WAKER.swap(null_mut(), Ordering::SeqCst);
@@ -530,10 +531,10 @@ mod sync {
#[cfg(all(feature="testing", feature="__rt_native__"))]
#[cfg(test)]
#[test] fn can_howl_on_any_native_async_runtime() {
- __rt__::block_on(async {
+ __rt__::testing::block_on(async {
crate::util::timeout_in(
std::time::Duration::from_secs(3),
- Ohkami::new(()).howl("localhost:3000")
+ Ohkami::new(()).howl(("localhost", __rt__::testing::PORT))
).await
});
}