rocket/fairing/
fairings.rs

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
use {Rocket, Request, Response, Data};
use fairing::{Fairing, Kind};

use yansi::Paint;

#[derive(Default)]
pub struct Fairings {
    all_fairings: Vec<Box<dyn Fairing>>,
    attach_failures: Vec<&'static str>,
    // The vectors below hold indices into `all_fairings`.
    launch: Vec<usize>,
    request: Vec<usize>,
    response: Vec<usize>,
}

impl Fairings {
    #[inline]
    pub fn new() -> Fairings {
        Fairings::default()
    }

    pub fn attach(&mut self, fairing: Box<dyn Fairing>, mut rocket: Rocket) -> Rocket {
        // Run the `on_attach` callback if this is an 'attach' fairing.
        let kind = fairing.info().kind;
        let name = fairing.info().name;
        if kind.is(Kind::Attach) {
            rocket = fairing.on_attach(rocket)
                .unwrap_or_else(|r| { self.attach_failures.push(name); r })
        }

        self.add(fairing);
        rocket
    }

    fn add(&mut self, fairing: Box<dyn Fairing>) {
        let kind = fairing.info().kind;
        if !kind.is_exactly(Kind::Attach) {
            let index = self.all_fairings.len();
            self.all_fairings.push(fairing);

            if kind.is(Kind::Launch) { self.launch.push(index); }
            if kind.is(Kind::Request) { self.request.push(index); }
            if kind.is(Kind::Response) { self.response.push(index); }
        }
    }

    pub fn append(&mut self, others: Fairings) {
        for fairing in others.all_fairings {
            self.add(fairing);
        }
    }

    #[inline(always)]
    pub fn handle_launch(&self, rocket: &Rocket) {
        for &i in &self.launch {
            self.all_fairings[i].on_launch(rocket);
        }
    }

    #[inline(always)]
    pub fn handle_request(&self, req: &mut Request, data: &Data) {
        for &i in &self.request {
            self.all_fairings[i].on_request(req, data);
        }
    }

    #[inline(always)]
    pub fn handle_response(&self, request: &Request, response: &mut Response) {
        for &i in &self.response {
            self.all_fairings[i].on_response(request, response);
        }
    }

    pub fn failures(&self) -> Option<&[&'static str]> {
        if self.attach_failures.is_empty() {
            None
        } else {
            Some(&self.attach_failures)
        }
    }

    fn info_for(&self, kind: &str, fairings: &[usize]) {
        if !fairings.is_empty() {
            let num = fairings.len();
            let names = fairings.iter().cloned()
                .map(|i| self.all_fairings[i].info().name)
                .collect::<Vec<_>>()
                .join(", ");

            info_!("{} {}: {}", Paint::default(num).bold(), kind, Paint::default(names).bold());
        }
    }

    pub fn pretty_print_counts(&self) {
        if !self.all_fairings.is_empty() {
            info!("{}{}:", Paint::masked("📡 "), Paint::magenta("Fairings"));
            self.info_for("launch", &self.launch);
            self.info_for("request", &self.request);
            self.info_for("response", &self.response);
        }
    }
}