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
65
66
67
68
69
70
71
mod redirect;

use std::marker::PhantomData;

use actix_service::Service;

pub use self::redirect::Redirect;

/// Trait for transform a type to another one.
/// Both the input and output type should impl [actix_service::Service] trait.
pub trait Transform<S, Req> {
    type Transform: Service<Req>;

    /// Creates and returns a new Transform component.
    fn new_transform(self, service: S) -> Self::Transform;
}

#[doc(hidden)]
/// Helper struct for constructing Nested types that would call `Transform::new_transform`
/// in a chain.
///
/// The child field would be called first and the output `Service` type is
/// passed to parent as input type.
pub struct NestTransform<T1, T2, S, Req>
where
    T1: Transform<S, Req>,
    T2: Transform<T1::Transform, Req>,
{
    child: T1,
    parent: T2,
    _service: PhantomData<(S, Req)>,
}

impl<T1, T2, S, Req> NestTransform<T1, T2, S, Req>
where
    T1: Transform<S, Req>,
    T2: Transform<T1::Transform, Req>,
{
    pub(crate) fn new(child: T1, parent: T2) -> Self {
        NestTransform {
            child,
            parent,
            _service: PhantomData,
        }
    }
}

impl<T1, T2, S, Req> Transform<S, Req> for NestTransform<T1, T2, S, Req>
where
    T1: Transform<S, Req>,
    T2: Transform<T1::Transform, Req>,
{
    type Transform = T2::Transform;

    fn new_transform(self, service: S) -> Self::Transform {
        let service = self.child.new_transform(service);
        self.parent.new_transform(service)
    }
}

/// Dummy impl for kick start `NestTransform` type in `ClientBuilder` type
impl<S, Req> Transform<S, Req> for ()
where
    S: Service<Req>,
{
    type Transform = S;

    fn new_transform(self, service: S) -> Self::Transform {
        service
    }
}