syn_prelude/
parse_terminate_until.rs

1use syn::{
2    parse::{Parse, ParseStream, Peek},
3    punctuated::Punctuated,
4};
5
6pub trait ParseTerminatedUntil {
7    fn parse_terminated_until<T, P>(
8        &self,
9        parser: fn(ParseStream) -> syn::Result<T>,
10        separator: P,
11    ) -> syn::Result<Punctuated<T, P::Token>>
12    where
13        P: Peek,
14        P::Token: Parse;
15}
16
17impl ParseTerminatedUntil for ParseStream<'_> {
18    fn parse_terminated_until<T, P>(
19        &self,
20        parser: fn(ParseStream) -> syn::Result<T>,
21        separator: P,
22    ) -> syn::Result<Punctuated<T, P::Token>>
23    where
24        P: Peek,
25        P::Token: Parse,
26    {
27        let _ = separator;
28        let mut punctuated = Punctuated::new();
29
30        loop {
31            if self.is_empty() {
32                break;
33            }
34            punctuated.push_value(parser(self)?);
35            if self.is_empty() {
36                break;
37            }
38            if self.peek(separator) {
39                punctuated.push_punct(self.parse()?);
40            } else {
41                break;
42            }
43        }
44
45        Ok(punctuated)
46    }
47}