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 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
use std::marker::PhantomData; use crate::{ DynSvc, InjectError, InjectResult, Injector, Interface, InterfaceFor, OwnedDynSvc, RequestInfo, Service, ServiceInfo, Svc, }; /// Weakly typed service provider. /// /// Given an injector, this can provide an instance of a service. This is /// automatically implemented for all types that implement [`TypedProvider`], /// and [`TypedProvider`] should be preferred if possible for custom service /// providers to allow for stronger type checking. pub trait Provider: Service { /// The [`ServiceInfo`] which describes the type returned by this provider. fn result(&self) -> ServiceInfo; /// Provides an instance of the service. fn provide( &mut self, injector: &Injector, request_info: &RequestInfo, ) -> InjectResult<DynSvc>; /// Provides an owned instance of the service. fn provide_owned( &mut self, _injector: &Injector, _request_info: &RequestInfo, ) -> InjectResult<OwnedDynSvc> { Err(InjectError::OwnedNotSupported { service_info: self.result(), }) } } impl<T> Provider for T where T: TypedProvider, { fn result(&self) -> ServiceInfo { ServiceInfo::of::<T::Result>() } fn provide( &mut self, injector: &Injector, request_info: &RequestInfo, ) -> InjectResult<DynSvc> { let result = self.provide_typed(injector, request_info)?; Ok(result as DynSvc) } fn provide_owned( &mut self, injector: &Injector, request_info: &RequestInfo, ) -> InjectResult<OwnedDynSvc> { let result = self.provide_owned_typed(injector, request_info)?; Ok(result as OwnedDynSvc) } } /// A strongly-typed service provider. /// /// Types which implement this trait can provide strongly-typed instances of a /// particular service type. Examples of typed providers include providers /// created from service factories or constant providers. This should be /// preferred over [`Provider`] for custom service providers if possible due to /// the strong type guarantees this provides. [`Provider`] is automatically /// implemented for all types which implement [`TypedProvider`]. /// /// ## Example /// /// ``` /// use runtime_injector::{ /// InjectResult, Injector, RequestInfo, Svc, TypedProvider, /// }; /// /// struct Foo; /// /// struct FooProvider; /// impl TypedProvider for FooProvider { /// type Result = Foo; /// /// fn provide_typed( /// &mut self, /// _injector: &Injector, /// _request_info: &RequestInfo, /// ) -> InjectResult<Svc<Self::Result>> { /// Ok(Svc::new(Foo)) /// } /// } /// /// let mut builder = Injector::builder(); /// builder.provide(FooProvider); /// /// let injector = builder.build(); /// let _foo: Svc<Foo> = injector.get().unwrap(); /// ``` pub trait TypedProvider: Sized + Provider { /// The type of service this can provide. type Result: Interface; /// Provides an instance of the service. The [`Injector`] passed in can be /// used to retrieve instances of any dependencies this service has. fn provide_typed( &mut self, injector: &Injector, request_info: &RequestInfo, ) -> InjectResult<Svc<Self::Result>>; /// Provides an owned instance of the service. Not all providers can /// provide an owned variant of the service. fn provide_owned_typed( &mut self, _injector: &Injector, _request_info: &RequestInfo, ) -> InjectResult<Box<Self::Result>> { Err(InjectError::OwnedNotSupported { service_info: ServiceInfo::of::<Self::Result>(), }) } /// Provides this service as an implementation of a particular interface. /// Rather than requesting this service with its concrete type, it can /// instead be requested by its interface type. /// /// *Note: it cannot be requested with its concrete type once it has been /// assigned an interface.* /// /// ## Example /// /// ``` /// use runtime_injector::{ /// interface, InjectResult, Injector, IntoSingleton, Service, Svc, /// TypedProvider, /// }; /// /// trait Fooable: Service { /// fn bar(&self) {} /// } /// /// interface!(dyn Fooable = [Foo]); /// /// #[derive(Default)] /// struct Foo; /// impl Fooable for Foo {} /// /// let mut builder = Injector::builder(); /// builder.provide(Foo::default.singleton().with_interface::<dyn Fooable>()); /// /// // Foo can now be requested through its interface of `dyn Fooable`. /// let injector = builder.build(); /// let fooable: Svc<dyn Fooable> = injector.get().unwrap(); /// fooable.bar(); /// /// // It can't be requested through its original type /// assert!(injector.get::<Svc<Foo>>().is_err()); /// ``` fn with_interface<I: ?Sized + InterfaceFor<Self::Result>>( self, ) -> InterfaceProvider<I, Self> { InterfaceProvider { inner: self, marker: PhantomData, } } } /// Provides a service as an implementation of an interface. See /// [`TypedProvider::with_interface()`] for more information. pub struct InterfaceProvider<I, P> where P: TypedProvider, I: ?Sized + InterfaceFor<P::Result>, { inner: P, marker: PhantomData<fn() -> I>, } impl<I, P> Provider for InterfaceProvider<I, P> where P: TypedProvider, I: ?Sized + InterfaceFor<P::Result>, { fn result(&self) -> ServiceInfo { ServiceInfo::of::<I>() } fn provide( &mut self, injector: &Injector, request_info: &RequestInfo, ) -> InjectResult<DynSvc> { self.inner.provide(injector, request_info) } fn provide_owned( &mut self, injector: &Injector, request_info: &RequestInfo, ) -> InjectResult<OwnedDynSvc> { self.inner.provide_owned(injector, request_info) } }