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}