rocket/fairing/
fairings.rs

1use crate::{Rocket, Request, Response, Data, Build, Orbit};
2use crate::fairing::{Fairing, Info, Kind};
3
4#[derive(Default)]
5pub struct Fairings {
6    // NOTE: This is a push-only vector due to the index-vectors below!
7    all_fairings: Vec<Box<dyn Fairing>>,
8    // Ignite fairings that have failed.
9    failures: Vec<Info>,
10    // The number of ignite fairings from `self.ignite` we've run.
11    num_ignited: usize,
12    // The vectors below hold indices into `all_fairings`.
13    ignite: Vec<usize>,
14    liftoff: Vec<usize>,
15    request: Vec<usize>,
16    response: Vec<usize>,
17    shutdown: Vec<usize>,
18}
19
20macro_rules! iter {
21    ($_self:ident . $kind:ident) => ({
22        iter!($_self, $_self.$kind.iter().copied()).map(|v| v.1)
23    });
24    ($_self:ident, $indices:expr) => ({
25        let all_fairings = &$_self.all_fairings;
26        $indices.filter_map(move |i| {
27            let i = i.clone();
28            debug_assert!(all_fairings.get(i).is_some());
29            let f = all_fairings.get(i).map(|f| &**f)?;
30            Some((i, f))
31        })
32    })
33}
34
35impl Fairings {
36    #[inline]
37    pub fn new() -> Fairings {
38        Fairings::default()
39    }
40
41    pub fn active(&self) -> impl Iterator<Item = &usize> {
42        self.ignite.iter()
43            .chain(self.liftoff.iter())
44            .chain(self.request.iter())
45            .chain(self.response.iter())
46            .chain(self.shutdown.iter())
47    }
48
49    pub fn unique_active(&self) -> impl Iterator<Item = usize> {
50        let mut bitmap = vec![false; self.all_fairings.len()];
51        for i in self.active() {
52            bitmap.get_mut(*i).map(|active| *active = true);
53        }
54
55        bitmap.into_iter()
56            .enumerate()
57            .filter_map(|(i, active)| active.then_some(i))
58    }
59
60    pub fn unique_set(&self) -> Vec<&dyn Fairing> {
61        iter!(self, self.unique_active()).map(|v| v.1).collect()
62    }
63
64    pub fn add(&mut self, fairing: Box<dyn Fairing>) {
65        let this = &fairing;
66        let this_info = this.info();
67        if this_info.kind.is(Kind::Singleton) {
68            // If we already ran a duplicate on ignite, then fail immediately.
69            // There is no way to uphold the "only run last singleton" promise.
70            //
71            // How can this happen? Like this:
72            //   1. Attach A (singleton).
73            //   2. Attach B (any fairing).
74            //   3. Ignite.
75            //   4. A executes on_ignite.
76            //   5. B executes on_ignite, attaches another A.
77            //   6. --- (A would run if not for this code)
78            let ignite_dup = iter!(self.ignite).position(|f| f.type_id() == this.type_id());
79            if let Some(dup_ignite_index) = ignite_dup {
80                if dup_ignite_index < self.num_ignited {
81                    self.failures.push(this_info);
82                    return;
83                }
84            }
85
86            // Finds `k` in `from` and removes it if it's there.
87            let remove = |k: usize, from: &mut Vec<usize>| {
88                if let Ok(j) = from.binary_search(&k) {
89                    from.remove(j);
90                }
91            };
92
93            // Collect all of the active duplicates.
94            let mut dups: Vec<usize> = iter!(self, self.unique_active())
95                .filter(|(_, f)| f.type_id() == this.type_id())
96                .map(|(i, _)| i)
97                .collect();
98
99            // Reverse the dup indices so `remove` is stable given shifts.
100            dups.sort(); dups.dedup(); dups.reverse();
101            for i in dups {
102                remove(i, &mut self.ignite);
103                remove(i, &mut self.liftoff);
104                remove(i, &mut self.request);
105                remove(i, &mut self.response);
106                remove(i, &mut self.shutdown);
107            }
108        }
109
110        let index = self.all_fairings.len();
111        self.all_fairings.push(fairing);
112        if this_info.kind.is(Kind::Ignite) { self.ignite.push(index); }
113        if this_info.kind.is(Kind::Liftoff) { self.liftoff.push(index); }
114        if this_info.kind.is(Kind::Request) { self.request.push(index); }
115        if this_info.kind.is(Kind::Response) { self.response.push(index); }
116        if this_info.kind.is(Kind::Shutdown) { self.shutdown.push(index); }
117    }
118
119    pub fn append(&mut self, others: &mut Fairings) {
120        for fairing in others.all_fairings.drain(..) {
121            self.add(fairing);
122        }
123    }
124
125    pub async fn handle_ignite(mut rocket: Rocket<Build>) -> Rocket<Build> {
126        while rocket.fairings.num_ignited < rocket.fairings.ignite.len() {
127            // We're going to move `rocket` while borrowing `fairings`...
128            let mut fairings = std::mem::replace(&mut rocket.fairings, Fairings::new());
129            for fairing in iter!(fairings.ignite).skip(fairings.num_ignited) {
130                let info = fairing.info();
131                rocket = match fairing.on_ignite(rocket).await {
132                    Ok(rocket) => rocket,
133                    Err(rocket) => {
134                        fairings.failures.push(info);
135                        rocket
136                    }
137                };
138
139                fairings.num_ignited += 1;
140            }
141
142            // Note that `rocket.fairings` may now be non-empty since ignite
143            // fairings could have added more fairings! Move them to the end.
144            fairings.append(&mut rocket.fairings);
145            rocket.fairings = fairings;
146        }
147
148        rocket
149    }
150
151    #[inline(always)]
152    pub async fn handle_liftoff(&self, rocket: &Rocket<Orbit>) {
153        let liftoff_futures = iter!(self.liftoff).map(|f| f.on_liftoff(rocket));
154        futures::future::join_all(liftoff_futures).await;
155    }
156
157    #[inline(always)]
158    pub async fn handle_request(&self, req: &mut Request<'_>, data: &mut Data<'_>) {
159        for fairing in iter!(self.request) {
160            fairing.on_request(req, data).await
161        }
162    }
163
164    #[inline(always)]
165    pub async fn handle_response<'r>(&self, req: &'r Request<'_>, res: &mut Response<'r>) {
166        for fairing in iter!(self.response) {
167            fairing.on_response(req, res).await;
168        }
169    }
170
171    #[inline(always)]
172    pub async fn handle_shutdown(&self, rocket: &Rocket<Orbit>) {
173        let shutdown_futures = iter!(self.shutdown).map(|f| f.on_shutdown(rocket));
174        futures::future::join_all(shutdown_futures).await;
175    }
176
177    pub fn audit(&self) -> Result<(), &[Info]> {
178        match &self.failures[..] {
179            [] => Ok(()),
180            failures => Err(failures)
181        }
182    }
183
184    pub fn filter<F: Fairing>(&self) -> impl Iterator<Item = &F> {
185        iter!(self, self.unique_active())
186            .filter_map(|v| v.1.downcast_ref::<F>())
187    }
188
189    pub fn filter_mut<F: Fairing>(&mut self) -> impl Iterator<Item = &mut F> {
190        let mut bitmap = vec![false; self.all_fairings.len()];
191        for &i in self.active() {
192            let is_target = self.all_fairings.get(i)
193                .and_then(|f| f.downcast_ref::<F>())
194                .is_some();
195
196            bitmap.get_mut(i).map(|target| *target = is_target);
197        }
198
199        self.all_fairings.iter_mut()
200            .enumerate()
201            .filter(move |(i, _)| *bitmap.get(*i).unwrap_or(&false))
202            .filter_map(|(_, f)| f.downcast_mut::<F>())
203    }
204}
205
206impl std::fmt::Debug for Fairings {
207    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208        fn debug_info<'a>(iter: impl Iterator<Item = &'a dyn Fairing>) -> Vec<Info> {
209            iter.map(|f| f.info()).collect()
210        }
211
212        f.debug_struct("Fairings")
213            .field("launch", &debug_info(iter!(self.ignite)))
214            .field("liftoff", &debug_info(iter!(self.liftoff)))
215            .field("request", &debug_info(iter!(self.request)))
216            .field("response", &debug_info(iter!(self.response)))
217            .field("shutdown", &debug_info(iter!(self.shutdown)))
218            .finish()
219    }
220}