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}