macron_map/
lib.rs

1#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
2
3//! See the documentation here [macron documentation](https://docs.rs/macron)
4
5use proc_macro::TokenStream;
6use quote::quote;
7use syn::punctuated::Punctuated;
8
9/// The key-value collection parser
10#[proc_macro]
11pub fn map(input: TokenStream) -> TokenStream {
12    let Map { fields } = syn::parse_macro_input!(input as Map);
13    
14    let list = fields.into_iter().map(|pair| {
15        let (k, v) = (pair.key, pair.value);
16        quote! { (#k, #v) }
17    });
18
19    quote! { [#(#list),*] }.into()
20}
21
22/// The key-value collection
23struct Map {
24    pub fields: Punctuated::<Field, syn::Token![,]>,
25}
26
27impl syn::parse::Parse for Map {
28    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
29        let fields = Punctuated::<Field, syn::Token![,]>::parse_terminated(input)?;
30        
31        Ok(Map { fields })
32    }
33}
34
35/// The key-value collection field
36struct Field {
37    pub key: syn::Expr,
38    pub value: syn::Expr,
39}
40
41impl syn::parse::Parse for Field {
42    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
43        let key = input.parse()?;
44
45        if input.peek(syn::Token![:]) {
46            input.parse::<syn::Token![:]>()?;
47        } else if input.peek(syn::Token![=>]) {
48            input.parse::<syn::Token![=>]>()?;
49        } else {
50            return Err(syn::Error::new(input.span(), "the expected separator is `:` or `=>` between key and value"));
51        }
52
53        let value = input.parse()?;
54        
55        Ok(Field {
56            key,
57            value,
58        })
59    }
60}