diff --git a/tower/CHANGELOG.md b/tower/CHANGELOG.md index 5bdc7e3da..af16b8c07 100644 --- a/tower/CHANGELOG.md +++ b/tower/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 # Unreleased +### Added + +- **util**: Add `Wrap` for wrapping a `Service` with pre/post functions + ### Changed - **util**: Removed deprecated `ServiceExt::ready_and` method and `ReadyAnd` diff --git a/tower/src/builder/mod.rs b/tower/src/builder/mod.rs index 33684137d..c02a6bdce 100644 --- a/tower/src/builder/mod.rs +++ b/tower/src/builder/mod.rs @@ -808,6 +808,76 @@ impl<L> ServiceBuilder<L> { { self.layer(crate::util::BoxCloneService::layer()) } + + /// Wraps the inner service with async pre/post functions. + /// + /// The `pre` function is any function that looks like + /// <code>async [FnMut]\(Request) -> [Result]<(SRequest, T), [Result]<Response, Err>></code> + /// where `Request` is the request given to the `Wrap` service. + /// + /// * If this function outputs <code>[Ok]\((SRequest, T))</code> the `SRequest` is passed to + /// the inner service and the `T` is retained as shared state. When the inner service outputs + /// a result, this result is passed to `post` along with the shared `T`. + /// * If this function returns <code>[Err]\(result)</code> the result is output by the `Wrap` + /// service without calling the inner service or the `post` function. + /// + /// The `post` function is any function that looks like + /// <code>async [FnOnce]\(Res, T) -> [Result]<Response, Err></code> where `Res` is the result + /// returned by the inner service, `T` is the shared state provided by `pre`, and `Response` + /// and `Err` match the types used in `pre`. The returned [`Result`] is the overall result from + /// the wrapped service. + /// + /// See the documentation for the [`decorate` combinator][] for examples. + /// + /// See also [`wrap`](Self::wrap) for when you just need to share state across the inner + /// service and don't need asynchronous functions or short-circuiting. + /// + /// [`decorate` combinator]: crate::util::ServiceExt::decorate + #[cfg(feature = "util")] + #[cfg_attr(docsrs, doc(cfg(feature = "util")))] + pub fn decorate<Pre, Post>( + self, + pre: Pre, + post: Post, + ) -> ServiceBuilder<Stack<crate::util::WrapLayer<Pre, Post>, L>> + where + Self: Sized, + { + self.layer(crate::util::WrapLayer::decorate(pre, post)) + } + + /// Wraps the inner service with a synchronous pre function that returns a post function. + /// + /// The given function is any function that looks like + /// <code>[FnMut]\(&mut Request) -> [FnOnce]\(Response) -> T</code> where `Request` is the + /// request given to the `Wrap` service, `Response` is the response returned from the inner + /// service, and `T` is the response returned from the `Wrap` service. If the inner service + /// returns an error the error is output directly without being given to the post function. + /// + /// See the documentation for the [`wrap` combinator][] for examples. + /// + /// [`wrap` combinator]: crate::util::ServiceExt::wrap + #[cfg(feature = "util")] + #[cfg_attr(docsrs, doc(cfg(feature = "util")))] + pub fn wrap<F, F2, Request, Response, T, E>( + self, + f: F, + ) -> ServiceBuilder< + Stack< + crate::util::WrapLayer< + crate::util::helper::Pre<Request, T, E, F>, + crate::util::helper::Post<F2, E>, + >, + L, + >, + > + where + Self: Sized, + F: FnMut(&mut Request) -> F2, + F2: FnOnce(Response) -> T, + { + self.layer(crate::util::WrapLayer::new(f)) + } } impl<L: fmt::Debug> fmt::Debug for ServiceBuilder<L> { diff --git a/tower/src/util/mod.rs b/tower/src/util/mod.rs index dddf8ed7a..eb0f7abbd 100644 --- a/tower/src/util/mod.rs +++ b/tower/src/util/mod.rs @@ -18,6 +18,7 @@ mod optional; mod ready; mod service_fn; mod then; +mod wrap; pub use self::{ and_then::{AndThen, AndThenLayer}, @@ -35,6 +36,7 @@ pub use self::{ ready::{Ready, ReadyOneshot}, service_fn::{service_fn, ServiceFn}, then::{Then, ThenLayer}, + wrap::{Wrap, WrapLayer}, }; pub use self::call_all::{CallAll, CallAllUnordered}; @@ -58,6 +60,13 @@ pub mod future { pub use super::map_result::MapResultFuture; pub use super::optional::future as optional; pub use super::then::ThenFuture; + pub use super::wrap::{WrapFuture, WrapPostFuture, WrapPreFuture}; +} + +pub mod helper { + //! Helper types + + pub use super::wrap::{Post, PostFn, Pre, PreFn}; } /// An extension trait for `Service`s that provides a variety of convenient @@ -1036,6 +1045,145 @@ pub trait ServiceExt<Request>: tower_service::Service<Request> { { BoxCloneService::new(self) } + + /// Wraps this service with async pre/post functions. + /// + /// The `pre` function is any function that looks like + /// <code>async [FnMut]\(Request) -> [Result]<(SRequest, T), [Result]<Response, Err>></code> + /// where `Request` is the request given to the `Wrap` service. + /// + /// * If this function outputs <code>[Ok]\((SRequest, T))</code> the `SRequest` is passed to + /// the inner service and the `T` is retained as shared state. When the inner service outputs + /// a result, this result is passed to `post` along with the shared `T`. + /// * If this function returns <code>[Err]\(result)</code> the result is output by the `Wrap` + /// service without calling the inner service or the `post` function. + /// + /// The `post` function is any function that looks like + /// <code>async [FnOnce]\(Res, T) -> [Result]<Response, Err></code> where `Res` is the result + /// returned by the inner service, `T` is the shared state provided by `pre`, and `Response` + /// and `Err` match the types used in `pre`. The returned [`Result`] is the overall result from + /// the wrapped service. + /// + /// See also [`wrap`](Self::wrap) for when you just need to share state across the inner + /// service and don't need asynchronous functions or short-circuiting. + /// + /// # Examples + /// + /// Adding a cache in front of a service: + /// + /// ```rust + /// use tower::{Service, ServiceExt}; + /// use std::collections::HashMap; + /// use std::sync::{Arc, Mutex}; + /// # #[derive(Clone, PartialEq, Eq, Hash)] struct Request; + /// # impl Request { fn new(_: &str) -> Self { Request }} + /// # #[derive(Clone)] struct Response; + /// + /// # fn main() { + /// # async { + /// // A service returning Result<Response, Error> + /// let service = /* ... */ + /// # tower::service_fn(|_: Request| async { Ok::<_, ()>(Response) }); + /// + /// // Wrap the service in a cache for successful responses + /// let cache = Arc::new(Mutex::new(HashMap::new())); + /// let mut new_service = service.decorate( + /// { + /// let cache = cache.clone(); + /// move |req: Request| std::future::ready( + /// cache.lock().unwrap().get(&req).cloned().map_or_else( + /// || Ok((req.clone(), req)), + /// |response| Err(Ok(response))), + /// ) + /// }, + /// move |res: Result<Response, _>, req| async move { + /// if let Ok(ref val) = res { + /// cache.lock().unwrap().insert(req, val.clone()); + /// } + /// res + /// }, + /// ); + /// + /// // Call the new service + /// let request = Request::new("cats"); + /// let response = new_service + /// .ready() + /// .await? + /// .call(request) + /// .await?; + /// # Ok::<(), ()>(()) + /// # }; + /// # } + /// ``` + fn decorate<Pre, Post>(self, pre: Pre, post: Post) -> Wrap<Self, Pre, Post> + where + Self: Sized, + { + Wrap::decorate(self, pre, post) + } + + /// Wraps this service with a synchronous pre function that returns a post function. + /// + /// The given function is any function that looks like + /// <code>[FnMut]\(&mut Request) -> [FnOnce]\(Response) -> T</code> where `Request` is the + /// request given to the `Wrap` service, `Response` is the response returned from the inner + /// service, and `T` is the response returned from the `Wrap` service. If the inner service + /// returns an error the error is output directly without being given to the post function. + /// + /// # Examples + /// + /// Attaching a unique identifier to the request and response: + /// + /// ```rust + /// use tower::{Service, ServiceExt}; + /// # #[derive(Clone)] struct UUID; + /// # impl UUID { fn new() -> Self { UUID } } + /// # struct Request; + /// # impl Request { + /// # fn new(_: &str) -> Self { Request } + /// # fn set_identifier(&mut self, _: UUID) {} + /// # } + /// # struct Response; + /// # impl Response { fn set_identifier(&mut self, _: UUID) {} } + /// + /// # fn main() { + /// # async { + /// // A service returning Result<Response, Error> + /// let service = /* ... */ + /// # tower::service_fn(|_: Request| async { Ok::<_, ()>(Response) }); + /// + /// // Attach a unique identifier to each request and response + /// let mut new_service = service.wrap(|req| { + /// let uuid = UUID::new(); + /// req.set_identifier(uuid.clone()); + /// move |mut res| { + /// res.set_identifier(uuid); + /// res + /// } + /// }); + /// + /// // Call the new service + /// let request = Request::new("cats"); + /// let response = new_service + /// .ready() + /// .await? + /// .call(request) + /// .await?; + /// # Ok::<(), ()>(()) + /// # }; + /// # } + /// ``` + fn wrap<F, F2, T>( + self, + f: F, + ) -> Wrap<Self, wrap::Pre<Request, T, Self::Error, F>, wrap::Post<F2, Self::Error>> + where + Self: Sized, + F: FnMut(&mut Request) -> F2, + F2: FnOnce(Self::Response) -> T, + { + Wrap::new(self, f) + } } impl<T: ?Sized, Request> ServiceExt<Request> for T where T: tower_service::Service<Request> {} diff --git a/tower/src/util/wrap.rs b/tower/src/util/wrap.rs new file mode 100644 index 000000000..e3e8595e7 --- /dev/null +++ b/tower/src/util/wrap.rs @@ -0,0 +1,460 @@ +//! Middleware that decorates a [`Service`] with pre/post functions. + +use std::{fmt, future::Future, marker::PhantomData, pin::Pin, task::Poll}; + +use futures_core::ready; +use pin_project_lite::pin_project; +use tower_layer::Layer; +use tower_service::Service; + +/// Middleware that decorates a [`Service`] with pre/post functions. +/// +/// Service returned by the [`wrap`] and [`decorate`] combinators. +/// +/// [`wrap`]: fn@crate::util::ServiceExt::wrap +/// [`decorate`]: fn@crate::util::ServiceExt::decorate +#[derive(Clone)] +pub struct Wrap<S, Pre, Post> { + inner: S, + pre: Pre, + post: Post, +} + +impl<S, F, F2> Wrap<S, F, F2> { + /// Creates a new `Wrap` service with separate async pre/post functions. + /// + /// The `pre` function is any function that looks like + /// <code>async [FnMut]\(Request) -> [Result]<(SRequest, T), [Result]<Response, Err>></code> + /// where `Request` is the request given to the `Wrap` service. + /// + /// * If this function outputs <code>[Ok]\((SRequest, T))</code> the `SRequest` is passed to + /// the inner service and the `T` is retained as shared state. When the inner service outputs + /// a result, this result is passed to `post` along with the shared `T`. + /// * If this function returns <code>[Err]\(result)</code> the result is output by the `Wrap` + /// service without calling the inner service or the `post` function. + /// + /// The `post` function is any function that looks like + /// <code>async [FnOnce]\(Res, T) -> [Result]<Response, Err></code> where `Res` is the result + /// returned by the inner service, `T` is the shared state provided by `pre`, and `Response` + /// and `Err` match the types used in `pre`. The returned [`Result`] is the overall result from + /// the wrapped service. + /// + /// See the documentation for the [`decorate` combinator][] for examples. + /// + /// See also [`new`](Self::new) for when you just need to share state across the inner service + /// and don't need asynchronous functions or short-circuiting. + /// + /// [`decorate` combinator]: crate::util::ServiceExt::decorate + pub fn decorate(inner: S, pre: F, post: F2) -> Self { + Self { inner, pre, post } + } + + /// Creates a new `Wrap` service with a synchronous pre function that returns a post function. + /// + /// The given function is any function that looks like + /// <code>[FnMut]\(&mut Request) -> [FnOnce]\(Response) -> T</code> where `Request` is the + /// request given to the `Wrap` service, `Response` is the response returned from the inner + /// service, and `T` is the response returned from the `Wrap` service. If the inner service + /// returns an error the error is output directly without being given to the post function. + /// + /// See the documentation for the [`wrap` combinator][] for examples. + /// + /// [`wrap` combinator]: crate::util::ServiceExt::wrap + pub fn new<Request, T>( + inner: S, + f: F, + ) -> Wrap<S, Pre<Request, T, S::Error, F>, Post<F2, S::Error>> + where + F: FnMut(&mut Request) -> F2, + F2: FnOnce(S::Response) -> T, + S: Service<Request>, + { + Wrap { + inner, + pre: Pre { + f, + _marker: PhantomData, + }, + post: Post { + _marker: PhantomData, + }, + } + } +} + +impl<F, F2> Wrap<(), F, F2> { + /// Returns a new [`Layer`] that produces [`Wrap`] services. + /// + /// This is a convenience function that simply calls [`WrapLayer::new`]. + pub fn layer<Request, Response, T, E>(f: F) -> WrapLayer<Pre<Request, T, E, F>, Post<F2, E>> + where + F: FnMut(&mut Request) -> F2, + F2: FnOnce(Response) -> T, + { + WrapLayer::new(f) + } +} + +/// A [`Layer`] that produces a [`Wrap`] service. +#[derive(Clone)] +pub struct WrapLayer<Pre, Post> { + pre: Pre, + post: Post, +} + +impl<F, F2> WrapLayer<F, F2> { + /// Creates a new `WrapLayer` layer with separate async pre/post functions. + /// + /// The `pre` function is any function that looks like + /// <code>async [FnMut]\(Request) -> [Result]<(SRequest, T), [Result]<Response, Err>></code> + /// where `Request` is the request given to the `Wrap` service. + /// + /// * If this function outputs <code>[Ok]\((SRequest, T))</code> the `SRequest` is passed to + /// the inner service and the `T` is retained as shared state. When the inner service outputs + /// a result, this result is passed to `post` along with the shared `T`. + /// * If this function returns <code>[Err]\(result)</code> the result is output by the `Wrap` + /// service without calling the inner service or the `post` function. + /// + /// The `post` function is any function that looks like + /// <code>async [FnOnce]\(Res, T) -> [Result]<Response, Err></code> where `Res` is the result + /// returned by the inner service, `T` is the shared state provided by `pre`, and `Response` + /// and `Err` match the types used in `pre`. The returned [`Result`] is the overall result from + /// the wrapped service. + /// + /// See the documentation for the [`decorate` combinator][] for examples. + /// + /// See also [`new`](Self::new) for when you just need to share state across the inner service + /// and don't need asynchronous functions or short-circuiting. + /// + /// [`decorate` combinator]: crate::util::ServiceExt::decorate + pub fn decorate(pre: F, post: F2) -> Self { + Self { pre, post } + } + + /// Creates a new `WrapLayer` layer with a synchronous pre function that returns a post + /// function. + /// + /// The given function is any function that looks like + /// <code>[FnMut]\(&mut Request) -> [FnOnce]\(Response) -> T</code> where `Request` is the + /// request given to the `Wrap` service, `Response` is the response returned from the inner + /// service, and `T` is the response returned from the `Wrap` service. If the inner service + /// returns an error the error is output directly without being given to the post function. + /// + /// See the documentation for the [`wrap` combinator][] for examples. + /// + /// [`wrap` combinator]: crate::util::ServiceExt::wrap + pub fn new<Request, Response, T, E>(f: F) -> WrapLayer<Pre<Request, T, E, F>, Post<F2, E>> + where + F: FnMut(&mut Request) -> F2, + F2: FnOnce(Response) -> T, + { + WrapLayer { + pre: Pre { + f, + _marker: PhantomData, + }, + post: Post { + _marker: PhantomData, + }, + } + } +} + +impl<S, Pre, Post> Layer<S> for WrapLayer<Pre, Post> +where + Pre: Clone, + Post: Clone, +{ + type Service = Wrap<S, Pre, Post>; + + fn layer(&self, inner: S) -> Self::Service { + Wrap { + inner, + pre: self.pre.clone(), + post: self.post.clone(), + } + } +} + +impl<S, Req, Pre, Post, Res, E> Service<Req> for Wrap<S, Pre, Post> +where + Pre: PreFn<Req, Response = Res, Error = E>, + S: Service<Pre::Request> + Clone, + S::Error: Into<E>, + Post: PostFn<S::Response, S::Error, Pre::Value, Response = Res, Error = E> + Clone, +{ + type Response = Res; + type Error = E; + type Future = WrapFuture<S, S::Future, Pre::Future, Post, Post::Future, Pre::Value>; + + fn poll_ready(&mut self, cx: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> { + self.inner.poll_ready(cx).map_err(Into::into) + } + + fn call(&mut self, req: Req) -> Self::Future { + WrapFuture { + state: State::Pre { + future: self.pre.call(req), + inner: self.inner.clone(), + post: self.post.clone(), + }, + } + } +} + +pin_project! { + /// Response future for [`Wrap`]. + pub struct WrapFuture<S, SFut, PreFut, Post, PostFut, T> { + #[pin] + state: State<S, SFut, PreFut, Post, PostFut, T>, + } +} + +pin_project! { + #[project = StateProj] + #[project_replace = StateOwned] + enum State<S, SFut, PreFut, Post, PostFut, T> { + Pre { + #[pin] + future: PreFut, + inner: S, + post: Post + }, + Inner { + #[pin] + future: SFut, + post: Post, + value: T, + }, + Post { + #[pin] + future: PostFut, + }, + Complete + } +} + +impl<S, SReq, PreFut, Res, E, Post, T> Future + for WrapFuture<S, S::Future, PreFut, Post, Post::Future, T> +where + PreFut: Future<Output = Result<(SReq, T), Result<Res, E>>>, + S: Service<SReq>, + S::Error: Into<E>, + Post: PostFn<S::Response, S::Error, T, Response = Res, Error = E>, +{ + type Output = Result<Res, E>; + + fn poll(mut self: Pin<&mut Self>, cx: &mut std::task::Context<'_>) -> Poll<Self::Output> { + Poll::Ready(loop { + let mut state = self.as_mut().project().state; + match state.as_mut().project() { + StateProj::Pre { future, .. } => match ready!(future.poll(cx)) { + Ok((req, value)) => match state.as_mut().project_replace(State::Complete) { + StateOwned::Pre { + mut inner, post, .. + } => state.set(State::Inner { + future: inner.call(req), + post, + value, + }), + _ => unreachable!(), + }, + Err(res) => { + state.set(State::Complete); + break res.map_err(Into::into); + } + }, + StateProj::Inner { future, .. } => { + let result = ready!(future.poll(cx)); + match state.as_mut().project_replace(State::Complete) { + StateOwned::Inner { post, value, .. } => state.set(State::Post { + future: post.call(result, value), + }), + _ => unreachable!(), + } + } + StateProj::Post { future } => { + let res = ready!(future.poll(cx)); + state.set(State::Complete); + break res; + } + StateProj::Complete => { + panic!("WrapFuture must not be polled after it returned `Poll::Ready`") + } + } + }) + } +} + +/// A trait that represents pre functions for use with [`Wrap`]. +/// +/// This is implemented for all +/// <code>async [FnMut]\(Req) -> [Result]<(SReq, T), [Result]<Response, Err>></code> where `SReq` +/// is the request type passed to the inner service, `T` is the shared state passed to the +/// [`PostFn`], and <code>[Result]<Response, Err></code> is a short-circuit result that bypasses +/// the wrapped service and post-fn. +pub trait PreFn<Req> { + /// Requests passed to the inner service. + type Request; + /// Shared values passed to the [`PostFn`]. + type Value; + /// Responses given by the service. + /// + /// This matches the corresponding [`PostFn::Response`]. + type Response; + /// Errors produced by the service. + /// + /// This matches the corresponding [`PostFn::Error`]. + type Error; + /// The future result used to either call the inner service or short-circuit. + type Future: Future< + Output = Result<(Self::Request, Self::Value), Result<Self::Response, Self::Error>>, + >; + + /// Invokes the function. + fn call(&mut self, request: Req) -> Self::Future; +} + +impl<F, Req, T, Fut, SReq, Res, Err> PreFn<Req> for F +where + F: FnMut(Req) -> Fut, + Fut: Future<Output = Result<(SReq, T), Result<Res, Err>>>, +{ + type Request = SReq; + type Value = T; + type Response = Res; + type Error = Err; + type Future = Fut; + + fn call(&mut self, request: Req) -> Self::Future { + self(request) + } +} + +/// A trait that represents post functions for use with [`Wrap`]. +/// +/// This is implemented for all +/// <code>async [FnMut]\([Result]<Res, E>, T) -> [Result]<Response, Error></code> where +/// <code>[Result]<Res, E></code> is the output from the inner service, `T` is the shared state +/// returned from the [`PreFn`], and <code>[Result]<Response, Error></code> is the overall result +/// from the wrapped service. +pub trait PostFn<Res, E, T> { + /// Responses given by the service. + type Response; + /// Errors produced by the service. + type Error; + /// The future response value. + type Future: Future<Output = Result<Self::Response, Self::Error>>; + + /// Invokes the function. + fn call(self, result: Result<Res, E>, value: T) -> Self::Future; +} + +impl<F, Res, E, T, Fut, Ok, Err> PostFn<Res, E, T> for F +where + F: FnOnce(Result<Res, E>, T) -> Fut, + Fut: Future<Output = Result<Ok, Err>>, +{ + type Response = Ok; + type Error = Err; + type Future = Fut; + + fn call(self, result: Result<Res, E>, value: T) -> Self::Future { + self(result, value) + } +} + +/// Helper type for use with [`Wrap::new`]. +/// +/// This type is an adaptor from [`Wrap::new`]'s synchronous pre function to the more generic +/// asynchronous failable pre function given to [`Wrap::decorate`]. +#[allow(missing_debug_implementations)] +pub struct Pre<Req, Res, E, F> { + f: F, + _marker: PhantomData<fn(Req) -> (Req, Res, E)>, +} + +impl<F, Req, Post, Res, E> PreFn<Req> for Pre<Req, Res, E, F> +where + F: FnMut(&mut Req) -> Post, +{ + type Request = Req; + type Value = Post; + type Response = Res; + type Error = E; + type Future = WrapPreFuture<Req, Post, Res, E>; + + fn call(&mut self, mut request: Req) -> Self::Future { + let f2 = (self.f)(&mut request); + WrapPreFuture::new(futures_util::future::ready(Ok((request, f2)))) + } +} + +opaque_future! { + /// Future returned by the [`PreFn`] impl for [`Pre`]. + pub type WrapPreFuture<Req, Post, Res, E> = + futures_util::future::Ready<Result<(Req, Post), Result<Res, E>>>; +} + +/// Helper type for use with [`Wrap::new`]. +/// +/// This type is an adaptor from [`Wrap::new`]'s synchronous post function to the more generic +/// asynchronous failable post function given to [`Wrap::decorate`]. +#[allow(missing_debug_implementations)] +pub struct Post<F, E> { + _marker: PhantomData<fn(F, E) -> E>, +} + +impl<F, Res, E, T> PostFn<Res, E, F> for Post<F, E> +where + F: FnOnce(Res) -> T, +{ + type Response = T; + type Error = E; + type Future = WrapPostFuture<T, E>; + + fn call(self, result: Result<Res, E>, value: F) -> Self::Future { + WrapPostFuture::new(futures_util::future::ready(result.map(value))) + } +} + +opaque_future! { + /// Future returned by the [`PostFn`] impl for [`Post`]. + pub type WrapPostFuture<T, E> = futures_util::future::Ready<Result<T, E>>; +} + +impl<S: fmt::Debug, Pre, Post> fmt::Debug for Wrap<S, Pre, Post> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Wrap") + .field("inner", &self.inner) + .field("pre", &format_args!("{}", std::any::type_name::<Pre>())) + .field("post", &format_args!("{}", std::any::type_name::<Post>())) + .finish() + } +} + +impl<Pre, Post> fmt::Debug for WrapLayer<Pre, Post> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("WrapLayer") + .field("pre", &format_args!("{}", std::any::type_name::<Pre>())) + .field("post", &format_args!("{}", std::any::type_name::<Post>())) + .finish() + } +} + +impl<Req, Res, E, F: Clone> Clone for Pre<Req, Res, E, F> { + fn clone(&self) -> Self { + Self { + f: self.f.clone(), + _marker: PhantomData, + } + } +} + +impl<F, E> Clone for Post<F, E> { + fn clone(&self) -> Self { + Self { + _marker: PhantomData, + } + } +}