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,
102 second: (P, S),
103 rest: Vec<(P, S)>,
104}
105
106impl<S, P> Punctuated<S, P> {
107 pub fn new(first: S, punctuation: P, second: S) -> Self {
109 Self {
110 first,
111 second: (punctuation, second),
112 rest: Vec::new(),
113 }
114 }
115
116 pub fn from_pair(pair: SeparatedPair<S, P>) -> Self {
118 Self::from_pair_and_rest(pair, Vec::new())
119 }
120
121 pub fn from_pair_and_rest(pair: SeparatedPair<S, P>, rest: Vec<(P, S)>) -> Self {
124 let (left, punctuation, right) = pair.into_parts();
125 Self {
126 first: left,
127 second: (punctuation, right),
128 rest,
129 }
130 }
131
132 pub fn first(&self) -> &S {
134 &self.first
135 }
136
137 pub fn first_mut(&mut self) -> &mut S {
139 &mut self.first
140 }
141
142 pub fn pairs(&self) -> Pairs<'_, S, P> {
144 once(&self.second).chain(self.rest.iter())
145 }
146
147 pub fn pairs_mut(&mut self) -> PairsMut<'_, S, P> {
149 once(&mut self.second).chain(self.rest.iter_mut())
150 }
151
152 pub fn into_parts(self) -> (SeparatedPair<S, P>, Vec<(P, S)>) {
154 let (punctuation, second) = self.second;
155 (
156 SeparatedPair::new(self.first, punctuation, second),
157 self.rest,
158 )
159 }
160
161 pub fn len(&self) -> usize {
163 self.rest.len() + 2
164 }
165
166 pub const fn is_empty(&self) -> bool {
168 false
169 }
170
171 pub fn token_len(&self) -> usize {
173 self.rest.len() * 2 + 3
174 }
175
176 pub fn iter(&self) -> Values<'_, S, P> {
178 once(&self.first).chain(
179 self.pairs()
180 .map(rest_value_ref::<S, P> as fn(&(P, S)) -> &S),
181 )
182 }
183
184 pub fn iter_mut(&mut self) -> ValuesMut<'_, S, P> {
187 once(&mut self.first).chain(
188 once(&mut self.second)
189 .chain(self.rest.iter_mut())
190 .map(rest_value_mut::<S, P> as fn(&mut (P, S)) -> &mut S),
191 )
192 }
193
194 pub fn push(&mut self, punctuation: P, value: S) {
196 self.rest.push((punctuation, value));
197 }
198
199 pub fn map_values<T>(self, mut map: impl FnMut(S) -> T) -> Punctuated<T, P> {
201 let (pair, rest) = self.into_parts();
202 let (first, punctuation, second) = pair.into_parts();
203 Punctuated::from_pair_and_rest(
204 SeparatedPair::new(map(first), punctuation, map(second)),
205 rest.into_iter()
206 .map(|(punctuation, value)| (punctuation, map(value)))
207 .collect(),
208 )
209 }
210
211 pub fn try_map<T, Q, E>(
217 self,
218 mut map_value: impl FnMut(S) -> Result<T, E>,
219 mut map_punct: impl FnMut(P) -> Result<Q, E>,
220 ) -> Result<Punctuated<T, Q>, E> {
221 let (pair, rest) = self.into_parts();
222 let (first, punct, second) = pair.into_parts();
223 Ok(Punctuated::from_pair_and_rest(
224 SeparatedPair::new(map_value(first)?, map_punct(punct)?, map_value(second)?),
225 rest.into_iter()
226 .map(|(punct, value)| Ok((map_punct(punct)?, map_value(value)?)))
227 .collect::<Result<Vec<_>, E>>()?,
228 ))
229 }
230}
231
232impl<S: Lex, P: Lex> Lex for Punctuated<S, P> {
233 fn to_tokens(&self, output: &mut TokenStream) {
234 self.first.to_tokens(output);
235 for (punct, value) in self.pairs() {
236 punct.to_tokens(output);
237 value.to_tokens(output);
238 }
239 }
240}
241
242impl<S, P> Parse for Punctuated<S, P>
243where
244 S: Parse,
245 P: Parse + Token,
246{
247 fn parse(input: &mut ParseStream) -> Result<Self, TokenParseError> {
248 let first = S::parse(input)?;
249 let punct = P::parse(input)?;
250 let second = S::parse(input)?;
251 let mut values = Self::new(first, punct, second);
252 while input.peek().is_some_and(P::matches_token_tree) {
253 let punct = P::parse(input)?;
254 values.push(punct, S::parse(input)?);
255 }
256 Ok(values)
257 }
258}
259
260pub type Pairs<'a, S, P> = Chain<Once<&'a (P, S)>, slice::Iter<'a, (P, S)>>;
262
263pub type PairsMut<'a, S, P> = Chain<Once<&'a mut (P, S)>, IterMut<'a, (P, S)>>;
265
266pub type Values<'a, S, P> = Chain<Once<&'a S>, Map<Pairs<'a, S, P>, fn(&(P, S)) -> &S>>;
268
269pub type ValuesMut<'a, S, P> =
271 Chain<Once<&'a mut S>, Map<PairsMut<'a, S, P>, fn(&mut (P, S)) -> &mut S>>;
272
273pub type IntoPairs<S, P> = Chain<Once<(P, S)>, IntoIter<(P, S)>>;
275
276pub type IntoValues<S, P> = Chain<Once<S>, Map<IntoPairs<S, P>, fn((P, S)) -> S>>;
278
279impl<S, P> IntoIterator for Punctuated<S, P> {
280 type Item = S;
281 type IntoIter = IntoValues<S, P>;
282
283 fn into_iter(self) -> Self::IntoIter {
284 once(self.first).chain(
285 once(self.second)
286 .chain(self.rest)
287 .map(rest_value::<S, P> as fn((P, S)) -> S),
288 )
289 }
290}
291
292impl<'a, S, P> IntoIterator for &'a Punctuated<S, P> {
293 type Item = &'a S;
294 type IntoIter = Values<'a, S, P>;
295
296 fn into_iter(self) -> Self::IntoIter {
297 self.iter()
298 }
299}
300
301impl<'a, S, P> IntoIterator for &'a mut Punctuated<S, P> {
302 type Item = &'a mut S;
303 type IntoIter = ValuesMut<'a, S, P>;
304
305 fn into_iter(self) -> Self::IntoIter {
306 self.iter_mut()
307 }
308}
309
310fn rest_value<S, P>((_, value): (P, S)) -> S {
312 value
313}
314
315fn rest_value_ref<S, P>((_, value): &(P, S)) -> &S {
317 value
318}
319
320fn rest_value_mut<S, P>((_, value): &mut (P, S)) -> &mut S {
322 value
323}
324
325#[cfg(test)]
326mod tests {
327 use super::*;
328
329 #[test]
330 fn a_sequence_is_nonempty_and_retains_separator_spans() {
331 let source = "+,+";
332 let values: Punctuated<Token![+], Token![,]> = crate::parse_fragment_str(source).unwrap();
333 let comma_span = values.pairs().next().unwrap().0.expect_span();
334
335 assert_eq!(values.len(), 2);
336 assert_eq!(values.token_len(), 3);
337 assert_eq!(comma_span.text(), Some(","));
338 assert_eq!(comma_span.bounds(), Some((1, 2)));
339 assert_eq!(values.to_m2(), "+,+");
340 }
341
342 #[test]
343 fn a_single_value_is_not_a_punctuated_sequence() {
344 let result = crate::parse_fragment_str::<Punctuated<Token![+]>>("+");
345
346 assert!(result.is_err());
347 }
348}