1#![cfg_attr(feature="DEBUG", doc = include_str!("../../README.md"))]
3
4#![cfg_attr(docsrs, feature(doc_cfg))]
18#![allow(incomplete_features)]
19#![cfg_attr(
20 feature = "nightly",
21 feature(specialization, try_trait_v2, impl_trait_in_assoc_type,)
22)]
23#![allow(
24 clippy::non_minimal_cfg, clippy::result_large_err, )]
27
28#[cfg(any(
29 all(
30 feature = "rt_tokio",
31 any(
32 feature = "rt_smol",
33 feature = "rt_nio",
34 feature = "rt_glommio",
35 feature = "rt_monoio",
36 feature = "rt_compio",
37 feature = "rt_worker"
38 )
39 ),
40 all(
41 feature = "rt_smol",
42 any(
43 feature = "rt_nio",
44 feature = "rt_glommio",
45 feature = "rt_monoio",
46 feature = "rt_compio",
47 feature = "rt_worker",
48 feature = "rt_tokio"
49 )
50 ),
51 all(
52 feature = "rt_nio",
53 any(
54 feature = "rt_glommio",
55 feature = "rt_monoio",
56 feature = "rt_compio",
57 feature = "rt_worker",
58 feature = "rt_tokio",
59 feature = "rt_smol"
60 )
61 ),
62 all(
63 feature = "rt_glommio",
64 any(
65 feature = "rt_monoio",
66 feature = "rt_compio",
67 feature = "rt_worker",
68 feature = "rt_tokio",
69 feature = "rt_smol",
70 feature = "rt_nio"
71 )
72 ),
73 all(
74 feature = "rt_monoio",
75 any(
76 feature = "rt_compio",
77 feature = "rt_worker",
78 feature = "rt_tokio",
79 feature = "rt_smol",
80 feature = "rt_nio",
81 feature = "rt_glommio"
82 )
83 ),
84 all(
85 feature = "rt_compio",
86 any(
87 feature = "rt_worker",
88 feature = "rt_tokio",
89 feature = "rt_smol",
90 feature = "rt_nio",
91 feature = "rt_glommio",
92 feature = "rt_monoio"
93 )
94 ),
95 all(
96 feature = "rt_worker",
97 any(
98 feature = "rt_tokio",
99 feature = "rt_smol",
100 feature = "rt_nio",
101 feature = "rt_glommio",
102 feature = "rt_monoio",
103 feature = "rt_compio"
104 )
105 ),
106))]
107compile_error! {"
108 Can't activate multiple `rt_*` features at once!
109"}
110
111#[cfg(feature = "__rt_native__")]
112mod __rt__ {
113 #![allow(unused)]
114
115 #[cfg(feature = "__io_futures__")]
116 pub(crate) use futures_util::{AsyncReadExt as AsyncRead, AsyncWriteExt as AsyncWrite};
117 #[cfg(feature = "__io_tokio__")]
118 pub(crate) use tokio::io::{AsyncReadExt as AsyncRead, AsyncWriteExt as AsyncWrite};
119
120 #[cfg(feature = "rt_compio")]
121 pub(crate) use compio::net::{TcpListener, ToSocketAddrsAsync as ToSocketAddrs};
122 #[cfg(feature = "rt_smol")]
123 pub(crate) use smol::net::{AsyncToSocketAddrs as ToSocketAddrs, TcpListener, TcpStream};
124 #[cfg(feature = "rt_tokio")]
125 pub(crate) use tokio::net::{TcpListener, TcpStream, ToSocketAddrs};
126 #[cfg(feature = "rt_glommio")]
127 pub(crate) use {
128 glommio::net::{TcpListener, TcpStream},
129 std::net::ToSocketAddrs,
130 };
131 #[cfg(feature = "rt_monoio")]
132 pub(crate) use {
133 monoio::net::TcpListener, monoio_compat::TcpStreamCompat as TcpStream,
134 std::net::ToSocketAddrs,
135 };
136 #[cfg(feature = "rt_nio")]
137 pub(crate) use {
138 nio::net::{TcpListener, TcpStream},
139 std::net::ToSocketAddrs,
140 };
141
142 #[cfg(feature = "rt_compio")]
143 pub(crate) type TcpStream = compio::io::compat::AsyncStream<compio::net::TcpStream>;
144
145 #[cfg(not(feature = "rt_nio"))]
146 #[inline(always)]
147 pub(crate) async fn accept(
148 listener: &TcpListener,
149 ) -> std::io::Result<(TcpStream, std::net::SocketAddr)> {
150 #[cfg(any(feature = "rt_tokio", feature = "rt_smol"))]
151 {
152 listener.accept().await
153 }
154 #[cfg(any(feature = "rt_glommio"))]
155 {
156 let connection = listener.accept().await?;
157 let addr = connection.peer_addr()?;
158 Ok((connection, addr))
159 }
160 #[cfg(any(feature = "rt_monoio", feature = "rt_compio"))]
161 {
162 let (conn, addr) = listener.accept().await?;
163 Ok((TcpStream::new(conn), addr))
164 }
165 }
166
167 pub trait IntoTcpListener<T> {
168 fn into_tcp_listener(self) -> impl Future<Output = TcpListener>;
169 }
170 impl IntoTcpListener<()> for TcpListener {
171 async fn into_tcp_listener(self) -> TcpListener {
172 self
173 }
174 }
175 impl<A: ToSocketAddrs> IntoTcpListener<A> for A {
176 async fn into_tcp_listener(self) -> TcpListener {
177 let binded = TcpListener::bind(self);
178
179 #[cfg(not(any(feature = "rt_glommio", feature = "rt_monoio")))]
180 let binded = binded.await;
181
182 binded.expect("Failed to bind TCP listener")
183 }
184 }
185
186 #[cfg(feature = "rt_tokio")]
187 pub(crate) use tokio::time::sleep;
188 #[cfg(feature = "rt_smol")]
189 pub(crate) async fn sleep(duration: std::time::Duration) {
190 smol::Timer::after(duration).await;
191 }
192 #[cfg(feature = "rt_compio")]
193 pub(crate) use compio::runtime::time::sleep;
194 #[cfg(feature = "rt_glommio")]
195 pub(crate) use glommio::timer::sleep;
196 #[cfg(feature = "rt_monoio")]
197 pub(crate) use monoio::time::sleep;
198 #[cfg(feature = "rt_nio")]
199 pub(crate) use nio::sleep;
200
201 #[cfg(feature = "__rt_threaded__")]
202 mod task {
203 pub trait Task: std::future::Future<Output: Send + 'static> + Send + 'static {}
204 impl<F: std::future::Future<Output: Send + 'static> + Send + 'static> Task for F {}
205 }
206 #[cfg(not(feature = "__rt_threaded__"))]
207 mod task {
208 pub trait Task: std::future::Future + 'static {}
209 impl<F: std::future::Future + 'static> Task for F {}
210 }
211
212 pub(crate) fn spawn(task: impl task::Task) {
213 #[cfg(feature = "rt_tokio")]
214 tokio::task::spawn(task);
215
216 #[cfg(feature = "rt_smol")]
217 smol::spawn(task).detach();
218
219 #[cfg(feature = "rt_glommio")]
220 glommio::spawn_local(task).detach();
221
222 #[cfg(feature = "rt_monoio")]
223 monoio::spawn(task);
224
225 #[cfg(feature = "rt_compio")]
226 compio::runtime::spawn(task).detach();
227 }
228
229 #[cfg(test)]
230 pub(crate) mod testing {
231 pub(crate) fn block_on<F: Future>(future: F) -> F::Output {
232 #[cfg(feature = "rt_tokio")]
233 return tokio::runtime::Builder::new_current_thread()
234 .enable_all()
235 .build()
236 .unwrap()
237 .block_on(future);
238
239 #[cfg(feature = "rt_smol")]
240 return smol::block_on(future);
241
242 #[cfg(feature = "rt_nio")]
243 return nio::RuntimeBuilder::new().build().unwrap().block_on(future);
244
245 #[cfg(feature = "rt_glommio")]
246 return glommio::LocalExecutor::default().run(future);
247
248 #[cfg(feature = "rt_monoio")]
249 return monoio::RuntimeBuilder::<monoio::FusionDriver>::new()
250 .enable_all()
251 .build()
252 .unwrap()
253 .block_on(future);
254
255 #[cfg(feature = "rt_compio")]
256 return compio::runtime::Runtime::new().unwrap().block_on(future);
257 }
258
259 pub(crate) const PORT: u16 = {
260 #[cfg(feature = "rt_tokio")]
261 {
262 3001
263 }
264 #[cfg(feature = "rt_smol")]
265 {
266 3003
267 }
268 #[cfg(feature = "rt_nio")]
269 {
270 3004
271 }
272 #[cfg(feature = "rt_glommio")]
273 {
274 3005
275 }
276 #[cfg(feature = "rt_monoio")]
277 {
278 3006
279 }
280 #[cfg(feature = "rt_compio")]
281 {
282 3007
283 }
284 };
285 }
286}
287
288pub mod util;
289
290mod config;
291pub use config::Config;
292
293#[cfg(debug_assertions)]
294#[cfg(feature = "__rt__")]
295pub mod testing;
296
297pub mod request;
298pub use ::ohkami_macros::FromRequest;
299pub use request::{FromRequest, Method, Request};
300
301mod response;
302pub use response::{IntoResponse, Response, Status};
303
304#[cfg(feature = "__rt_native__")]
305mod session;
306
307#[cfg(feature = "__rt__")]
308mod router;
309
310#[cfg(feature = "__rt__")]
311mod ohkami;
312#[cfg(feature = "__rt__")]
313pub use ohkami::{Ohkami, Route};
314
315pub mod fang;
316pub use fang::{Fang, FangAction, FangProc, handler};
317
318pub mod header;
319
320pub mod claw;
321pub use claw::{Cookie, Json, Path, Query};
322
323#[cfg(feature = "sse")]
324#[cfg_attr(docsrs, doc(cfg(feature = "sse")))]
325pub mod sse;
326
327#[cfg(feature = "ws")]
328#[cfg_attr(docsrs, doc(cfg(feature = "ws")))]
329pub mod ws;
330
331#[cfg(feature = "rt_lambda")]
332mod x_lambda;
333#[cfg(feature = "rt_worker")]
339mod x_worker;
340#[cfg(feature = "rt_worker")]
341pub use x_worker::*;
342
343pub mod prelude {
344 pub use crate::fang::Context;
345 pub use crate::serde::{Deserialize, Serialize};
346 pub use crate::util::FangAction;
347 pub use crate::{IntoResponse, Json, Method, Path, Query, Request, Response, Status};
348
349 #[cfg(feature = "__rt__")]
350 pub use crate::{Ohkami, Route};
351}
352
353pub mod serde {
379 pub use ::ohkami_macros::{Deserialize, Serialize};
380 pub use ::serde::de::{self, Deserialize, Deserializer};
381 pub use ::serde::ser::{self, Serialize, Serializer};
382 pub use ::serde_json as json;
383}
384
385#[cfg(feature = "openapi")]
386#[cfg_attr(docsrs, doc(cfg(feature = "openapi")))]
387pub mod openapi {
389 pub use ::ohkami_macros::{Schema, operation};
390 pub use ::ohkami_openapi::document::Server;
391 pub use ::ohkami_openapi::*;
392
393 #[cfg(feature = "__rt__")]
394 #[derive(Clone)]
395 pub struct OpenAPI<'s> {
396 pub title: &'static str,
397 pub version: &'static str,
398 pub servers: &'s [Server],
399 }
400
401 pub struct Tag(pub &'static str);
436 impl<I: crate::FangProc> crate::Fang<I> for Tag {
437 type Proc = I;
439 fn chain(&self, inner: I) -> Self::Proc {
440 inner
441 }
442
443 fn openapi_map_operation(&self, operation: Operation) -> Operation {
445 operation.with_tag(self.0)
446 }
447 }
448}
449
450#[doc(hidden)]
451pub mod __internal__ {
452 pub use ::serde;
453
454 pub use ohkami_macros::consume_struct;
455
456 pub use crate::fang::Fangs;
457
458 #[cfg(feature = "DEBUG")]
460 pub use crate::{
461 request::{RequestHeader, RequestHeaders},
462 response::{ResponseHeader, ResponseHeaders},
463 };
464}