Skip to content

Commit

Permalink
add nightly feature enabling async closure as middleware
Browse files Browse the repository at this point in the history
  • Loading branch information
fakeshadow committed Nov 27, 2024
1 parent 3b005af commit f9da61d
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 0 deletions.
1 change: 1 addition & 0 deletions service/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ workspace = true
[features]
alloc = []
std = []
nightly = []

[dev-dependencies]
xitca-unsafe-collection = "0.2.0"
7 changes: 7 additions & 0 deletions service/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,15 @@
//! ```
#![no_std]
#![forbid(unsafe_code)]
#![cfg_attr(feature = "nightly", feature(async_closure))]

#[cfg(not(feature = "nightly"))]
mod async_fn;
#[cfg(feature = "nightly")]
mod async_fn {
pub use core::ops::AsyncFn;
}

mod service;

pub mod middleware;
Expand Down
15 changes: 15 additions & 0 deletions service/src/middleware/async_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ where
}
}

#[cfg(not(feature = "nightly"))]
impl<S, Req, F, Res, Err> Service<Req> for PipelineT<S, F, marker::AsyncFn>
where
F: for<'s> async_fn::AsyncFn<(&'s S, Req), Output = Result<Res, Err>>,
Expand All @@ -34,3 +35,17 @@ where
self.second.call((&self.first, req)).await
}
}

#[cfg(feature = "nightly")]
impl<S, Req, F, Res, Err> Service<Req> for PipelineT<S, F, marker::AsyncFn>
where
F: for<'s> async_fn::AsyncFn(&'s S, Req) -> Result<Res, Err>,
{
type Response = Res;
type Error = Err;

#[inline]
async fn call(&self, req: Req) -> Result<Self::Response, Self::Error> {
(self.second)(&self.first, req).await
}
}
31 changes: 31 additions & 0 deletions service/src/service/ext.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub trait ServiceExt<Arg>: Service<Arg> {
PipelineT::new(self, build)
}

#[cfg(not(feature = "nightly"))]
/// Function version of [Self::enclosed] method.
fn enclosed_fn<T, Req>(self, func: T) -> PipelineT<Self, middleware::AsyncFn<T>, marker::BuildEnclosed>
where
Expand All @@ -26,6 +27,16 @@ pub trait ServiceExt<Arg>: Service<Arg> {
self.enclosed(middleware::AsyncFn(func))
}

#[cfg(feature = "nightly")]
/// Function version of [Self::enclosed] method.
fn enclosed_fn<T, Req, O>(self, func: T) -> PipelineT<Self, middleware::AsyncFn<T>, marker::BuildEnclosed>
where
T: for<'s> async_fn::AsyncFn(&'s Self::Response, Req) -> O + Clone,
Self: Sized,
{
self.enclosed(middleware::AsyncFn(func))
}

/// Mutate `<<Self::Response as Service<Req>>::Future as Future>::Output` type with given
/// closure.
fn map<F, Res, ResMap>(self, mapper: F) -> PipelineT<Self, F, marker::BuildMap>
Expand Down Expand Up @@ -153,6 +164,26 @@ mod test {
assert_eq!(res, "251");
}

#[cfg(feature = "nightly")]
#[test]
fn enclosed_fn_async_closure() {
let res = fn_service(index)
.enclosed_fn(async |service, req| {
let res = service.call(req).now_or_panic()?;
assert_eq!(res, "996");
Ok::<_, ()>("251")
})
.call(())
.now_or_panic()
.unwrap()
.call("996")
.now_or_panic()
.ok()
.unwrap();

assert_eq!(res, "251");
}

#[cfg(feature = "alloc")]
#[test]
fn enclosed_opt() {
Expand Down

0 comments on commit f9da61d

Please sign in to comment.