|
| 1 | +use std::any::TypeId; |
1 | 2 | use std::fmt;
|
2 | 3 | use std::ops::{Deref, DerefMut};
|
3 | 4 | use std::sync::Arc;
|
@@ -488,6 +489,61 @@ impl Rocket<Build> {
|
488 | 489 | self
|
489 | 490 | }
|
490 | 491 |
|
| 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 | + |
491 | 547 | /// Returns a `Future` that transitions this instance of `Rocket` into the
|
492 | 548 | /// _ignite_ phase.
|
493 | 549 | ///
|
|
0 commit comments