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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use std::sync::Arc;

use super::{
    boxed::BoxServiceFactory, layer::FactoryLayer, ArcMakeService, BoxedMakeService, MakeService,
    MapTargetService, Service,
};

pub struct FactoryStack<C, S> {
    config: C,
    inner: S,
}

impl<C> FactoryStack<C, ()> {
    pub const fn new(config: C) -> Self {
        FactoryStack { config, inner: () }
    }
}

impl<C, F> FactoryStack<C, F> {
    /// Replace inner with a new factory.
    #[inline]
    pub fn replace<NF>(self, factory: NF) -> FactoryStack<C, NF> {
        FactoryStack {
            config: self.config,
            inner: factory,
        }
    }

    /// Push a new factory layer.
    #[inline]
    pub fn push<L>(self, layer: L) -> FactoryStack<C, L::Factory>
    where
        L: FactoryLayer<C, F>,
    {
        let inner = layer.layer(&self.config, self.inner);
        FactoryStack {
            config: self.config,
            inner,
        }
    }

    /// Push a new factory of service to map the request type.
    #[inline]
    pub fn push_map_target<M: Clone>(self, f: M) -> FactoryStack<C, MapTargetService<F, M>> {
        FactoryStack {
            config: self.config,
            inner: MapTargetService {
                f,
                inner: self.inner,
            },
        }
    }

    /// Push a new factory of BoxedService.
    #[inline]
    pub fn push_boxed_service<Req>(self) -> FactoryStack<C, BoxServiceFactory<F, Req>>
    where
        F: MakeService,
        F::Service: Service<Req>,
    {
        FactoryStack {
            config: self.config,
            inner: BoxServiceFactory::new(self.inner),
        }
    }

    /// Push a new factory wrapper to get a fixed type factory.
    #[inline]
    pub fn push_boxed_factory(self) -> FactoryStack<C, BoxedMakeService<F::Service, F::Error>>
    where
        F: MakeService + Send + Sync + 'static,
    {
        FactoryStack {
            config: self.config,
            inner: Box::new(self.inner),
        }
    }

    /// Push a new factory wrapper to get a fixed type factory.
    #[inline]
    pub fn push_arc_factory(self) -> FactoryStack<C, ArcMakeService<F::Service, F::Error>>
    where
        F: MakeService + Send + Sync + 'static,
    {
        FactoryStack {
            config: self.config,
            inner: Arc::new(self.inner),
        }
    }

    /// Check if the stack is a factory of Service<R>.
    #[inline]
    pub fn check_make_svc<R>(self) -> Self
    where
        F: MakeService,
        F::Service: Service<R>,
    {
        self
    }

    /// Get the inner factory.
    #[inline]
    pub fn into_inner(self) -> F {
        self.inner
    }

    /// Into config and the factory.
    #[inline]
    pub fn into_parts(self) -> (C, F) {
        (self.config, self.inner)
    }
}

impl<C, F> FactoryStack<C, F>
where
    F: MakeService,
{
    /// Make a service.
    #[inline]
    pub fn make(&self) -> Result<F::Service, F::Error> {
        self.inner.make()
    }
}