macroific_attr_parse/
delimited_iter.rs1use std::marker::PhantomData;
2use std::ops::Deref;
3
4use syn::parse::{Parse, ParseBuffer, ParseStream};
5
6enum 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
22pub 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 pub const fn new(parse: ParseStream<'a>) -> Self {
32 Self::construct(PossiblyBorrowed::Borrowed(parse))
33 }
34
35 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}