Skip to content

Commit 1cafc72

Browse files
Add fairing retrieval methods to 'Rocket'.
Introduces four new methods: * `Rocket::fairing::<F>()` * `Rocket::fairing_mut::<F>()` * `Rocket::fairings::<F>()` * `Rocket::fairings_mut::<F>()` These methods allow retrieving references to fairings of type `F` from an instance of `Rocket`. The `fairing` and `fairing_mut` methods return a (mutable) reference to the first attached fairing of type `F`, while the `fairings` and `fairings_mut` methods return an iterator over (mutable) references to all attached fairings of type `F`. Co-authored-by: Matthew Pomes <[email protected]>
1 parent e889c26 commit 1cafc72

File tree

4 files changed

+284
-23
lines changed

4 files changed

+284
-23
lines changed

core/lib/src/fairing/fairings.rs

+42-13
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
use std::collections::HashSet;
2-
31
use crate::{Rocket, Request, Response, Data, Build, Orbit};
42
use crate::fairing::{Fairing, Info, Kind};
53

@@ -21,14 +19,15 @@ pub struct Fairings {
2119

2220
macro_rules! iter {
2321
($_self:ident . $kind:ident) => ({
24-
iter!($_self, $_self.$kind.iter()).map(|v| v.1)
22+
iter!($_self, $_self.$kind.iter().copied()).map(|v| v.1)
2523
});
2624
($_self:ident, $indices:expr) => ({
2725
let all_fairings = &$_self.all_fairings;
2826
$indices.filter_map(move |i| {
29-
debug_assert!(all_fairings.get(*i).is_some());
30-
let f = all_fairings.get(*i).map(|f| &**f)?;
31-
Some((*i, f))
27+
let i = i.clone();
28+
debug_assert!(all_fairings.get(i).is_some());
29+
let f = all_fairings.get(i).map(|f| &**f)?;
30+
Some((i, f))
3231
})
3332
})
3433
}
@@ -47,10 +46,19 @@ impl Fairings {
4746
.chain(self.shutdown.iter())
4847
}
4948

49+
pub fn unique_active(&self) -> impl Iterator<Item = usize> {
50+
let mut bitmap = vec![false; self.all_fairings.len()];
51+
for i in self.active() {
52+
bitmap.get_mut(*i).map(|active| *active = true);
53+
}
54+
55+
bitmap.into_iter()
56+
.enumerate()
57+
.filter_map(|(i, active)| active.then_some(i))
58+
}
59+
5060
pub fn unique_set(&self) -> Vec<&dyn Fairing> {
51-
iter!(self, self.active().collect::<HashSet<_>>().into_iter())
52-
.map(|v| v.1)
53-
.collect()
61+
iter!(self, self.unique_active()).map(|v| v.1).collect()
5462
}
5563

5664
pub fn add(&mut self, fairing: Box<dyn Fairing>) {
@@ -83,7 +91,7 @@ impl Fairings {
8391
};
8492

8593
// Collect all of the active duplicates.
86-
let mut dups: Vec<usize> = iter!(self, self.active())
94+
let mut dups: Vec<usize> = iter!(self, self.unique_active())
8795
.filter(|(_, f)| f.type_id() == this.type_id())
8896
.map(|(i, _)| i)
8997
.collect();
@@ -167,10 +175,31 @@ impl Fairings {
167175
}
168176

169177
pub fn audit(&self) -> Result<(), &[Info]> {
170-
match self.failures.is_empty() {
171-
true => Ok(()),
172-
false => Err(&self.failures)
178+
match &self.failures[..] {
179+
[] => Ok(()),
180+
failures => Err(failures)
181+
}
182+
}
183+
184+
pub fn filter<F: Fairing>(&self) -> impl Iterator<Item = &F> {
185+
iter!(self, self.unique_active())
186+
.filter_map(|v| v.1.downcast_ref::<F>())
187+
}
188+
189+
pub fn filter_mut<F: Fairing>(&mut self) -> impl Iterator<Item = &mut F> {
190+
let mut bitmap = vec![false; self.all_fairings.len()];
191+
for &i in self.active() {
192+
let is_target = self.all_fairings.get(i)
193+
.and_then(|f| f.downcast_ref::<F>())
194+
.is_some();
195+
196+
bitmap.get_mut(i).map(|target| *target = is_target);
173197
}
198+
199+
self.all_fairings.iter_mut()
200+
.enumerate()
201+
.filter(move |(i, _)| *bitmap.get(*i).unwrap_or(&false))
202+
.filter_map(|(_, f)| f.downcast_mut::<F>())
174203
}
175204
}
176205

core/lib/src/fairing/mod.rs

+21-1
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ pub type Result<T = Rocket<Build>, E = Rocket<Build>> = std::result::Result<T, E
425425
///
426426
/// [request-local state]: https://rocket.rs/master/guide/state/#request-local-state
427427
#[crate::async_trait]
428-
pub trait Fairing: Send + Sync + Any + 'static {
428+
pub trait Fairing: Send + Sync + AsAny + 'static {
429429
/// Returns an [`Info`] structure containing the `name` and [`Kind`] of this
430430
/// fairing. The `name` can be any arbitrary string. `Kind` must be an `or`d
431431
/// set of `Kind` variants.
@@ -533,6 +533,11 @@ pub trait Fairing: Send + Sync + Any + 'static {
533533
async fn on_shutdown(&self, _rocket: &Rocket<Orbit>) { }
534534
}
535535

536+
pub trait AsAny: Any {
537+
fn as_any_ref(&self) -> &dyn Any;
538+
fn as_any_mut(&mut self) -> &mut dyn Any;
539+
}
540+
536541
#[crate::async_trait]
537542
impl<T: Fairing + ?Sized> Fairing for std::sync::Arc<T> {
538543
#[inline]
@@ -565,3 +570,18 @@ impl<T: Fairing + ?Sized> Fairing for std::sync::Arc<T> {
565570
(self as &T).on_shutdown(rocket).await
566571
}
567572
}
573+
574+
impl<T: Any> AsAny for T {
575+
fn as_any_ref(&self) -> &dyn Any { self }
576+
fn as_any_mut(&mut self) -> &mut dyn Any { self }
577+
}
578+
579+
impl dyn Fairing {
580+
fn downcast_ref<T: Any>(&self) -> Option<&T> {
581+
self.as_any_ref().downcast_ref()
582+
}
583+
584+
fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
585+
self.as_any_mut().downcast_mut()
586+
}
587+
}

