sdi/
lib.rs

1#![crate_type = "proc-macro"]
2
3use std::collections::HashMap;
4use std::sync::Mutex;
5
6use lazy_static::lazy_static;
7use proc_macro::TokenStream;
8
9lazy_static! {
10    static ref MAP: Mutex<HashMap<String, String>> =
11        Mutex::new(HashMap::new());
12}
13
14/// Register an statically resolved service expression indexed by key.
15///
16/// ## Example
17///
18/// ```rust
19/// use sdi::{inject, provide};
20///
21/// #[derive(Debug, PartialEq)]
22/// struct A;
23///
24/// impl A {
25///     pub fn new() -> A { A }
26///     provide!(A <- A::new());
27/// }
28///
29/// assert_eq!(A::new(), inject!(A))
30/// ```
31/// Provide by inject is also ok.
32/// ```rust
33/// use sdi::{inject, provide};
34///
35/// #[derive(Debug, PartialEq)]
36/// struct A;
37/// provide!(A <- A);
38///
39/// #[derive(Debug, PartialEq)]
40/// struct B(A);
41///
42/// impl B {
43///     pub fn new(a:A) -> B { B(a) }
44///     provide!(B <- B::new(inject!(A)));
45/// }
46///
47/// assert_eq!(B::new(A), inject!(B))
48/// ```
49#[proc_macro]
50pub fn provide(attr: TokenStream) -> TokenStream {
51    let (key, expr) = {
52        let stringify = attr.to_string();
53        let split: Vec<String> = stringify
54            .split(" <- ")
55            .map(|str| str.to_owned())
56            .collect();
57
58        let err_msg = "Invalid provider syntax, consider: provide!(<key> <- <expr>)";
59        if split.len() != 2 {
60            panic!("{}", err_msg);
61        }
62
63        let key = split
64            .get(0)
65            .expect(err_msg)
66            .to_owned();
67        let expr = split
68            .get(1)
69            .expect(err_msg)
70            .to_owned();
71
72        (key, expr)
73    };
74
75    MAP.lock()
76        .unwrap()
77        .insert(key, expr);
78
79    TokenStream::new()
80}
81
82/// Get an statically resolved service expression by key
83///
84/// ## Example
85///
86/// ```rust
87/// use sdi::{inject, provide};
88///
89/// #[derive(Debug, PartialEq)]
90/// struct A;
91///
92/// impl A {
93///     pub fn new() -> A { A }
94///     provide!(A <- A::new());
95/// }
96///
97/// assert_eq!(A::new(), inject!(A))
98/// ```
99#[proc_macro]
100pub fn inject(attr: TokenStream) -> TokenStream {
101    let key = attr.to_string();
102    MAP.lock()
103        .unwrap()
104        .get(&key)
105        .expect(&format!("Unknown inject key: `{}`", key))
106        .parse()
107        .unwrap()
108}