macroific_attr_parse/
delimited_iter.rs

1use std::marker::PhantomData;
2use std::ops::Deref;
3
4use syn::parse::{Parse, ParseBuffer, ParseStream};
5
6/// Like `Cow` but without the clone requirement
7enum PossiblyBorrowed<'a, T> {
8    Borrowed(&'a T),
9    Owned(T),
10}
11impl<'a, T> Deref for PossiblyBorrowed<'a, T> {
12    type Target = T;
13
14    fn deref(&self) -> &Self::Target {
15        match *self {
16            PossiblyBorrowed::Borrowed(b) => b,
17            PossiblyBorrowed::Owned(ref o) => o,
18        }
19    }
20}
21
22/// [`Punctuated`](syn::punctuated::Punctuated), in iterator form
23pub struct DelimitedIter<'a, T, D> {
24    parse: PossiblyBorrowed<'a, ParseBuffer<'a>>,
25    errored: bool,
26    _marker: PhantomData<(T, D)>,
27}
28
29impl<'a, T, D> DelimitedIter<'a, T, D> {
30    /// Construct an iterator from the stream and delimiter
31    pub const fn new(parse: ParseStream<'a>) -> Self {
32        Self::construct(PossiblyBorrowed::Borrowed(parse))
33    }
34
35    /// Construct an iterator from the buffer and a delimiter
36    pub const fn new_buffer(parse: ParseBuffer<'a>) -> Self {
37        Self::construct(PossiblyBorrowed::Owned(parse))
38    }
39
40    #[inline]
41    const fn construct(parse: PossiblyBorrowed<'a, ParseBuffer<'a>>) -> Self {
42        Self {
43            parse,
44            errored: false,
45            _marker: PhantomData,
46        }
47    }
48
49    #[inline]
50    #[allow(clippy::unnecessary_wraps)]
51    fn on_error(&mut self, err: syn::Error) -> Option<syn::Result<T>> {
52        self.errored = true;
53        Some(Err(err))
54    }
55}
56
57impl<'a, T, D> From<ParseStream<'a>> for DelimitedIter<'a, T, D> {
58    #[inline]
59    fn from(value: ParseStream<'a>) -> Self {
60        Self::new(value)
61    }
62}
63
64impl<'a, T, D> From<ParseBuffer<'a>> for DelimitedIter<'a, T, D> {
65    #[inline]
66    fn from(value: ParseBuffer<'a>) -> Self {
67        Self::new_buffer(value)
68    }
69}
70
71impl<'a, T: Parse, D: Parse> Iterator for DelimitedIter<'a, T, D> {
72    type Item = syn::Result<T>;
73
74    fn next(&mut self) -> Option<Self::Item> {
75        if self.parse.is_empty() || self.errored {
76            return None;
77        }
78
79        let output = match self.parse.parse::<T>() {
80            Ok(o) => o,
81            Err(e) => return self.on_error(e),
82        };
83
84        if self.parse.is_empty() {
85            return Some(Ok(output));
86        }
87
88        if let Err(e) = self.parse.parse::<D>() {
89            return self.on_error(e);
90        }
91
92        Some(Ok(output))
93    }
94}