1use std::iter::{Chain, Map, Once, once};
4use std::slice;
5use std::slice::IterMut;
6use std::vec::IntoIter;
7
8use crate::{Lex, Parse, ParseStream, Spanned, Token, TokenParseError, TokenStream};
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Spanned)]
16pub struct SeparatedPair<T, P = Token![,]> {
17 pub left: T,
19 pub punctuation: P,
21 pub right: T,
23}
24
25impl<T, P> SeparatedPair<T, P> {
26 pub fn new(left: T, punctuation: P, right: T) -> Self {
28 Self {
29 left,
30 punctuation,
31 right,
32 }
33 }
34
35 pub fn into_parts(self) -> (T, P, T) {
37 (self.left, self.punctuation, self.right)
38 }
39}
40
41impl<T: Parse, P: Parse> Parse for SeparatedPair<T, P> {
42 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
43 Ok(Self::new(
44 T::parse(input)?,
45 P::parse(input)?,
46 T::parse(input)?,
47 ))
48 }
49}
50
51impl<T: Lex, P: Lex> Lex for SeparatedPair<T, P> {
52 fn to_tokens(&self, output: &mut TokenStream) {
53 self.left.to_tokens(output);
54 self.punctuation.to_tokens(output);
55 self.right.to_tokens(output);
56 }
57}
58
59#[macro_export]
65macro_rules! punc {
66 (
67 pairs $first:expr;
68 $punctuation:expr => $second:expr
69 $(, $rest_punctuation:expr => $rest_value:expr)*
70 $(,)?
71 ) => {{
72 let mut values = $crate::Punctuated::new($first, $punctuation, $second);
73 $(values.push($rest_punctuation, $rest_value);)*
74 values
75 }};
76 ($value:ty) => {
77 $crate::Punctuated<$value>
78 };
79}
80
81#[derive(Debug, Clone, PartialEq, Eq, Spanned)]
100pub struct Punctuated<S, P = Token![,]> {
101 first: S,
103 second: (P, S),
105 rest: Vec<(P, S)>,
107}
108
109impl<S, P> Punctuated<S, P> {
110 pub fn new(first: S, punctuation: P, second: S) -> Self {
112 Self {
113 first,
114 second: (punctuation, second),
115 rest: Vec::new(),
116 }
117 }
118
119 pub fn from_pair(pair: SeparatedPair<S, P>) -> Self {
121 Self::from_pair_and_rest(pair, Vec::new())
122 }
123
124 pub fn from_pair_and_rest(pair: SeparatedPair<S, P>, rest: Vec<(P, S)>) -> Self {
127 let (left, punctuation, right) = pair.into_parts();
128 Self {
129 first: left,
130 second: (punctuation, right),
131 rest,
132 }
133 }
134
135 pub fn first(&self) -> &S {
137 &self.first
138 }
139
140 pub fn first_mut(&mut self) -> &mut S {
142 &mut self.first
143 }
144
145 pub fn pairs(&self) -> Pairs<'_, S, P> {
147 once(&self.second).chain(self.rest.iter())
148 }
149
150 pub fn pairs_mut(&mut self) -> PairsMut<'_, S, P> {
152 once(&mut self.second).chain(self.rest.iter_mut())
153 }
154
155 pub fn into_parts(self) -> (SeparatedPair<S, P>, Vec<(P, S)>) {
157 let (punctuation, second) = self.second;
158 (
159 SeparatedPair::new(self.first, punctuation, second),
160 self.rest,
161 )
162 }
163
164 pub fn len(&self) -> usize {
166 self.rest.len() + 2
167 }
168
169 pub const fn is_empty(&self) -> bool {
171 false
172 }
173
174 pub fn token_len(&self) -> usize {
176 self.rest.len() * 2 + 3
177 }
178
179 pub fn iter(&self) -> Values<'_, S, P> {
181 once(&self.first).chain(
182 self.pairs()
183 .map(rest_value_ref::<S, P> as fn(&(P, S)) -> &S),
184 )
185 }
186
187 pub fn iter_mut(&mut self) -> ValuesMut<'_, S, P> {
190 once(&mut self.first).chain(
191 once(&mut self.second)
192 .chain(self.rest.iter_mut())
193 .map(rest_value_mut::<S, P> as fn(&mut (P, S)) -> &mut S),
194 )
195 }
196
197 pub fn push(&mut self, punctuation: P, value: S) {
199 self.rest.push((punctuation, value));
200 }
201
202 pub fn map_values<T>(self, mut map: impl FnMut(S) -> T) -> Punctuated<T, P> {
204 let (pair, rest) = self.into_parts();
205 let (first, punctuation, second) = pair.into_parts();
206 Punctuated::from_pair_and_rest(
207 SeparatedPair::new(map(first), punctuation, map(second)),
208 rest.into_iter()
209 .map(|(punctuation, value)| (punctuation, map(value)))
210 .collect(),
211 )
212 }
213
214 pub fn try_map<T, Q, E>(
220 self,
221 mut map_value: impl FnMut(S) -> Result<T, E>,
222 mut map_punctuation: impl FnMut(P) -> Result<Q, E>,
223 ) -> Result<Punctuated<T, Q>, E> {
224 let (pair, rest) = self.into_parts();
225 let (first, punctuation, second) = pair.into_parts();
226 Ok(Punctuated::from_pair_and_rest(
227 SeparatedPair::new(
228 map_value(first)?,
229 map_punctuation(punctuation)?,
230 map_value(second)?,
231 ),
232 rest.into_iter()
233 .map(|(punctuation, value)| Ok((map_punctuation(punctuation)?, map_value(value)?)))
234 .collect::<Result<Vec<_>, E>>()?,
235 ))
236 }
237}
238
239impl<S: Lex, P: Lex> Lex for Punctuated<S, P> {
240 fn to_tokens(&self, output: &mut TokenStream) {
241 self.first.to_tokens(output);
242 for (punctuation, value) in self.pairs() {
243 punctuation.to_tokens(output);
244 value.to_tokens(output);
245 }
246 }
247}
248
249impl<S, P> Parse for Punctuated<S, P>
250where
251 S: Parse,
252 P: Parse + Token,
253{
254 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
255 let first = S::parse(input)?;
256 let punctuation = P::parse(input)?;
257 let second = S::parse(input)?;
258 let mut values = Self::new(first, punctuation, second);
259 while input.peek().is_some_and(P::matches_token_tree) {
260 let punctuation = P::parse(input)?;
261 values.push(punctuation, S::parse(input)?);
262 }
263 Ok(values)
264 }
265}
266
267pub type Pairs<'a, S, P> = Chain<Once<&'a (P, S)>, slice::Iter<'a, (P, S)>>;
269
270pub type PairsMut<'a, S, P> = Chain<Once<&'a mut (P, S)>, IterMut<'a, (P, S)>>;
272
273pub type Values<'a, S, P> = Chain<Once<&'a S>, Map<Pairs<'a, S, P>, fn(&(P, S)) -> &S>>;
275
276pub type ValuesMut<'a, S, P> =
278 Chain<Once<&'a mut S>, Map<PairsMut<'a, S, P>, fn(&mut (P, S)) -> &mut S>>;
279
280pub type IntoPairs<S, P> = Chain<Once<(P, S)>, IntoIter<(P, S)>>;
282
283pub type IntoValues<S, P> = Chain<Once<S>, Map<IntoPairs<S, P>, fn((P, S)) -> S>>;
285
286impl<S, P> IntoIterator for Punctuated<S, P> {
287 type Item = S;
288 type IntoIter = IntoValues<S, P>;
289
290 fn into_iter(self) -> Self::IntoIter {
291 once(self.first).chain(
292 once(self.second)
293 .chain(self.rest)
294 .map(rest_value::<S, P> as fn((P, S)) -> S),
295 )
296 }
297}
298
299impl<'a, S, P> IntoIterator for &'a Punctuated<S, P> {
300 type Item = &'a S;
301 type IntoIter = Values<'a, S, P>;
302
303 fn into_iter(self) -> Self::IntoIter {
304 self.iter()
305 }
306}
307
308impl<'a, S, P> IntoIterator for &'a mut Punctuated<S, P> {
309 type Item = &'a mut S;
310 type IntoIter = ValuesMut<'a, S, P>;
311
312 fn into_iter(self) -> Self::IntoIter {
313 self.iter_mut()
314 }
315}
316
317fn rest_value<S, P>((_, value): (P, S)) -> S {
319 value
320}
321
322fn rest_value_ref<S, P>((_, value): &(P, S)) -> &S {
324 value
325}
326
327fn rest_value_mut<S, P>((_, value): &mut (P, S)) -> &mut S {
329 value
330}
331
332#[cfg(test)]
333mod tests {
334 use super::*;
335
336 #[test]
337 fn a_sequence_is_nonempty_and_retains_separator_spans() {
338 let source = "+,+";
339 let values: Punctuated<Token![+], Token![,]> = crate::parse_fragment_str(source).unwrap();
340 let comma_span = values.pairs().next().unwrap().0.expect_span();
341
342 assert_eq!(values.len(), 2);
343 assert_eq!(values.token_len(), 3);
344 assert_eq!(comma_span.text(), Some(","));
345 assert_eq!(comma_span.bounds(), Some((1, 2)));
346 assert_eq!(values.to_m2(), "+,+");
347 }
348
349 #[test]
350 fn a_single_value_is_not_a_punctuated_sequence() {
351 let result = crate::parse_fragment_str::<Punctuated<Token![+]>>("+");
352
353 assert!(result.is_err());
354 }
355}