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}