1use 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
15pub trait MacroArg: Sized {
28 fn parse_macro_arg(stream: ParseStream) -> syn::Result<Self>;
30}
31
32impl<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
43macro_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#[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
79pub trait MacroDictKey: MacroArg + Eq + Hash + Spanned {}
84impl<T: ?Sized + MacroArg + Eq + Hash + Spanned> MacroDictKey for T {}
85
86#[derive(Debug, Clone, Eq, PartialEq)]
88pub struct KeyValuePair<K: MacroDictKey, V: MacroArg> {
89 pub key: K,
91 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
104pub struct NestedDict<K: MacroDictKey, V: MacroArg> {
113 pub braces: syn::token::Brace,
115 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#[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 Err(stream.error("Expected either `Some` or `None`"))
201 }
202}
203
204#[derive(PartialEq, Eq, Debug, Hash)]
209pub struct NestedList<T: MacroArg, P = Token![,]> {
210 pub brackets: syn::token::Bracket,
212 pub elements: Vec<T>,
214 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}
258impl<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);
307parse_macro_arg_via_syn!(syn::Visibility);
310#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
315pub struct Syn<T: Parse>(pub T);
316impl<T: Parse> Syn<T> {
317 #[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
360pub 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}