apply_string_args/
lib.rs

1use std::any::Any;
2use std::collections::HashMap;
3use lazy_regex::regex;
4
5/// Creates a `HashMap<String, Box<dyn Any>>` from a list of key-value pairs.
6///
7/// ## Example
8///
9/// ```
10/// use apply_string_args::string_args;
11/// fn main() {
12///     let map = string_args!{
13///         "a" => "foo",
14///         "b" => "bar",
15///     };
16///     assert_eq!(*map[&"a".to_owned()], "foo");
17///     assert_eq!(*map[&"b".to_owned()], "bar");
18///     assert_eq!(map.get(&"c".to_owned()), None);
19/// }
20/// ```
21#[macro_export]
22macro_rules! string_args {
23    (@single $($x:tt)*) => (());
24    (@count $($rest:expr),*) => (<[()]>::len(&[$(string_args!(@single $rest)),*]));
25
26    ($($key:expr => $value:expr,)+) => { string_args!($($key => $value),+) };
27    ($($key:expr => $value:expr),*) => {
28        {
29            let r_cap = string_args!(@count $($key),*);
30            let mut r_map = HashMap::<String, Box<dyn Any>>::with_capacity(r_cap);
31            $(
32                let _ = r_map.insert($key.to_string(), Box::new($value));
33            )*
34            r_map
35        }
36    };
37}
38
39pub fn apply(base: impl AsRef<str>, vars: &HashMap<String, Box<dyn Any>>, convert: fn(arg: &Box<dyn Any>) -> String) -> String {
40    regex!(r"\$(\$|[A-Za-z0-9]+)").replace_all(base.as_ref(), |s: &regex::Captures<'_>| {
41        let s = s.get(0).unwrap().as_str();
42        if s == "$$" {
43            "$".to_owned()
44        } else {
45            let v = vars.get(&s.to_string().replace("$", ""));
46            if let Some(v) = v { convert(v) } else { "None".to_owned() }
47        }
48    }).as_ref().to_string()
49}