1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use crate::get_module_from_state; use rocket::outcome::IntoOutcome; use rocket::request::{FromRequest, Outcome}; use rocket::{http::Status, Request}; use shaku::{HasProvider, ModuleInterface}; use std::marker::PhantomData; use std::ops::Deref; /// Used to create a provided service from a shaku `Module`. /// The module should be stored in Rocket's state, in a `Box` (It could be /// `Box<dyn MyModule>` if the module implementation changes at runtime). /// Use this `InjectProvided` struct as a request guard. /// /// # Example /// ```rust /// #![feature(proc_macro_hygiene, decl_macro)] /// /// #[macro_use] extern crate rocket; /// /// use shaku::{module, Provider}; /// use shaku_rocket::InjectProvided; /// /// trait HelloWorld { /// fn greet(&self) -> String; /// } /// /// #[derive(Provider)] /// #[shaku(interface = HelloWorld)] /// struct HelloWorldImpl; /// /// impl HelloWorld for HelloWorldImpl { /// fn greet(&self) -> String { /// "Hello, world!".to_owned() /// } /// } /// /// module! { /// HelloModule { /// components = [], /// providers = [HelloWorldImpl] /// } /// } /// /// #[get("/")] /// fn hello(hello_world: InjectProvided<HelloModule, dyn HelloWorld>) -> String { /// hello_world.greet() /// } /// /// fn main() { /// let module = HelloModule::builder().build(); /// /// # if false { // We don't actually want to launch the server in an example. /// rocket::ignite() /// .manage(Box::new(module)) /// .mount("/", routes![hello]) /// .launch(); /// # } /// } /// ``` pub struct InjectProvided<M: ModuleInterface + HasProvider<I> + ?Sized, I: ?Sized>( Box<I>, PhantomData<M>, ); impl<'a, 'r, M: ModuleInterface + HasProvider<I> + ?Sized, I: ?Sized> FromRequest<'a, 'r> for InjectProvided<M, I> { type Error = String; fn from_request(request: &'a Request<'r>) -> Outcome<Self, Self::Error> { let module = get_module_from_state::<M>(request)?; let service = module .inner() .provide() .map_err(|e| e.to_string()) .into_outcome(Status::InternalServerError)?; Outcome::Success(InjectProvided(service, PhantomData)) } } impl<M: ModuleInterface + HasProvider<I> + ?Sized, I: ?Sized> Deref for InjectProvided<M, I> { type Target = I; fn deref(&self) -> &Self::Target { self.0.deref() } }