macroscope/
separated.rs

1use std::marker::PhantomData;
2
3use quote::{quote, ToTokens};
4use syn::{
5    parse::{Parse, ParseStream},
6    punctuated::Punctuated,
7};
8
9pub trait ParseFrom {
10    type Item: Parse;
11
12    fn parse_from(input: ParseStream<'_>) -> syn::Result<Self::Item>;
13}
14
15impl<T> ParseFrom for T
16where
17    T: Parse,
18{
19    type Item = T;
20
21    fn parse_from(input: ParseStream<'_>) -> syn::Result<Self::Item> {
22        T::parse(input)
23    }
24}
25
26#[derive(Debug)]
27pub struct Separated<T, S, P = T>
28where
29    T: Parse,
30    S: Parse,
31    P: ParseFrom,
32{
33    punctuated: Punctuated<T, S>,
34    parse: PhantomData<P>,
35}
36
37transparent_wrapper!(Separated<T, S, P> where { T: Parse, S: Parse, P: ParseFrom } => self.punctuated as Punctuated<T, S>);
38
39impl<T, S, P> ToTokens for Separated<T, S, P>
40where
41    T: ToTokens + Parse,
42    S: ToTokens + Parse,
43    P: ParseFrom<Item = T>,
44{
45    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
46        let p = &self.punctuated;
47        tokens.extend(quote!(#p))
48    }
49}
50
51impl<T, S, P> Parse for Separated<T, S, P>
52where
53    T: Parse,
54    S: Parse,
55    P: ParseFrom<Item = T>,
56{
57    fn parse(input: syn::parse::ParseStream) -> syn::Result<Self> {
58        let punctuated = Punctuated::parse_terminated_with(&input, |stream| P::parse_from(stream))?;
59
60        Ok(Separated {
61            punctuated,
62            parse: PhantomData,
63        })
64    }
65}