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}