bevy_reflect_derive/
attribute_parser.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use syn::{
    parse::{Parse, ParseStream, Peek},
    punctuated::Punctuated,
};

/// Returns a [`syn::parse::Parser`] which parses a stream of zero or more occurrences of `T`
/// separated by punctuation of type `P`, with optional trailing punctuation.
///
/// This is functionally the same as [`Punctuated::parse_terminated`],
/// but accepts a closure rather than a function pointer.
pub(crate) fn terminated_parser<T, P, F: FnMut(ParseStream) -> syn::Result<T>>(
    terminator: P,
    mut parser: F,
) -> impl FnOnce(ParseStream) -> syn::Result<Punctuated<T, P::Token>>
where
    P: Peek,
    P::Token: Parse,
{
    let _ = terminator;
    move |stream: ParseStream| {
        let mut punctuated = Punctuated::new();

        loop {
            if stream.is_empty() {
                break;
            }
            let value = parser(stream)?;
            punctuated.push_value(value);
            if stream.is_empty() {
                break;
            }
            let punct = stream.parse()?;
            punctuated.push_punct(punct);
        }

        Ok(punctuated)
    }
}