dilib_macros/
lib.rs

1mod keys;
2mod provide_attr;
3mod resolve_fn_arg;
4mod scope;
5mod target;
6mod utils;
7
8use crate::provide_attr::ProvideAttribute;
9use proc_macro::TokenStream;
10use syn::parse_macro_input;
11use target::Target;
12
13/// Adds a provider from a `function` or `struct` to the global `Container`.
14///
15/// # Arguments
16/// - `name`: The name of the provider.
17/// - `scope`: The scope 'singleton' or 'scoped', defaults to 'scoped'.
18/// - `bind`: The trait to bind this instance to. This adds `Send + Sync` to the type.
19///
20/// # Example
21///
22/// ```rust,no_run
23/// use dilib::{macros::provide, Inject, Singleton, global::init_container, get_singleton, get_scoped};
24/// use std::sync::Mutex;
25///
26/// #[provide]
27/// fn message() -> String {
28///    "Current count".to_string()
29/// }
30///
31/// #[provide(scope = "singleton", name="count")]
32/// fn counter() -> Mutex<usize> {
33///   Mutex::new(0)
34/// }
35///
36/// #[derive(Inject)]
37/// #[provide] // provide should resolve after the derive
38/// struct PrintCount {
39///     #[inject(name="count")]
40///     counter: Singleton<Mutex<usize>>,
41///     msg: String
42/// }
43///
44/// impl PrintCount {
45///     fn print(&self) -> String {
46///         let count = self.counter.lock().unwrap();
47///         format!("{} {}", self.msg, count)
48///     }
49/// }
50///
51/// // Required to register the providers
52/// init_container(|_|{}).unwrap();
53///
54/// let counter = get_singleton!(Mutex<usize>, "count").expect("Could not get counter");
55/// *counter.lock().unwrap() += 5;
56///
57/// let print_count = get_scoped!(PrintCount).expect("Could not get print count");
58/// assert_eq!(print_count.print(), "Current count 5");
59/// ```
60#[proc_macro_attribute]
61pub fn provide(attr: TokenStream, item: TokenStream) -> TokenStream {
62    let attr = parse_macro_input!(attr as syn::AttributeArgs);
63    let target = match parse_macro_input!(item as syn::Item) {
64        syn::Item::Fn(item_fn) => Target::Fn(item_fn),
65        syn::Item::Struct(item_struct) => Target::Struct(item_struct),
66        _ => {
67            let call_site = proc_macro2::Span::call_site();
68            return syn::Error::new(call_site, "Expected a function or struct")
69                .into_compile_error()
70                .into();
71        }
72    };
73
74    ProvideAttribute::new(attr, target).expand().into()
75}
76
77/// Specify the dependency to inject to a function argument.
78///
79/// # Example
80/// ```rust,no_run
81/// use std::sync::Arc;
82/// use dilib::macros::{provide, inject};
83///
84/// #[provide]
85/// #[inject(value, name="initial_value")]
86/// fn compute(hash: String, value: Arc<usize>) -> usize {
87///    0 // ...
88/// }
89/// ```
90#[proc_macro_attribute]
91pub fn inject(_: TokenStream, item: TokenStream) -> TokenStream {
92    item
93}