1 use std::fmt;
2 use std::future::Future;
3 use std::pin::Pin;
4 use std::sync::Arc;
5
6 use futures::TryFutureExt;
7
8 use super::{Filter, FilterBase, Internal, Tuple};
9 use crate::reject::Rejection;
10
11 /// A type representing a boxed `Filter` trait object.
12 ///
13 /// The filter inside is a dynamic trait object. The purpose of this type is
14 /// to ease returning `Filter`s from other functions.
15 ///
16 /// To create one, call `Filter::boxed` on any filter.
17 ///
18 /// # Examples
19 ///
20 /// ```
21 /// use warp::{Filter, filters::BoxedFilter, Reply};
22 ///
23 /// pub fn assets_filter() -> BoxedFilter<(impl Reply,)> {
24 /// warp::path("assets")
25 /// .and(warp::fs::dir("./assets"))
26 /// .boxed()
27 /// }
28 /// ```
29 ///
30 pub struct BoxedFilter<T: Tuple> {
31 filter: Arc<
32 dyn Filter<
33 Extract = T,
34 Error = Rejection,
35 Future = Pin<Box<dyn Future<Output = Result<T, Rejection>> + Send>>,
36 > + Send
37 + Sync,
38 >,
39 }
40
41 impl<T: Tuple + Send> BoxedFilter<T> {
new<F>(filter: F) -> BoxedFilter<T> where F: Filter<Extract = T> + Send + Sync + 'static, F::Error: Into<Rejection>,42 pub(super) fn new<F>(filter: F) -> BoxedFilter<T>
43 where
44 F: Filter<Extract = T> + Send + Sync + 'static,
45 F::Error: Into<Rejection>,
46 {
47 BoxedFilter {
48 filter: Arc::new(BoxingFilter {
49 filter: filter.map_err(super::Internal, Into::into),
50 }),
51 }
52 }
53 }
54
55 impl<T: Tuple> Clone for BoxedFilter<T> {
clone(&self) -> BoxedFilter<T>56 fn clone(&self) -> BoxedFilter<T> {
57 BoxedFilter {
58 filter: self.filter.clone(),
59 }
60 }
61 }
62
63 impl<T: Tuple> fmt::Debug for BoxedFilter<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 f.debug_struct("BoxedFilter").finish()
66 }
67 }
68
_assert_send()69 fn _assert_send() {
70 fn _assert<T: Send>() {}
71 _assert::<BoxedFilter<()>>();
72 }
73
74 impl<T: Tuple + Send> FilterBase for BoxedFilter<T> {
75 type Extract = T;
76 type Error = Rejection;
77 type Future = Pin<Box<dyn Future<Output = Result<T, Rejection>> + Send>>;
78
filter(&self, _: Internal) -> Self::Future79 fn filter(&self, _: Internal) -> Self::Future {
80 self.filter.filter(Internal)
81 }
82 }
83
84 struct BoxingFilter<F> {
85 filter: F,
86 }
87
88 impl<F> FilterBase for BoxingFilter<F>
89 where
90 F: Filter,
91 F::Future: Send + 'static,
92 {
93 type Extract = F::Extract;
94 type Error = F::Error;
95 type Future = Pin<Box<dyn Future<Output = Result<Self::Extract, Self::Error>> + Send>>;
96
filter(&self, _: Internal) -> Self::Future97 fn filter(&self, _: Internal) -> Self::Future {
98 Box::pin(self.filter.filter(Internal).into_future())
99 }
100 }
101