proc_macro_kwargs/
parse.rs

1//! Utilities for parsing
2use std::hash::Hash;
3use std::marker::PhantomData;
4use std::ops::{Deref, DerefMut};
5
6use indexmap::IndexMap;
7
8use proc_macro2::{Ident, TokenStream};
9use quote::ToTokens;
10use syn::parse::{Parse, ParseStream};
11use syn::punctuated::Punctuated;
12use syn::spanned::Spanned;
13use syn::{braced, bracketed, parenthesized, Token};
14
15/// A type that can be parsed as an argument
16/// to a macro.
17///
18/// This is often implemented by delegating to syn's [Parse].
19///
20/// However, sometimes it can behave differently.
21/// For example, nested [MacroKeywordArgs](crate::MacroKeywordArgs)
22/// require surrounding braces `{}` when parsed as a `MacroArg`,
23/// but not when parsed via syn's [Parse].
24///
25/// This gives the effect of requiring braces when nested (as a MacroArg),
26/// but not at the top level (via syn's Parse).
27pub trait MacroArg: Sized {
28    /// Parse the argument to the macro
29    fn parse_macro_arg(stream: ParseStream) -> syn::Result<Self>;
30}
31
32/// Parses an optional [MacroArg],
33/// always returning the `Some` variant
34///
35/// The `None` variant will only be generated
36/// if the argument is missing
37impl<T: MacroArg> MacroArg for Option<T> {
38    fn parse_macro_arg(stream: ParseStream) -> syn::Result<Self> {
39        Ok(Some(T::parse_macro_arg(stream)?))
40    }
41}
42
43/// Internal utility for parsing
44macro_rules! macro_arg_parse_map {
45    ($target:ty; via $delegate:ty, |$src:ident| $transform:expr) => {
46        impl MacroArg for $target {
47            fn parse_macro_arg(stream: ParseStream) -> syn::Result<Self> {
48                let $src: $delegate = stream.parse()?;
49                Ok($transform)
50            }
51        }
52    };
53}
54macro_rules! macro_arg_parse_int {
55    ($($target:ty),*) => {
56        $(macro_arg_parse_map!($target; via syn::LitInt, |i| i.base10_parse::<$target>()?);)*
57    };
58}
59
60/// Implements [MacroArg] via syn's [Parse] trait
61#[macro_export]
62macro_rules! parse_macro_arg_via_syn {
63    ($target:path) => (parse_macro_arg_via_syn!($target; for <>););
64    ($target:path; for <$($lt:lifetime,)* $($param:ident),*> $(where $($where_tks:tt)*)?) => {
65        impl<$($lt,)* $($param),*> $crate::parse::MacroArg for $target $(where $($where_tks)* )* {
66            fn parse_macro_arg(stream: syn::parse::ParseStream) -> syn::Result<Self> {
67                stream.parse()
68            }
69        }
70    };
71}
72macro_arg_parse_int!(u8, u16, u32, u64, usize, i8, i16, i32, i64, isize);
73macro_arg_parse_map!(String; via syn::LitStr, |s| s.value());
74macro_arg_parse_map!(bool; via syn::LitBool, |s| s.value());
75macro_arg_parse_map!(f64; via syn::LitFloat, |f| f.base10_parse::<f64>()?);
76macro_arg_parse_map!(f32; via syn::LitFloat, |f| f.base10_parse::<f32>()?);
77macro_arg_parse_map!(char; via syn::LitChar, |c| c.value());
78
79/// The key in a [NestedDict]
80///
81/// This is supposed to be a trait alias,
82/// but those are not yet stable.
83pub trait MacroDictKey: MacroArg + Eq + Hash + Spanned {}
84impl<T: ?Sized + MacroArg + Eq + Hash + Spanned> MacroDictKey for T {}
85
86/// A pair of values in a [NestedDict]
87#[derive(Debug, Clone, Eq, PartialEq)]
88pub struct KeyValuePair<K: MacroDictKey, V: MacroArg> {
89    /// The key
90    pub key: K,
91    /// The value
92    pub value: V,
93}
94impl<K: MacroDictKey, V: MacroArg> Parse for KeyValuePair<K, V> {
95    fn parse(stream: ParseStream) -> syn::Result<Self> {
96        let key = K::parse_macro_arg(stream)?;
97        stream.parse::<Token![=>]>()?;
98        let value = V::parse_macro_arg(stream)?;
99        Ok(KeyValuePair { key, value })
100    }
101}
102parse_macro_arg_via_syn!(KeyValuePair::<K, V>; for <K, V> where K: MacroDictKey, V: MacroArg);
103
104/// A nested dictionary mapping keys to values with `=>`,
105/// and surrounded by braces
106///
107/// Duplicated keys are considered an error.
108///
109///
110/// ## Example
111/// `{ a => b, c => b }` is a `NestedDict<Ident, Ident>`
112pub struct NestedDict<K: MacroDictKey, V: MacroArg> {
113    /// The brace token
114    pub braces: syn::token::Brace,
115    /// The underlying map of keys to values
116    pub elements: IndexMap<K, V>,
117}
118impl<K: MacroDictKey, V: MacroArg> NestedDict<K, V> {
119    fn try_extend_pairs(
120        &mut self,
121        iter: impl Iterator<Item = KeyValuePair<K, V>>,
122    ) -> Result<(), syn::Error> {
123        for pair in iter {
124            let key_span = pair.key.span();
125            let existing = self.elements.insert(pair.key, pair.value);
126            if existing.is_some() {
127                return Err(syn::Error::new(key_span, "Duplicate keys"));
128            }
129        }
130        Ok(())
131    }
132}
133impl<K: MacroDictKey, V: MacroArg> MacroArg for NestedDict<K, V> {
134    fn parse_macro_arg(stream: ParseStream) -> syn::Result<Self> {
135        let content;
136        let braces = braced!(content in stream);
137        let pairs = Punctuated::<KeyValuePair<K, V>, Token![,]>::parse_terminated(&content)?;
138        let mut res = NestedDict {
139            braces,
140            elements: IndexMap::default(),
141        };
142        res.try_extend_pairs(pairs.into_iter())?;
143        Ok(res)
144    }
145}
146impl<K: MacroDictKey, V: MacroArg> Deref for NestedDict<K, V> {
147    type Target = IndexMap<K, V>;
148    #[inline]
149    fn deref(&self) -> &Self::Target {
150        &self.elements
151    }
152}
153impl<K: MacroDictKey, V: MacroArg> DerefMut for NestedDict<K, V> {
154    #[inline]
155    fn deref_mut(&mut self) -> &mut Self::Target {
156        &mut self.elements
157    }
158}
159
160/// A version of `Option` that is parsed with explicit `Some(<inner>)`
161/// or `None` syntax
162///
163/// This is as opposed to a regular `Option`, which requires
164/// no extra syntax and always parses to `Some`
165/// (it's intended for use with optional args)
166#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
167pub struct ExplicitOption<T>(pub Option<T>);
168impl<T> Deref for ExplicitOption<T> {
169    type Target = Option<T>;
170    #[inline]
171    fn deref(&self) -> &Option<T> {
172        &self.0
173    }
174}
175impl<T> From<Option<T>> for ExplicitOption<T> {
176    #[inline]
177    fn from(opt: Option<T>) -> Self {
178        ExplicitOption(opt)
179    }
180}
181impl<T> From<ExplicitOption<T>> for Option<T> {
182    #[inline]
183    fn from(explicit: ExplicitOption<T>) -> Option<T> {
184        explicit.0
185    }
186}
187impl<T: MacroArg> MacroArg for ExplicitOption<T> {
188    fn parse_macro_arg(stream: ParseStream) -> syn::Result<Self> {
189        if stream.peek(syn::Ident) {
190            let ident = stream.parse::<Ident>().unwrap();
191            if ident == "Some" {
192                let content;
193                parenthesized!(content in stream);
194                return Ok(ExplicitOption(Some(T::parse_macro_arg(&content)?)));
195            } else if ident == "None" {
196                return Ok(ExplicitOption(None));
197            }
198        }
199        // fall-through to error
200        Err(stream.error("Expected either `Some` or `None`"))
201    }
202}
203
204/// A nested list of [Punctuated] items,
205/// surrounded by brackets (ex. `[1, 2, 3]`)
206///
207/// By default, the separator token is the comma `,`
208#[derive(PartialEq, Eq, Debug, Hash)]
209pub struct NestedList<T: MacroArg, P = Token![,]> {
210    /// The brackets tokens
211    pub brackets: syn::token::Bracket,
212    /// The list of elements
213    pub elements: Vec<T>,
214    /// PhantomData, for the Token
215    marker: PhantomData<P>,
216}
217impl<T: MacroArg, P: Default> From<Vec<T>> for NestedList<T, P> {
218    #[inline]
219    fn from(v: Vec<T>) -> Self {
220        NestedList {
221            brackets: Default::default(),
222            elements: v,
223            marker: PhantomData,
224        }
225    }
226}
227impl<T: MacroArg, P> From<NestedList<T, P>> for Vec<T> {
228    #[inline]
229    fn from(v: NestedList<T, P>) -> Vec<T> {
230        v.elements
231    }
232}
233impl<T: MacroArg, P: Default> FromIterator<T> for NestedList<T, P> {
234    fn from_iter<A: IntoIterator<Item = T>>(iter: A) -> Self {
235        NestedList {
236            brackets: Default::default(),
237            elements: iter.into_iter().collect(),
238            marker: PhantomData,
239        }
240    }
241}
242impl<T: MacroArg, P> IntoIterator for NestedList<T, P> {
243    type Item = T;
244    type IntoIter = std::vec::IntoIter<T>;
245    #[inline]
246    fn into_iter(self) -> Self::IntoIter {
247        self.elements.into_iter()
248    }
249}
250impl<'a, T: MacroArg, P> IntoIterator for &'a NestedList<T, P> {
251    type Item = &'a T;
252    type IntoIter = std::slice::Iter<'a, T>;
253    #[inline]
254    fn into_iter(self) -> Self::IntoIter {
255        self.elements.iter()
256    }
257}
258// NOTE: Implemented manually to avoid bounds on `T`
259impl<T: MacroArg, P> Default for NestedList<T, P> {
260    fn default() -> Self {
261        NestedList {
262            brackets: Default::default(),
263            elements: Default::default(),
264            marker: PhantomData,
265        }
266    }
267}
268impl<T: MacroArg, P> Deref for NestedList<T, P> {
269    type Target = Vec<T>;
270    #[inline]
271    fn deref(&self) -> &Self::Target {
272        &self.elements
273    }
274}
275impl<T: MacroArg, P> DerefMut for NestedList<T, P> {
276    #[inline]
277    fn deref_mut(&mut self) -> &mut Self::Target {
278        &mut self.elements
279    }
280}
281impl<T: MacroArg, P: Parse> Parse for NestedList<T, P> {
282    fn parse(stream: ParseStream) -> syn::Result<Self> {
283        let content;
284        Ok(NestedList {
285            brackets: bracketed!(content in stream),
286            elements: Punctuated::<T, P>::parse_terminated_with(&content, T::parse_macro_arg)?
287                .into_iter()
288                .collect(),
289            marker: PhantomData,
290        })
291    }
292}
293parse_macro_arg_via_syn!(NestedList::<T, P>; for <T, P> where T: MacroArg, P: Parse);
294
295parse_macro_arg_via_syn!(Ident);
296parse_macro_arg_via_syn!(syn::Path);
297parse_macro_arg_via_syn!(syn::Type);
298parse_macro_arg_via_syn!(syn::GenericParam);
299parse_macro_arg_via_syn!(syn::Expr);
300parse_macro_arg_via_syn!(syn::Lifetime);
301parse_macro_arg_via_syn!(syn::LitStr);
302parse_macro_arg_via_syn!(syn::LitInt);
303parse_macro_arg_via_syn!(syn::LitFloat);
304parse_macro_arg_via_syn!(syn::LitBool);
305parse_macro_arg_via_syn!(syn::Lit);
306parse_macro_arg_via_syn!(syn::Meta);
307// TODO: What is the replacement for this in syn v2?
308// parse_macro_arg_via_syn!(syn::NestedMeta);
309parse_macro_arg_via_syn!(syn::Visibility);
310/// Wrapper type that parses via syn's [Parse] trait
311///
312/// Through this wrapper, any AST node can be parsed
313/// as a [MacroArg]
314#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
315pub struct Syn<T: Parse>(pub T);
316impl<T: Parse> Syn<T> {
317    /// Convert this type into its inner type
318    #[inline]
319    pub fn into_inner(self) -> T {
320        self.0
321    }
322}
323impl<T: Parse> From<T> for Syn<T> {
324    #[inline]
325    fn from(t: T) -> Syn<T> {
326        Syn(t)
327    }
328}
329impl<T: Parse> Parse for Syn<T> {
330    fn parse(stream: ParseStream) -> syn::Result<Self> {
331        Ok(Syn(stream.parse()?))
332    }
333}
334impl<T: Parse + ToTokens> ToTokens for Syn<T> {
335    fn to_tokens(&self, stream: &mut TokenStream) {
336        self.0.to_tokens(stream)
337    }
338    fn to_token_stream(&self) -> TokenStream {
339        self.0.to_token_stream()
340    }
341    fn into_token_stream(self) -> TokenStream {
342        self.0.into_token_stream()
343    }
344}
345impl<T: Parse> Deref for Syn<T> {
346    type Target = T;
347    #[inline]
348    fn deref(&self) -> &T {
349        &self.0
350    }
351}
352impl<T: Parse> DerefMut for Syn<T> {
353    #[inline]
354    fn deref_mut(&mut self) -> &mut T {
355        &mut self.0
356    }
357}
358parse_macro_arg_via_syn!(Syn::<T>; for <T> where T: Parse);
359
360/// Parses a `MacroArg` type from a string
361///
362/// Analogous to [syn::parse_str]
363pub fn parse_str<T: MacroArg>(s: &str) -> syn::Result<T> {
364    struct ParseWrapper<T: MacroArg>(T);
365    impl<T: MacroArg> Parse for ParseWrapper<T> {
366        fn parse(stream: ParseStream) -> syn::Result<Self> {
367            Ok(ParseWrapper(T::parse_macro_arg(stream)?))
368        }
369    }
370    syn::parse_str::<ParseWrapper<T>>(s).map(|wrap| wrap.0)
371}
372
373#[cfg(test)]
374mod test {
375    use super::*;
376    #[test]
377    fn ints() {
378        assert_eq!(parse_str::<i32>("5").unwrap(), 5);
379        assert_eq!(parse_str::<i32>("8").unwrap(), 8);
380    }
381    #[test]
382    fn strs() {
383        assert_eq!(
384            parse_str::<String>(r##""foo""##).unwrap(),
385            String::from("foo")
386        );
387    }
388    #[test]
389    fn explicit_option() {
390        assert_eq!(
391            parse_str::<ExplicitOption::<i32>>("None").unwrap(),
392            ExplicitOption(None)
393        );
394        assert_eq!(
395            parse_str::<ExplicitOption::<i32>>("Some(5)").unwrap(),
396            ExplicitOption(Some(5))
397        );
398        assert_eq!(
399            parse_str::<ExplicitOption::<String>>(r##"Some("foo")"##).unwrap(),
400            ExplicitOption(Some(String::from("foo")))
401        );
402    }
403}