#![cfg_attr(feature="DEBUG", doc = include_str!("../../README.md"))]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![allow(incomplete_features)]
#![cfg_attr(
feature = "nightly",
feature(specialization, try_trait_v2, impl_trait_in_assoc_type,)
)]
#![allow(
clippy::non_minimal_cfg, // for `cfg(any(...))` for various `rt_*` features
clippy::result_large_err, // TODO: reduce the size of `Response` (and also `Request`) (most parts are their headers!)
)]
#[cfg(any(
all(
feature = "rt_tokio",
any(
feature = "rt_smol",
feature = "rt_nio",
feature = "rt_glommio",
feature = "rt_monoio",
feature = "rt_compio",
feature = "rt_worker"
)
),
all(
feature = "rt_smol",
any(
feature = "rt_nio",
feature = "rt_glommio",
feature = "rt_monoio",
feature = "rt_compio",
feature = "rt_worker",
feature = "rt_tokio"
)
),
all(
feature = "rt_nio",
any(
feature = "rt_glommio",
feature = "rt_monoio",
feature = "rt_compio",
feature = "rt_worker",
feature = "rt_tokio",
feature = "rt_smol"
)
),
all(
feature = "rt_glommio",
any(
feature = "rt_monoio",
feature = "rt_compio",
feature = "rt_worker",
feature = "rt_tokio",
feature = "rt_smol",
feature = "rt_nio"
)
),
all(
feature = "rt_monoio",
any(
feature = "rt_compio",
feature = "rt_worker",
feature = "rt_tokio",
feature = "rt_smol",
feature = "rt_nio",
feature = "rt_glommio"
)
),
all(
feature = "rt_compio",
any(
feature = "rt_worker",
feature = "rt_tokio",
feature = "rt_smol",
feature = "rt_nio",
feature = "rt_glommio",
feature = "rt_monoio"
)
),
all(
feature = "rt_worker",
any(
feature = "rt_tokio",
feature = "rt_smol",
feature = "rt_nio",
feature = "rt_glommio",
feature = "rt_monoio",
feature = "rt_compio"
)
),
))]
compile_error! {"
Can't activate multiple `rt_*` features at once!
"}
#[cfg(feature = "__rt_native__")]
mod __rt__ {
#![allow(unused)]
#[cfg(feature = "__io_futures__")]
pub(crate) use futures_util::{AsyncReadExt as AsyncRead, AsyncWriteExt as AsyncWrite};
#[cfg(feature = "__io_tokio__")]
pub(crate) use tokio::io::{AsyncReadExt as AsyncRead, AsyncWriteExt as AsyncWrite};
#[cfg(feature = "rt_compio")]
pub(crate) use compio::net::{TcpListener, ToSocketAddrsAsync as ToSocketAddrs};
#[cfg(feature = "rt_smol")]
pub(crate) use smol::net::{AsyncToSocketAddrs as ToSocketAddrs, TcpListener, TcpStream};
#[cfg(feature = "rt_tokio")]
pub(crate) use tokio::net::{TcpListener, TcpStream, ToSocketAddrs};
#[cfg(feature = "rt_glommio")]
pub(crate) use {
glommio::net::{TcpListener, TcpStream},
std::net::ToSocketAddrs,
};
#[cfg(feature = "rt_monoio")]
pub(crate) use {
monoio::net::TcpListener, monoio_compat::TcpStreamCompat as TcpStream,
std::net::ToSocketAddrs,
};
#[cfg(feature = "rt_nio")]
pub(crate) use {
nio::net::{TcpListener, TcpStream},
std::net::ToSocketAddrs,
};
#[cfg(feature = "rt_compio")]
pub(crate) type TcpStream = compio::io::compat::AsyncStream<compio::net::TcpStream>;
#[cfg(not(feature = "rt_nio"))]
#[inline(always)]
pub(crate) async fn accept(
listener: &TcpListener,
) -> std::io::Result<(TcpStream, std::net::SocketAddr)> {
#[cfg(any(feature = "rt_tokio", feature = "rt_smol"))]
{
listener.accept().await
}
#[cfg(any(feature = "rt_glommio"))]
{
let connection = listener.accept().await?;
let addr = connection.peer_addr()?;
Ok((connection, addr))
}
#[cfg(any(feature = "rt_monoio", feature = "rt_compio"))]
{
let (conn, addr) = listener.accept().await?;
Ok((TcpStream::new(conn), addr))
}
}
pub trait IntoTcpListener<T> {
fn into_tcp_listener(self) -> impl Future<Output = TcpListener>;
}
impl IntoTcpListener<()> for TcpListener {
async fn into_tcp_listener(self) -> TcpListener {
self
}
}
impl<A: ToSocketAddrs> IntoTcpListener<A> for A {
async fn into_tcp_listener(self) -> TcpListener {
let binded = TcpListener::bind(self);
#[cfg(not(any(feature = "rt_glommio", feature = "rt_monoio")))]
let binded = binded.await;
binded.expect("Failed to bind TCP listener")
}
}
#[cfg(feature = "rt_tokio")]
pub(crate) use tokio::time::sleep;
#[cfg(feature = "rt_smol")]
pub(crate) async fn sleep(duration: std::time::Duration) {
smol::Timer::after(duration).await;
}
#[cfg(feature = "rt_compio")]
pub(crate) use compio::runtime::time::sleep;
#[cfg(feature = "rt_glommio")]
pub(crate) use glommio::timer::sleep;
#[cfg(feature = "rt_monoio")]
pub(crate) use monoio::time::sleep;
#[cfg(feature = "rt_nio")]
pub(crate) use nio::sleep;
#[cfg(feature = "__rt_threaded__")]
mod task {
pub trait Task: std::future::Future<Output: Send + 'static> + Send + 'static {}
impl<F: std::future::Future<Output: Send + 'static> + Send + 'static> Task for F {}
}
#[cfg(not(feature = "__rt_threaded__"))]
mod task {
pub trait Task: std::future::Future + 'static {}
impl<F: std::future::Future + 'static> Task for F {}
}
pub(crate) fn spawn(task: impl task::Task) {
#[cfg(feature = "rt_tokio")]
tokio::task::spawn(task);
#[cfg(feature = "rt_smol")]
smol::spawn(task).detach();
#[cfg(feature = "rt_glommio")]
glommio::spawn_local(task).detach();
#[cfg(feature = "rt_monoio")]
monoio::spawn(task);
#[cfg(feature = "rt_compio")]
compio::runtime::spawn(task).detach();
}
#[cfg(test)]
pub(crate) mod testing {
pub(crate) fn block_on<F: Future>(future: F) -> F::Output {
#[cfg(feature = "rt_tokio")]
return tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.unwrap()
.block_on(future);
#[cfg(feature = "rt_smol")]
return smol::block_on(future);
#[cfg(feature = "rt_nio")]
return nio::RuntimeBuilder::new().build().unwrap().block_on(future);
#[cfg(feature = "rt_glommio")]
return glommio::LocalExecutor::default().run(future);
#[cfg(feature = "rt_monoio")]
return monoio::RuntimeBuilder::<monoio::FusionDriver>::new()
.enable_all()
.build()
.unwrap()
.block_on(future);
#[cfg(feature = "rt_compio")]
return compio::runtime::Runtime::new().unwrap().block_on(future);
}
pub(crate) const PORT: u16 = {
#[cfg(feature = "rt_tokio")]
{
3001
}
#[cfg(feature = "rt_smol")]
{
3003
}
#[cfg(feature = "rt_nio")]
{
3004
}
#[cfg(feature = "rt_glommio")]
{
3005
}
#[cfg(feature = "rt_monoio")]
{
3006
}
#[cfg(feature = "rt_compio")]
{
3007
}
};
}
}
pub mod util;
mod config;
pub use config::Config;
#[cfg(debug_assertions)]
#[cfg(feature = "__rt__")]
pub mod testing;
pub mod request;
pub use ::ohkami_macros::FromRequest;
pub use request::{FromRequest, Method, Request};
mod response;
pub use response::{IntoResponse, Response, Status};
#[cfg(feature = "__rt_native__")]
mod session;
#[cfg(feature = "__rt__")]
mod router;
#[cfg(feature = "__rt__")]
mod ohkami;
#[cfg(feature = "__rt__")]
pub use ohkami::{Ohkami, Route};
pub mod fang;
pub use fang::{Fang, FangAction, FangProc, handler};
pub mod header;
pub mod claw;
pub use claw::{Cookie, Json, Path, Query};
#[cfg(feature = "sse")]
#[cfg_attr(docsrs, doc(cfg(feature = "sse")))]
pub mod sse;
#[cfg(feature = "ws")]
#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
pub mod ws;
#[cfg(feature = "rt_lambda")]
mod x_lambda;
#[cfg(feature = "rt_worker")]
mod x_worker;
#[cfg(feature = "rt_worker")]
pub use x_worker::*;
pub mod prelude {
pub use crate::fang::Context;
pub use crate::serde::{Deserialize, Serialize};
pub use crate::util::FangAction;
pub use crate::{IntoResponse, Json, Method, Path, Query, Request, Response, Status};
#[cfg(feature = "__rt__")]
pub use crate::{Ohkami, Route};
}
pub mod serde {
pub use ::ohkami_macros::{Deserialize, Serialize};
pub use ::serde::de::{self, Deserialize, Deserializer};
pub use ::serde::ser::{self, Serialize, Serializer};
pub use ::serde_json as json;
}
#[cfg(feature = "openapi")]
#[cfg_attr(docsrs, doc(cfg(feature = "openapi")))]
pub mod openapi {
pub use ::ohkami_macros::{Schema, operation};
pub use ::ohkami_openapi::document::Server;
pub use ::ohkami_openapi::*;
#[cfg(feature = "__rt__")]
#[derive(Clone)]
pub struct OpenAPI<'s> {
pub title: &'static str,
pub version: &'static str,
pub servers: &'s [Server],
}
pub struct Tag(pub &'static str);
impl<I: crate::FangProc> crate::Fang<I> for Tag {
type Proc = I;
fn chain(&self, inner: I) -> Self::Proc {
inner
}
fn openapi_map_operation(&self, operation: Operation) -> Operation {
operation.with_tag(self.0)
}
}
}
#[doc(hidden)]
pub mod __internal__ {
pub use ::serde;
pub use ohkami_macros::consume_struct;
pub use crate::fang::Fangs;
#[cfg(feature = "DEBUG")]
pub use crate::{
request::{RequestHeader, RequestHeaders},
response::{ResponseHeader, ResponseHeaders},
};
}