busybody/
helpers.rs

1#![allow(dead_code)]
2
3use crate::{
4    Resolver, ServiceContainer, ServiceContainerBuilder, handlers::Handler, service::Service,
5};
6
7/// Takes an async function or closure and execute it
8/// Require arguments are resolve either by a resolver or sourced from the service container
9///
10/// This function will use an existing if one exist.
11/// The service container to used is provided by the caller.
12pub async fn resolve_and_call<F, Args>(handler: F) -> F::Output
13where
14    F: Handler<Args>,
15    Args: Clone + Resolver + 'static,
16{
17    service_container().resolve_and_call(handler).await
18}
19
20/// Given a tuple of types, this function will try to resolve them
21/// by using a resolver or cloning an existing instance in the container
22///
23/// The global service container is used.
24pub async fn resolve_all<Args>() -> Args
25where
26    Args: Resolver,
27{
28    Args::resolve(&service_container()).await
29}
30
31/// Given a tuple of types, this function will try to resolve them
32/// by using a resolver or cloning an existing instance in the container
33///
34pub async fn resolve_all_with<Args>(ci: &ServiceContainer) -> Args
35where
36    Args: Resolver,
37{
38    Args::resolve(ci).await
39}
40
41/// Takes an async function or closure, a reference to the service container and execute it
42/// Require arguments are resolve either by a resolver or sourced from the service container
43///
44/// This function will use an existing if one exist.
45/// This  function will use the provided service container before fallback back to the global one
46pub async fn resolve_and_call_with<F, Args>(ci: &ServiceContainer, handler: F) -> F::Output
47where
48    F: Handler<Args>,
49    Args: Clone + Resolver + 'static,
50{
51    ci.resolve_and_call(handler).await
52}
53
54/// Given a type, this function will try to find an instance of the type
55/// wrapped in a `Service<T>` that is currently registered in the service
56/// container.
57/// The global service container is used as the resolver.
58pub async fn service<T: Send + Sync + 'static>() -> Service<T> {
59    service_container().get_type().await.unwrap()
60}
61
62/// Returns the global service container instance
63pub fn service_container() -> ServiceContainer {
64    ServiceContainerBuilder::new().build()
65}
66
67/// Returns an instance of the service builder
68pub fn make_builder() -> ServiceContainerBuilder {
69    ServiceContainerBuilder::new()
70}
71
72/// Tries to get an instance of the type if one exist in the container
73/// This function uses the global container
74pub async fn get_type<T: Clone + 'static>() -> Option<T> {
75    service_container().get_type().await
76}
77
78/// Tries to get an instance of the type's service if one exist in the container
79/// This function uses the global container
80pub async fn get_service<T: 'static>() -> Option<Service<T>> {
81    service_container().get::<T>().await
82}
83
84/// Removes the registered instance of the type specified and returns it
85/// This function uses the global container
86pub async fn forget_type<T: 'static>() -> Option<Box<T>> {
87    service_container().forget_type().await
88}
89
90/// Removes the registered service instance of the type specified and returns it
91/// This function uses the global container
92pub async fn forget<T: 'static>() -> Option<Box<Service<T>>> {
93    service_container().forget().await
94}
95
96/// Register a service instance
97/// The instance is registered with the global service container
98/// This function uses the global container
99pub async fn register_service<T: Send + Sync + 'static>(ext: T) -> ServiceContainer {
100    let container = service_container();
101    container.set(ext).await;
102
103    container
104}
105
106/// Register a type instance
107/// The instance is registered with the global service container
108/// This function uses the global container
109pub async fn register_type<T: Clone + Send + Sync + 'static>(ext: T) -> ServiceContainer {
110    let container = service_container();
111    container.set_type(ext).await;
112
113    container
114}
115
116/// Register a type instance
117/// Same as `register_type`
118/// The instance is registered with the global service container
119/// This function uses the global container
120pub async fn set_type<T: Clone + Send + Sync + 'static>(ext: T) -> ServiceContainer {
121    let container = service_container();
122    container.set_type(ext).await;
123
124    container
125}
126
127/// Registers a closure that will be call each time
128/// an instance of the specified type is requested
129/// This closure will override existing closure for this type
130/// This function uses the global container
131///
132pub async fn resolver<T: Clone + Send + Sync + 'static, F>(
133    callback: impl FnMut(ServiceContainer) -> F + Send + Sync + 'static,
134) -> ServiceContainer
135where
136    F: Future<Output = T> + Send + 'static,
137{
138    let c = service_container();
139    c.resolver(callback).await;
140    c
141}
142
143/// Registers a type as resolvable
144/// Existing resolver for this type will be replaced
145/// This function uses the global container
146///
147pub async fn resolvable<T: Resolver + Clone + Send + Sync + 'static>() -> ServiceContainer {
148    let c = service_container();
149    c.resolvable::<T>().await;
150    c
151}
152
153pub async fn resolvable_once<T: Resolver + Clone + Send + Sync + 'static>() -> ServiceContainer {
154    let c = service_container();
155    c.resolvable_once::<T>().await;
156    c
157}
158
159pub async fn soft_resolvable<T: Resolver + Clone + Send + Sync + 'static>() -> ServiceContainer {
160    let c = service_container();
161    c.soft_resolvable::<T>().await;
162    c
163}
164
165/// Registers a closure that will be call each time
166/// an instance of the specified type is requested
167/// This closure will override existing closure for this type
168///
169/// The returned instance will be store in the global service container
170/// and subsequent request for this type will resolve to that copy.
171///
172/// Note: The service container passed to your callback is the instance
173///       of the global service container
174pub async fn resolver_once<T: Clone + Send + Sync + 'static, F>(
175    callback: impl Fn(ServiceContainer) -> F + Send + Sync + 'static,
176) -> ServiceContainer
177where
178    F: Future<Output = T> + Send + 'static,
179{
180    let c = service_container();
181    c.resolver_once(callback).await;
182    c
183}
184
185/// Registers a closure that will be call each time
186/// an instance of the specified type is requested
187/// If a closure already registered for this type, this one will be ignore
188///
189///
190/// Note: The service container passed to your callback is the instance
191///       of the global service container
192pub async fn soft_resolver<T: Clone + Send + Sync + 'static, F>(
193    callback: impl Fn(ServiceContainer) -> F + Send + Sync + 'static,
194) -> ServiceContainer
195where
196    F: Future<Output = T> + Send + 'static,
197{
198    let c = service_container();
199    c.soft_resolver(callback).await;
200    c
201}
202
203/// Registers a closure that will be call each time
204/// an instance of the specified type is requested
205/// If a closure already registered for this type, this one will be ignore
206///
207/// The returned instance will be store in the global service container
208/// and subsequent request for this type will resolve to that copy.
209///
210/// Note: The service container passed to your callback is the instance
211///       of the global service container
212pub async fn soft_resolver_once<T: Clone + Send + Sync + 'static, F>(
213    callback: impl Fn(ServiceContainer) -> F + Send + Sync + 'static,
214) -> ServiceContainer
215where
216    F: Future<Output = T> + Send + 'static,
217{
218    let c = service_container();
219    c.soft_resolver_once(callback).await;
220    c
221}
222
223/// Returns a new proxy service container
224pub fn make_proxy() -> ServiceContainer {
225    ServiceContainer::proxy()
226}
227
228/// Returns a new proxy service container that is tie to the current task
229///
230/// If this function is called outside of a task context, an error will be return
231pub fn make_task_proxy() -> Result<ServiceContainer, String> {
232    ServiceContainer::make_task_proxy()
233}
234
235/// Returns a new proxy service container that is tie to the current task
236///
237/// If this function is called outside of a task context, a normal proxy instance will be returned.
238pub fn make_task_proxy_or_fallback() -> ServiceContainer {
239    ServiceContainer::make_task_proxy().unwrap_or_else(|_| make_proxy())
240}