core/lib/src/phase.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ mod private {
1414
#[doc(hidden)]
1515
pub trait Stateful: private::Sealed {
1616
fn into_state(self) -> State;
17-
fn as_state_ref(&self) -> StateRef<'_>;
17+
fn as_ref(&self) -> StateRef<'_>;
18+
fn as_mut(&mut self) -> StateRefMut<'_>;
1819
}
1920

2021
/// A marker trait for Rocket's launch phases.
@@ -48,7 +49,8 @@ macro_rules! phase {
4849

4950
impl Stateful for $S {
5051
fn into_state(self) -> State { State::$P(self) }
51-
fn as_state_ref(&self) -> StateRef<'_> { StateRef::$P(self) }
52+
fn as_ref(&self) -> StateRef<'_> { StateRef::$P(self) }
53+
fn as_mut(&mut self) -> StateRefMut<'_> { StateRefMut::$P(self) }
5254
}
5355

5456
#[doc(hidden)]
@@ -70,6 +72,9 @@ macro_rules! phases {
7072
#[doc(hidden)]
7173
pub enum StateRef<'a> { $($P(&'a $S)),* }
7274

75+
#[doc(hidden)]
76+
pub enum StateRefMut<'a> { $($P(&'a mut $S)),* }
77+
7378
$(phase!($(#[$o])* $P ($(#[$i])* $S) { $($fields)* });)*
7479
)
7580
}

0 commit comments

Comments
 (0)