Skip to main content

tower_livereload/
predicate.rs

1//! Predicates for matching HTTP responses and requests.
2//!
3//! Note that in addition to the predicates exported by this module,
4//! [`Predicate`] is also implemented for `Fn(&T) -> bool + Copy`,
5//! which is useful for quickly constructing an arbitrary predicate.
6use http::{header, Response};
7
8/// Trait for predicates that check if a value matches them.
9pub trait Predicate<T>: Copy {
10    /// Check if the predicate matches the given value.
11    fn check(&mut self, thing: &T) -> bool;
12}
13
14/// A predicate that matches based on [`Content-Type`] header.
15///
16/// [`Content-Type`]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type
17#[derive(Copy, Clone, Debug)]
18pub struct ContentTypeStartsWith<Patt>(Patt);
19
20impl<Patt: AsRef<str> + Copy> ContentTypeStartsWith<Patt> {
21    /// Create a new [`ContentTypeStartsWith`] predicate.
22    pub fn new(pattern: Patt) -> Self {
23        ContentTypeStartsWith(pattern)
24    }
25}
26
27impl<T, Patt: AsRef<str> + Copy> Predicate<Response<T>> for ContentTypeStartsWith<Patt> {
28    fn check(&mut self, response: &Response<T>) -> bool {
29        response
30            .headers()
31            .get(header::CONTENT_TYPE)
32            .and_then(|val| val.to_str().ok().map(|s| s.starts_with(self.0.as_ref())))
33            .unwrap_or(false)
34    }
35}
36
37/// A predicate that matches any request or response.
38#[derive(Copy, Clone, Debug)]
39pub struct Always;
40
41impl<T> Predicate<T> for Always {
42    fn check(&mut self, _thing: &T) -> bool {
43        true
44    }
45}
46
47impl<T, F> Predicate<T> for F
48where
49    F: Fn(&T) -> bool + Copy,
50{
51    fn check(&mut self, thing: &T) -> bool {
52        (self)(thing)
53    }
54}