bon_macros/collections/
map.rs

1use crate::util::prelude::*;
2use syn::parse::ParseStream;
3use syn::punctuated::Punctuated;
4use syn::{Expr, Token};
5
6pub(crate) fn parse_macro_input(
7    input: ParseStream<'_>,
8) -> Result<Punctuated<(Expr, Expr), Token![,]>, syn::Error> {
9    Punctuated::parse_terminated_with(input, parse_map_pair)
10}
11
12fn parse_map_pair(pair: ParseStream<'_>) -> Result<(Expr, Expr), syn::Error> {
13    let key = pair.parse().map_err(|_| pair.error(pair))?;
14    let _: Token![:] = pair.parse()?;
15    let value = pair.parse()?;
16
17    Ok((key, value))
18}
19
20pub(crate) fn generate(entries: Punctuated<(Expr, Expr), Token![,]>) -> TokenStream {
21    let error =
22        super::validate_expressions_are_unique("key in the map", entries.iter().map(|(k, _)| k));
23
24    let items = entries.into_iter().map(|(key, value)| {
25        quote!((
26            ::core::convert::Into::into(#key),
27            ::core::convert::Into::into(#value),
28        ))
29    });
30
31    let output = quote! {
32        ::core::iter::FromIterator::from_iter([
33            #(#items),*
34        ])
35    };
36
37    // We unconditionally return `output` as part of the result to make sure IDEs
38    // see this output and see what input tokens map to what output tokens. This
39    // way IDEs can provide better help to the developer even when there are errors.
40    error
41        .map(|err| {
42            let err = err.write_errors();
43            quote! {{
44                #err
45                #output
46            }}
47        })
48        .unwrap_or(output)
49}