tokio_interceptor/
coeffects.rs

1// This file is part of tokio-interceptor.
2//
3// tokio-interceptor is free software: you can redistribute it and/or modify
4// it under the terms of the GNU Lesser General Public License as published by
5// the Free Software Foundation, either version 3 of the License, or
6// (at your option) any later version.
7//
8// tokio-interceptor is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11// GNU Lesser General Public License for more details.
12//
13// You should have received a copy of the GNU Lesser General Public License
14// along with tokio-interceptor.  If not, see <http://www.gnu.org/licenses/>.
15
16use std::any::Any;
17use std::marker::PhantomData;
18use std::rc::Rc;
19use std::sync::Arc;
20
21use futures::{future,Future};
22
23use super::{Context,Interceptor};
24
25pub trait Coeffect: Any {}
26
27impl<C: Coeffect + ?Sized> Coeffect for Arc<C> {}
28impl<C: Coeffect + ?Sized> Coeffect for Rc<C> {}
29impl<C: Coeffect + ?Sized> Coeffect for Box<C> {}
30
31pub trait NewCoeffect {
32    type Instance: Coeffect;
33
34    fn new_coeffect(&self) -> Self::Instance;
35}
36
37#[derive(Default)]
38pub struct InjectCoeffect<C, E>(C, PhantomData<E>);
39
40impl<C, E> InjectCoeffect<C, E>
41{
42    pub fn new(new_coeffect: C) -> InjectCoeffect<C, E> {
43        InjectCoeffect(new_coeffect, PhantomData)
44    }
45}
46
47impl<C, E> Interceptor for InjectCoeffect<C, E>
48where C: NewCoeffect,
49      E: 'static,
50{
51    type Error = E;
52
53    fn before(&self, mut context: Context<Self::Error>) -> Box<Future<Item = Context<Self::Error>,
54                                                                      Error = Self::Error>> {
55        context.coeffects.insert(self.0.new_coeffect());
56        Box::new(future::ok(context))
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    use std::rc::Rc;
65
66    use tests::{State,StateHolder};
67
68    #[test]
69    fn test_coeffect_interceptor() {
70        let context: Context<()> = Context::new(vec![]);
71        let state_holder = StateHolder(Rc::new(State(101)));
72        let i = InjectCoeffect::<StateHolder, ()>::new(state_holder);
73        let new_ctx = i.before(context).wait().unwrap();
74        assert_eq!(State(101), **new_ctx.coeffects.get::<Rc<State>>().unwrap());
75    }
76}