Skip to content

Commit f884eab

Browse files
Pomes, MatthewSergioBenitez
Pomes, Matthew
authored andcommitted
Add modify_fairings
1 parent 8b9d906 commit f884eab

File tree

2 files changed

+60
-0
lines changed

2 files changed

+60
-0
lines changed

core/lib/src/fairing/fairings.rs

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ impl Fairings {
3939
Fairings::default()
4040
}
4141

42+
pub(crate) fn iter_mut<'a>(&'a mut self) -> impl Iterator<Item = &mut Box<dyn Fairing>> + 'a {
43+
self.all_fairings.iter_mut()
44+
}
45+
4246
pub fn active(&self) -> impl Iterator<Item = &usize> {
4347
self.ignite.iter()
4448
.chain(self.liftoff.iter())

core/lib/src/rocket.rs

+56
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::any::TypeId;
12
use std::fmt;
23
use std::ops::{Deref, DerefMut};
34
use std::sync::Arc;
@@ -488,6 +489,61 @@ impl Rocket<Build> {
488489
self
489490
}
490491

492+
/// Modify previously attached fairings. This should typically be used by on_ignite Fairings,
493+
/// to register new handlers or otherwise enable Fairings to work together.
494+
///
495+
/// ```rust,no_run
496+
/// # #[macro_use] extern crate rocket;
497+
/// # extern crate rocket_dyn_templates;
498+
/// use rocket::Rocket;
499+
/// use rocket::fairing::AdHoc;
500+
/// use rocket_dyn_templates::Templates;
501+
///
502+
/// #[launch]
503+
/// fn rocket() -> _ {
504+
/// rocket::build()
505+
/// .attach(Templates::default())
506+
/// .attach(AdHoc::on_ignite("Register new template function", |r| {
507+
/// r.modify_fairing(|f: &mut Templates| {
508+
/// f.register_function("some_function", some_function)
509+
/// })
510+
/// })))
511+
/// }
512+
/// ```
513+
///
514+
/// If multiple instances of the same type of Fairing have been attached, the modify function
515+
/// will be run on each instance.
516+
#[must_use]
517+
pub fn modify_fairings<F: Fairing, E: fmt::Debug>(mut self, modifier: impl Fn(&mut F) -> Result<(), E>) -> Result<Self, Self> {
518+
#[derive(Debug, PartialEq, Eq)]
519+
enum State {
520+
None,
521+
Success,
522+
Failure,
523+
}
524+
let mut state = State::None;
525+
for f in self.fairings.iter_mut() {
526+
let f = f.as_mut();
527+
if f.type_id() == TypeId::of::<F>() {
528+
// SAFTEY: `f` is a valid pointer since it was obtained from a Box, and it points
529+
// at an `F` since it has the same TypeId. Converting from dyn type to a concrete
530+
// type is handled automatically by the compilier
531+
let f = unsafe { &mut *((f as *mut dyn Fairing) as *mut F) };
532+
match modifier(f) {
533+
Ok(()) => if state == State::None { state = State::Success },
534+
Err(e) => {
535+
error_!("Failed to modify fairing: {:?}", e);
536+
state = State::Failure;
537+
}
538+
}
539+
}
540+
}
541+
match state {
542+
State::None | State::Failure => Err(self),
543+
State::Success => Ok(self),
544+
}
545+
}
546+
491547
/// Returns a `Future` that transitions this instance of `Rocket` into the
492548
/// _ignite_ phase.
493549
///

0 commit comments

Comments
 (0)