bevy_reflect_derive/
attribute_parser.rs

1use syn::{
2    parse::{Parse, ParseStream, Peek},
3    punctuated::Punctuated,
4};
5
6/// Returns a [`syn::parse::Parser`] which parses a stream of zero or more occurrences of `T`
7/// separated by punctuation of type `P`, with optional trailing punctuation.
8///
9/// This is functionally the same as [`Punctuated::parse_terminated`],
10/// but accepts a closure rather than a function pointer.
11pub(crate) fn terminated_parser<T, P, F: FnMut(ParseStream) -> syn::Result<T>>(
12    terminator: P,
13    mut parser: F,
14) -> impl FnOnce(ParseStream) -> syn::Result<Punctuated<T, P::Token>>
15where
16    P: Peek,
17    P::Token: Parse,
18{
19    let _ = terminator;
20    move |stream: ParseStream| {
21        let mut punctuated = Punctuated::new();
22
23        loop {
24            if stream.is_empty() {
25                break;
26            }
27            let value = parser(stream)?;
28            punctuated.push_value(value);
29            if stream.is_empty() {
30                break;
31            }
32            let punct = stream.parse()?;
33            punctuated.push_punct(punct);
34        }
35
36        Ok(punctuated)
37    }
38}