Loosen bounds on 'AdHoc::{Attach,Launch}' methods.

These changes allow any type that implements `FnOnce`, instead of `Fn`,
to be used as attach or launch fairings via `AdHoc`. Furthermore, the
`Sync` bound was also lifted.

Resolves #522.
This commit is contained in:
Sergio Benitez 2018-04-22 01:44:43 -07:00
parent 6e34a04188
commit 0e85f9efd8
2 changed files with 22 additions and 11 deletions

View File

@ -1,3 +1,6 @@
use std::sync::Mutex;
use std::boxed::FnBox;
use {Rocket, Request, Response, Data}; use {Rocket, Request, Response, Data};
use fairing::{Fairing, Kind, Info}; use fairing::{Fairing, Kind, Info};
@ -35,10 +38,10 @@ use fairing::{Fairing, Kind, Info};
pub enum AdHoc { pub enum AdHoc {
/// An ad-hoc **attach** fairing. Called when the fairing is attached. /// An ad-hoc **attach** fairing. Called when the fairing is attached.
#[doc(hidden)] #[doc(hidden)]
Attach(Box<Fn(Rocket) -> Result<Rocket, Rocket> + Send + Sync + 'static>), Attach(Mutex<Option<Box<FnBox(Rocket) -> Result<Rocket, Rocket> + Send + 'static>>>),
/// An ad-hoc **launch** fairing. Called just before Rocket launches. /// An ad-hoc **launch** fairing. Called just before Rocket launches.
#[doc(hidden)] #[doc(hidden)]
Launch(Box<Fn(&Rocket) + Send + Sync + 'static>), Launch(Mutex<Option<Box<FnBox(&Rocket) + Send + 'static>>>),
/// An ad-hoc **request** fairing. Called when a request is received. /// An ad-hoc **request** fairing. Called when a request is received.
#[doc(hidden)] #[doc(hidden)]
Request(Box<Fn(&mut Request, &Data) + Send + Sync + 'static>), Request(Box<Fn(&mut Request, &Data) + Send + Sync + 'static>),
@ -61,9 +64,9 @@ impl AdHoc {
/// let fairing = AdHoc::on_attach(|rocket| Ok(rocket)); /// let fairing = AdHoc::on_attach(|rocket| Ok(rocket));
/// ``` /// ```
pub fn on_attach<F>(f: F) -> AdHoc pub fn on_attach<F>(f: F) -> AdHoc
where F: Fn(Rocket) -> Result<Rocket, Rocket> + Send + Sync + 'static where F: FnOnce(Rocket) -> Result<Rocket, Rocket> + Send + 'static
{ {
AdHoc::Attach(Box::new(f)) AdHoc::Attach(Mutex::new(Some(Box::new(f))))
} }
/// Constructs an `AdHoc` launch fairing. The function `f` will be called by /// Constructs an `AdHoc` launch fairing. The function `f` will be called by
@ -80,9 +83,9 @@ impl AdHoc {
/// }); /// });
/// ``` /// ```
pub fn on_launch<F>(f: F) -> AdHoc pub fn on_launch<F>(f: F) -> AdHoc
where F: Fn(&Rocket) + Send + Sync + 'static where F: FnOnce(&Rocket) + Send + 'static
{ {
AdHoc::Launch(Box::new(f)) AdHoc::Launch(Mutex::new(Some(Box::new(f))))
} }
/// Constructs an `AdHoc` request fairing. The function `f` will be called /// Constructs an `AdHoc` request fairing. The function `f` will be called
@ -158,15 +161,22 @@ impl Fairing for AdHoc {
} }
fn on_attach(&self, rocket: Rocket) -> Result<Rocket, Rocket> { fn on_attach(&self, rocket: Rocket) -> Result<Rocket, Rocket> {
match *self { if let AdHoc::Attach(ref mutex) = *self {
AdHoc::Attach(ref callback) => callback(rocket), let mut option = mutex.lock().expect("AdHoc::Attach lock");
_ => Ok(rocket), option.take()
.expect("internal error: `on_attach` single-call invariant broken")
.call_box((rocket,))
} else {
Ok(rocket)
} }
} }
fn on_launch(&self, rocket: &Rocket) { fn on_launch(&self, rocket: &Rocket) {
if let AdHoc::Launch(ref callback) = *self { if let AdHoc::Launch(ref mutex) = *self {
callback(rocket) let mut option = mutex.lock().expect("AdHoc::Launch lock");
option.take()
.expect("internal error: `on_launch` single-call invariant broken")
.call_box((rocket, ))
} }
} }

View File

@ -2,6 +2,7 @@
#![feature(const_fn)] #![feature(const_fn)]
#![feature(plugin, decl_macro)] #![feature(plugin, decl_macro)]
#![feature(try_trait)] #![feature(try_trait)]
#![feature(fnbox)]
#![recursion_limit="256"] #![recursion_limit="256"]
#![plugin(pear_codegen)] #![plugin(pear_codegen)]