1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
use futures::future;
use std::ops::{Deref, DerefMut};
use crate::{body::Body, configuration::Store, Extract, Response, RouteMatch};
pub type Request = http::Request<Body>;
pub trait Compute: 'static + Sync + Send + Clone + Sized {
fn compute_fresh(req: &mut Request) -> Self;
fn compute(req: &mut Request) -> Self {
if req.extensions().get::<ComputedMarker<Self>>().is_none() {
let t = Self::compute_fresh(req);
req.extensions_mut().insert(ComputedMarker(t));
}
req.extensions()
.get::<ComputedMarker<Self>>()
.unwrap()
.0
.clone()
}
}
struct ComputedMarker<T>(T);
#[derive(Clone)]
pub struct Computed<T>(pub T);
impl<T> Deref for Computed<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0
}
}
impl<T> DerefMut for Computed<T> {
fn deref_mut(&mut self) -> &mut T {
&mut self.0
}
}
impl<Data: 'static, T: Compute> Extract<Data> for Computed<T> {
type Fut = future::Ready<Result<Self, Response>>;
fn extract(
data: &mut Data,
req: &mut Request,
params: &Option<RouteMatch<'_>>,
store: &Store,
) -> Self::Fut {
future::ok(Computed(T::compute(req)))
}
}