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
use crate::key_value::KeyValueSeq;
use crate::value::{Value, ValueExpr, ValueIterExpr, Verbatim};
use crate::ParseRaw;
use proc_macro2::{Ident, Span, TokenStream};
use quote::{quote, ToTokens};
use syn::parse;
pub struct HashMapInput<V = Verbatim>(KeyValueSeq<V>);
impl<V> HashMapInput<V>
where
ValueExpr<V>: ToTokens,
ValueIterExpr<V>: ToTokens,
{
pub fn into_output(self) -> TokenStream {
let target = Ident::new("map", Span::call_site());
let key_values = self.0.key_values();
let initial_capacity = if self.0.is_simple() {
key_values.len()
} else {
16.max(key_values.len().next_power_of_two() * 2)
};
let updates = self.0.key_values().map(|kv| {
let key = kv.key();
let value = kv.value();
match key {
Value::One(expr) => quote! {
#target.insert(#expr, #value);
},
Value::Many(expr) => quote! {
for key in #expr {
#target.insert(key, #value);
}
},
}
});
quote! {{
let mut #target = ::std::collections::HashMap::with_capacity(#initial_capacity);
#(#updates)*
#target
}}
}
}
impl<V> ParseRaw for HashMapInput<V>
where
ValueExpr<V>: ToTokens,
ValueIterExpr<V>: ToTokens,
{
fn parse_raw(input: TokenStream) -> parse::Result<Self> {
Ok(HashMapInput(KeyValueSeq::parse_raw(input)?))
}
}