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