//! `syn` types for macro input. Sets are adapted as map entries with `()` //! values so the map-building path can be shared. use proc_macro2::TokenStream; use quote::ToTokens; use syn::parse::{Parse, ParseStream}; use syn::punctuated::Punctuated; use syn::{Expr, Result, Token}; #[derive(Clone)] pub struct Key { pub attrs: Vec, pub expr: Expr, } impl Parse for Key { fn parse(input: ParseStream<'_>) -> Result { Ok(Key { attrs: input.call(syn::Attribute::parse_outer)?, expr: input.parse()?, }) } } impl ToTokens for Key { fn to_tokens(&self, tokens: &mut TokenStream) { for attr in &self.attrs { attr.to_tokens(tokens); } self.expr.to_tokens(tokens); } } // Attributes on entries are handled as attributed on the corresponding `Key`. #[derive(Clone)] pub struct Entry { pub key: Key, pub arrow: Token![=>], pub value: Expr, } impl Parse for Entry { fn parse(input: ParseStream<'_>) -> Result { Ok(Entry { key: input.parse()?, arrow: input.parse()?, value: input.parse()?, }) } } impl ToTokens for Entry { fn to_tokens(&self, tokens: &mut TokenStream) { self.key.to_tokens(tokens); self.arrow.to_tokens(tokens); self.value.to_tokens(tokens); } } pub struct Map { pub entries: Punctuated, } impl Parse for Map { fn parse(input: ParseStream<'_>) -> Result { Ok(Map { entries: Punctuated::parse_terminated(input)?, }) } } pub struct Set { pub keys: Punctuated, } impl Parse for Set { fn parse(input: ParseStream<'_>) -> Result { Ok(Set { keys: Punctuated::parse_terminated(input)?, }) } } pub trait AsMapEntry { fn key(&self) -> &Key; fn value(&self) -> Expr; } impl AsMapEntry for Key { fn key(&self) -> &Key { self } fn value(&self) -> Expr { syn::parse_quote!(()) } } impl AsMapEntry for Entry { fn key(&self) -> &Key { &self.key } fn value(&self) -> Expr { self.value.clone() } }