1use std::iter::{Chain, Once, once};
4use std::{slice, vec};
5
6use crate::{Lex, Parse, ParseStream, Spanned, Token, TokenParseError, TokenStream};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Spanned)]
14pub struct PunctPair<L, P = Token![,], R = L> {
15 pub left: L,
17 pub punctuation: P,
19 pub right: R,
21}
22
23impl<L, P, R> PunctPair<L, P, R> {
24 pub fn new(left: L, punctuation: P, right: R) -> Self {
26 Self {
27 left,
28 punctuation,
29 right,
30 }
31 }
32
33 pub fn into_parts(self) -> (L, P, R) {
35 (self.left, self.punctuation, self.right)
36 }
37}
38
39impl<L: Parse, P: Parse, R: Parse> Parse for PunctPair<L, P, R> {
40 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
41 Ok(Self::new(
42 L::parse(input)?,
43 P::parse(input)?,
44 R::parse(input)?,
45 ))
46 }
47}
48
49impl<L: Lex, P: Lex, R: Lex> Lex for PunctPair<L, P, R> {
50 fn to_tokens(&self, output: &mut TokenStream) {
51 self.left.to_tokens(output);
52 self.punctuation.to_tokens(output);
53 self.right.to_tokens(output);
54 }
55}
56
57#[macro_export]
64macro_rules! punc {
65 (value $value:expr) => {
66 $crate::Punctuated::from_single($value)
67 };
68 (pairs $first:expr; $($punctuation:expr => $next:expr),+ $(,)?) => {{
69 let mut values = $crate::Punctuated::from_single($first);
70 $(values.push($punctuation, $next);)+
71 values
72 }};
73 ($value:ty) => {
74 $crate::Punctuated<$value>
75 };
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
97pub struct Punctuated<S, P = Token![,]> {
98 first: S,
99 rest: Vec<(P, S)>,
100}
101
102impl<S, P> Punctuated<S, P> {
103 pub fn new(first: S, rest: Vec<(P, S)>) -> Self {
106 Self { first, rest }
107 }
108
109 pub fn from_single(value: S) -> Self {
111 Self::new(value, Vec::new())
112 }
113
114 pub fn from_pair(pair: PunctPair<S, P>) -> Self {
116 let (left, punctuation, right) = pair.into_parts();
117 Self::new(left, vec![(punctuation, right)])
118 }
119
120 pub fn first(&self) -> &S {
122 &self.first
123 }
124
125 pub fn first_mut(&mut self) -> &mut S {
127 &mut self.first
128 }
129
130 pub fn rest(&self) -> &[(P, S)] {
132 &self.rest
133 }
134
135 pub fn rest_mut(&mut self) -> &mut [(P, S)] {
137 &mut self.rest
138 }
139
140 pub fn into_parts(self) -> (S, Vec<(P, S)>) {
142 (self.first, self.rest)
143 }
144
145 pub fn len(&self) -> usize {
147 self.rest.len() + 1
148 }
149
150 pub const fn is_empty(&self) -> bool {
152 false
153 }
154
155 pub fn token_len(&self) -> usize {
157 self.rest.len() * 2 + 1
158 }
159
160 pub fn iter(&self) -> Values<'_, S, P> {
162 once(&self.first).chain(
163 self.rest
164 .iter()
165 .map(rest_value_ref::<S, P> as fn(&(P, S)) -> &S),
166 )
167 }
168
169 pub fn iter_mut(&mut self) -> ValuesMut<'_, S, P> {
172 once(&mut self.first).chain(
173 self.rest
174 .iter_mut()
175 .map(rest_value_mut::<S, P> as fn(&mut (P, S)) -> &mut S),
176 )
177 }
178
179 pub fn push(&mut self, punctuation: P, value: S) {
181 self.rest.push((punctuation, value));
182 }
183}
184
185impl<S: Lex, P: Lex> Lex for Punctuated<S, P> {
186 fn to_tokens(&self, output: &mut TokenStream) {
187 self.first.to_tokens(output);
188 for (punctuation, value) in &self.rest {
189 punctuation.to_tokens(output);
190 value.to_tokens(output);
191 }
192 }
193}
194
195impl<S, P> Parse for Punctuated<S, P>
196where
197 S: Parse,
198 P: Parse + Token,
199{
200 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
201 let first = S::parse(input)?;
202 let mut values = Self::from_single(first);
203 while input.peek().is_some_and(P::matches_token_tree) {
204 let punctuation = P::parse(input)?;
205 values.push(punctuation, S::parse(input)?);
206 }
207 Ok(values)
208 }
209}
210
211pub type Values<'a, S, P> =
213 Chain<Once<&'a S>, std::iter::Map<slice::Iter<'a, (P, S)>, fn(&(P, S)) -> &S>>;
214
215pub type ValuesMut<'a, S, P> =
217 Chain<Once<&'a mut S>, std::iter::Map<slice::IterMut<'a, (P, S)>, fn(&mut (P, S)) -> &mut S>>;
218
219pub type IntoValues<S, P> = Chain<Once<S>, std::iter::Map<vec::IntoIter<(P, S)>, fn((P, S)) -> S>>;
221
222impl<S, P> IntoIterator for Punctuated<S, P> {
223 type Item = S;
224 type IntoIter = IntoValues<S, P>;
225
226 fn into_iter(self) -> Self::IntoIter {
227 once(self.first).chain(
228 self.rest
229 .into_iter()
230 .map(rest_value::<S, P> as fn((P, S)) -> S),
231 )
232 }
233}
234
235impl<'a, S, P> IntoIterator for &'a Punctuated<S, P> {
236 type Item = &'a S;
237 type IntoIter = Values<'a, S, P>;
238
239 fn into_iter(self) -> Self::IntoIter {
240 self.iter()
241 }
242}
243
244impl<'a, S, P> IntoIterator for &'a mut Punctuated<S, P> {
245 type Item = &'a mut S;
246 type IntoIter = ValuesMut<'a, S, P>;
247
248 fn into_iter(self) -> Self::IntoIter {
249 self.iter_mut()
250 }
251}
252
253fn rest_value<S, P>((_, value): (P, S)) -> S {
254 value
255}
256
257fn rest_value_ref<S, P>((_, value): &(P, S)) -> &S {
258 value
259}
260
261fn rest_value_mut<S, P>((_, value): &mut (P, S)) -> &mut S {
262 value
263}
264
265#[cfg(test)]
266mod tests {
267 use super::*;
268 use crate::Span;
269
270 #[test]
271 fn a_sequence_is_nonempty_and_retains_separator_spans() {
272 let comma_span = Span::new(1, 2);
273 let values = Punctuated::new(
274 Token),
275 vec, Token))],
276 );
277
278 assert_eq!(values.len(), 2);
279 assert_eq!(values.token_len(), 3);
280 assert_eq!(values.rest()[0].0.span().bounds(), comma_span.bounds());
281 assert_eq!(values.to_m2(), "+,+");
282 }
283}