gotham/router/route/matcher/and.rs
1//! Defines the type `AndRouteMatcher`
2
3use crate::router::non_match::RouteNonMatch;
4use crate::router::route::RouteMatcher;
5use crate::state::State;
6
7/// Allows multiple `RouteMatcher` values to be combined when accessing a request.
8///
9/// # Examples
10///
11/// ```rust
12/// # fn main() {
13/// # use hyper::Method;
14/// # use hyper::header::{HeaderMap, ACCEPT};
15/// # use gotham::state::State;
16/// # use gotham::router::route::matcher::{RouteMatcher, MethodOnlyRouteMatcher, AndRouteMatcher, AcceptHeaderRouteMatcher};
17/// #
18/// # State::with_new(|state| {
19/// #
20/// let methods = vec![Method::GET, Method::HEAD];
21/// let supported_media_types = vec![mime::APPLICATION_JSON];
22/// let method_matcher = MethodOnlyRouteMatcher::new(methods);
23/// let accept_matcher = AcceptHeaderRouteMatcher::new(supported_media_types);
24/// let matcher = AndRouteMatcher::new(method_matcher, accept_matcher);
25///
26/// state.put(Method::GET);
27///
28/// // Request that matches both requirements
29/// let mut headers = HeaderMap::new();
30/// headers.insert(ACCEPT, mime::APPLICATION_JSON.to_string().parse().unwrap());
31/// state.put(headers);
32/// assert!(matcher.is_match(&state).is_ok());
33///
34/// // Request that fails method requirements
35/// state.put(Method::POST);
36/// assert!(matcher.is_match(&state).is_err());
37///
38/// // Request that fails accept header
39/// state.put(Method::GET);
40/// let mut headers = HeaderMap::new();
41/// headers.insert(ACCEPT, mime::TEXT.to_string().parse().unwrap());
42/// state.put(headers);
43/// assert!(matcher.is_match(&state).is_err());
44/// #
45/// # });
46/// # }
47/// ```
48#[derive(Clone)]
49pub struct AndRouteMatcher<T, U>
50where
51 T: RouteMatcher,
52 U: RouteMatcher,
53{
54 t: T,
55 u: U,
56}
57
58impl<T, U> AndRouteMatcher<T, U>
59where
60 T: RouteMatcher,
61 U: RouteMatcher,
62{
63 /// Creates a new `AndRouteMatcher`
64 pub fn new(t: T, u: U) -> Self {
65 AndRouteMatcher { t, u }
66 }
67}
68
69impl<T, U> RouteMatcher for AndRouteMatcher<T, U>
70where
71 T: RouteMatcher,
72 U: RouteMatcher,
73{
74 fn is_match(&self, state: &State) -> Result<(), RouteNonMatch> {
75 match (self.t.is_match(state), self.u.is_match(state)) {
76 (Ok(_), Ok(_)) => Ok(()),
77 (Err(e), Ok(_)) => Err(e),
78 (Ok(_), Err(e)) => Err(e),
79 (Err(e), Err(e1)) => Err(e.intersection(e1)),
80 }
81 }
82}