rocket/fairing/
info_kind.rs

1use std::ops::BitOr;
2
3/// Information about a [`Fairing`](crate::fairing::Fairing).
4///
5/// The `name` field is an arbitrary name for a fairing. The `kind` field is a
6/// is an `or`d set of [`Kind`] structures. Rocket uses the values set in `Kind`
7/// to determine which callbacks from a given `Fairing` implementation to
8/// actually call.
9///
10/// # Example
11///
12/// A simple `Info` structure that can be used for a `Fairing` that implements
13/// all callbacks:
14///
15/// ```
16/// use rocket::fairing::{Info, Kind};
17///
18/// # let _unused_info =
19/// Info {
20///     name: "Example Fairing",
21///     kind: Kind::Ignite | Kind::Liftoff | Kind::Request | Kind::Response | Kind::Shutdown
22/// }
23/// # ;
24/// ```
25#[derive(Debug, Copy, Clone)]
26pub struct Info {
27    /// The name of the fairing.
28    pub name: &'static str,
29    /// A set representing the callbacks the fairing wishes to receive.
30    pub kind: Kind,
31}
32
33/// A bitset representing the kinds of callbacks a
34/// [`Fairing`](crate::fairing::Fairing) wishes to receive.
35///
36/// A fairing can request any combination of any of the following kinds of
37/// callbacks:
38///
39///   * Ignite
40///   * Liftoff
41///   * Request
42///   * Response
43///   * Shutdown
44///
45/// Two `Kind` structures can be `or`d together to represent a combination. For
46/// instance, to represent a fairing that is both an ignite and request fairing,
47/// use `Kind::Ignite | Kind::Request`. Similarly, to represent a fairing that
48/// is only an ignite fairing, use `Kind::Ignite`.
49///
50/// Additionally, a fairing can request to be treated as a
51/// [singleton](crate::fairing::Fairing#singletons) by specifying the
52/// `Singleton` kind.
53#[derive(Debug, Clone, Copy)]
54pub struct Kind(usize);
55
56#[allow(non_upper_case_globals)]
57impl Kind {
58    /// `Kind` flag representing a request for a 'ignite' callback.
59    pub const Ignite: Kind = Kind(1 << 0);
60
61    /// `Kind` flag representing a request for a 'liftoff' callback.
62    pub const Liftoff: Kind = Kind(1 << 1);
63
64    /// `Kind` flag representing a request for a 'request' callback.
65    pub const Request: Kind = Kind(1 << 2);
66
67    /// `Kind` flag representing a request for a 'response' callback.
68    pub const Response: Kind = Kind(1 << 3);
69
70    /// `Kind` flag representing a request for a 'shutdown' callback.
71    pub const Shutdown: Kind = Kind(1 << 4);
72
73    /// `Kind` flag representing a
74    /// [singleton](crate::fairing::Fairing#singletons) fairing.
75    pub const Singleton: Kind = Kind(1 << 5);
76
77    /// Returns `true` if `self` is a superset of `other`. In other words,
78    /// returns `true` if all of the kinds in `other` are also in `self`.
79    ///
80    /// # Example
81    ///
82    /// ```rust
83    /// use rocket::fairing::Kind;
84    ///
85    /// let ignite_and_req = Kind::Ignite | Kind::Request;
86    /// assert!(ignite_and_req.is(Kind::Ignite | Kind::Request));
87    ///
88    /// assert!(ignite_and_req.is(Kind::Ignite));
89    /// assert!(ignite_and_req.is(Kind::Request));
90    ///
91    /// assert!(!ignite_and_req.is(Kind::Liftoff));
92    /// assert!(!ignite_and_req.is(Kind::Response));
93    /// assert!(!ignite_and_req.is(Kind::Ignite | Kind::Response));
94    /// assert!(!ignite_and_req.is(Kind::Ignite | Kind::Request | Kind::Response));
95    /// ```
96    #[inline]
97    pub fn is(self, other: Kind) -> bool {
98        (other.0 & self.0) == other.0
99    }
100
101    /// Returns `true` if `self` is exactly `other`.
102    ///
103    /// # Example
104    ///
105    /// ```rust
106    /// use rocket::fairing::Kind;
107    ///
108    /// let ignite_and_req = Kind::Ignite | Kind::Request;
109    /// assert!(ignite_and_req.is_exactly(Kind::Ignite | Kind::Request));
110    ///
111    /// assert!(!ignite_and_req.is_exactly(Kind::Ignite));
112    /// assert!(!ignite_and_req.is_exactly(Kind::Request));
113    /// assert!(!ignite_and_req.is_exactly(Kind::Response));
114    /// assert!(!ignite_and_req.is_exactly(Kind::Ignite | Kind::Response));
115    /// ```
116    #[inline]
117    pub fn is_exactly(self, other: Kind) -> bool {
118        self.0 == other.0
119    }
120}
121
122impl BitOr for Kind {
123    type Output = Self;
124
125    #[inline(always)]
126    fn bitor(self, rhs: Self) -> Self {
127        Kind(self.0 | rhs.0)
128    }
129}
130
131impl std::fmt::Display for Kind {
132    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
133        let mut is_first = true;
134        let mut write = |string, kind| {
135            if self.is(kind) {
136                if !is_first { f.write_str(", ")?; }
137                f.write_str(string)?;
138                is_first = false;
139            }
140
141            Ok(())
142        };
143
144        write("ignite", Kind::Ignite)?;
145        write("liftoff", Kind::Liftoff)?;
146        write("request", Kind::Request)?;
147        write("response", Kind::Response)?;
148        write("shutdown", Kind::Shutdown)?;
149        write("singleton", Kind::Singleton)
150    }
151}