blob: 5aa519ffeb5e49e611611545886de26693e62f00 [file] [log] [blame]
David Tolnayf3198012018-01-06 20:00:42 -08001//! A punctuated sequence of syntax tree nodes separated by punctuation.
2//!
3//! Lots of things in Rust are punctuated sequences.
4//!
5//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
6//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
David Tolnayc8b0e0f2019-03-07 22:46:32 -08007//! - The bounds on a generic parameter are `Punctuated<TypeParamBound,
8//! Token![+]>`.
David Tolnayf3198012018-01-06 20:00:42 -08009//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
10//!
11//! This module provides a common representation for these punctuated sequences
12//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
13//! syntax tree node + punctuation, where every node in the sequence is followed
14//! by punctuation except for possibly the final one.
15//!
16//! [`Punctuated<T, P>`]: struct.Punctuated.html
17//!
18//! ```text
19//! a_function_call(arg1, arg2, arg3);
20//! ^^^^^ ~~~~~ ^^^^
21//! ```
22
David Tolnay94d2b792018-04-29 12:26:10 -070023#[cfg(feature = "extra-traits")]
24use std::fmt::{self, Debug};
David Tolnay6c0a6092018-03-31 22:47:39 +020025#[cfg(any(feature = "full", feature = "derive"))]
26use std::iter;
27use std::iter::FromIterator;
David Tolnay82712022019-04-22 15:15:40 -070028use std::marker::PhantomData;
David Tolnaybb987132018-01-08 13:51:19 -080029use std::ops::{Index, IndexMut};
Mateusz Naściszewski14111202018-04-11 21:17:41 +020030use std::option;
Alex Crichtonccbb45d2017-05-23 10:58:24 -070031use std::slice;
32use std::vec;
33
David Tolnayf3198012018-01-06 20:00:42 -080034#[cfg(feature = "parsing")]
David Tolnayecf0fbc2018-08-30 18:28:33 -070035use parse::{Parse, ParseStream, Result};
David Tolnay94f06632018-08-31 10:17:17 -070036#[cfg(any(feature = "full", feature = "derive"))]
37use private;
David Tolnay52619f62018-08-31 09:30:01 -070038#[cfg(feature = "parsing")]
39use token::Token;
David Tolnayf3198012018-01-06 20:00:42 -080040
41/// A punctuated sequence of syntax tree nodes of type `T` separated by
42/// punctuation of type `P`.
43///
44/// Refer to the [module documentation] for details about punctuated sequences.
45///
46/// [module documentation]: index.html
Nika Layzelld73a3652017-10-24 08:57:05 -040047#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070048#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -050049pub struct Punctuated<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020050 inner: Vec<(T, P)>,
51 last: Option<Box<T>>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070052}
53
David Tolnayf2cfd722017-12-31 18:02:51 -050054impl<T, P> Punctuated<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -080055 /// Creates an empty punctuated sequence.
David Tolnayf2cfd722017-12-31 18:02:51 -050056 pub fn new() -> Punctuated<T, P> {
David Tolnay94d2b792018-04-29 12:26:10 -070057 Punctuated {
58 inner: Vec::new(),
59 last: None,
60 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070061 }
62
David Tolnayf3198012018-01-06 20:00:42 -080063 /// Determines whether this punctuated sequence is empty, meaning it
64 /// contains no syntax tree nodes or punctuation.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070065 pub fn is_empty(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020066 self.inner.len() == 0 && self.last.is_none()
Alex Crichtonccbb45d2017-05-23 10:58:24 -070067 }
68
David Tolnayf3198012018-01-06 20:00:42 -080069 /// Returns the number of syntax tree nodes in this punctuated sequence.
70 ///
71 /// This is the number of nodes of type `T`, not counting the punctuation of
72 /// type `P`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070073 pub fn len(&self) -> usize {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020074 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070075 }
76
David Tolnayf3198012018-01-06 20:00:42 -080077 /// Borrows the first punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080078 pub fn first(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020079 self.pairs().next()
Alex Crichton0aa50e02017-07-07 20:59:03 -070080 }
81
David Tolnayf3198012018-01-06 20:00:42 -080082 /// Borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080083 pub fn last(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020084 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -070085 self.last.as_ref().map(|t| Pair::End(t.as_ref()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +020086 } else {
David Tolnay94d2b792018-04-29 12:26:10 -070087 self.inner
88 .last()
Mateusz Naściszewski14111202018-04-11 21:17:41 +020089 .map(|&(ref t, ref d)| Pair::Punctuated(t, d))
90 }
Alex Crichton0aa50e02017-07-07 20:59:03 -070091 }
92
David Tolnayf3198012018-01-06 20:00:42 -080093 /// Mutably borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080094 pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020095 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -070096 self.last.as_mut().map(|t| Pair::End(t.as_mut()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +020097 } else {
David Tolnay94d2b792018-04-29 12:26:10 -070098 self.inner
99 .last_mut()
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200100 .map(|&mut (ref mut t, ref mut d)| Pair::Punctuated(t, d))
101 }
Alex Crichton0aa50e02017-07-07 20:59:03 -0700102 }
103
David Tolnayf3198012018-01-06 20:00:42 -0800104 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
David Tolnay8095c302018-03-31 19:34:17 +0200105 pub fn iter(&self) -> Iter<T> {
David Tolnay51382052017-12-27 13:46:21 -0500106 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200107 inner: Box::new(PrivateIter {
108 inner: self.inner.iter(),
David Tolnay124e50b2019-02-28 23:53:36 -0800109 last: self.last.as_ref().map(Box::as_ref).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200110 }),
David Tolnay51382052017-12-27 13:46:21 -0500111 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700112 }
113
David Tolnayf3198012018-01-06 20:00:42 -0800114 /// Returns an iterator over mutably borrowed syntax tree nodes of type
115 /// `&mut T`.
David Tolnay8095c302018-03-31 19:34:17 +0200116 pub fn iter_mut(&mut self) -> IterMut<T> {
David Tolnaya0834b42018-01-01 21:30:02 -0800117 IterMut {
David Tolnay8095c302018-03-31 19:34:17 +0200118 inner: Box::new(PrivateIterMut {
119 inner: self.inner.iter_mut(),
David Tolnay124e50b2019-02-28 23:53:36 -0800120 last: self.last.as_mut().map(Box::as_mut).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200121 }),
David Tolnaya0834b42018-01-01 21:30:02 -0800122 }
123 }
124
David Tolnayf3198012018-01-06 20:00:42 -0800125 /// Returns an iterator over the contents of this sequence as borrowed
126 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800127 pub fn pairs(&self) -> Pairs<T, P> {
128 Pairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800129 inner: self.inner.iter(),
David Tolnay124e50b2019-02-28 23:53:36 -0800130 last: self.last.as_ref().map(Box::as_ref).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800131 }
132 }
133
David Tolnayf3198012018-01-06 20:00:42 -0800134 /// Returns an iterator over the contents of this sequence as mutably
135 /// borrowed punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800136 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
137 PairsMut {
David Tolnay51382052017-12-27 13:46:21 -0500138 inner: self.inner.iter_mut(),
David Tolnay124e50b2019-02-28 23:53:36 -0800139 last: self.last.as_mut().map(Box::as_mut).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500140 }
Alex Crichton164c5332017-07-06 13:18:34 -0700141 }
142
David Tolnayf3198012018-01-06 20:00:42 -0800143 /// Returns an iterator over the contents of this sequence as owned
144 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800145 pub fn into_pairs(self) -> IntoPairs<T, P> {
146 IntoPairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800147 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200148 last: self.last.map(|t| *t).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800149 }
150 }
151
David Tolnayf3198012018-01-06 20:00:42 -0800152 /// Appends a syntax tree node onto the end of this punctuated sequence. The
153 /// sequence must previously have a trailing punctuation.
154 ///
155 /// Use [`push`] instead if the punctuated sequence may or may not already
156 /// have trailing punctuation.
157 ///
158 /// [`push`]: #method.push
159 ///
160 /// # Panics
161 ///
162 /// Panics if the sequence does not already have a trailing punctuation when
163 /// this method is called.
David Tolnay56080682018-01-06 14:01:52 -0800164 pub fn push_value(&mut self, value: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -0500165 assert!(self.empty_or_trailing());
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200166 self.last = Some(Box::new(value));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700167 }
168
David Tolnayf3198012018-01-06 20:00:42 -0800169 /// Appends a trailing punctuation onto the end of this punctuated sequence.
170 /// The sequence must be non-empty and must not already have trailing
171 /// punctuation.
172 ///
173 /// # Panics
174 ///
175 /// Panics if the sequence is empty or already has a trailing punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800176 pub fn push_punct(&mut self, punctuation: P) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200177 assert!(self.last.is_some());
David Tolnay03163082018-04-11 12:10:18 -0700178 let last = self.last.take().unwrap();
179 self.inner.push((*last, punctuation));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700180 }
181
David Tolnayf3198012018-01-06 20:00:42 -0800182 /// Removes the last punctuated pair from this sequence, or `None` if the
183 /// sequence is empty.
David Tolnay56080682018-01-06 14:01:52 -0800184 pub fn pop(&mut self) -> Option<Pair<T, P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200185 if self.last.is_some() {
David Tolnay03163082018-04-11 12:10:18 -0700186 self.last.take().map(|t| Pair::End(*t))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200187 } else {
188 self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d))
189 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700190 }
191
David Tolnayf3198012018-01-06 20:00:42 -0800192 /// Determines whether this punctuated sequence ends with a trailing
193 /// punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800194 pub fn trailing_punct(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200195 self.last.is_none() && !self.is_empty()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700196 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400197
David Tolnayf2cfd722017-12-31 18:02:51 -0500198 /// Returns true if either this `Punctuated` is empty, or it has a trailing
199 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -0500200 ///
David Tolnaya0834b42018-01-01 21:30:02 -0800201 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -0400202 pub fn empty_or_trailing(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200203 self.last.is_none()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400204 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700205
David Tolnayf3198012018-01-06 20:00:42 -0800206 /// Appends a syntax tree node onto the end of this punctuated sequence.
207 ///
208 /// If there is not a trailing punctuation in this sequence when this method
209 /// is called, the default value of punctuation type `P` is inserted before
210 /// the given value of type `T`.
David Tolnay8842c7e2018-09-01 12:37:32 -0700211 pub fn push(&mut self, value: T)
212 where
213 P: Default,
214 {
David Tolnaya0834b42018-01-01 21:30:02 -0800215 if !self.empty_or_trailing() {
216 self.push_punct(Default::default());
217 }
David Tolnay56080682018-01-06 14:01:52 -0800218 self.push_value(value);
David Tolnaya0834b42018-01-01 21:30:02 -0800219 }
David Tolnayb77d1802018-01-11 16:18:35 -0800220
221 /// Inserts an element at position `index`.
222 ///
223 /// # Panics
224 ///
225 /// Panics if `index` is greater than the number of elements previously in
226 /// this punctuated sequence.
David Tolnay8842c7e2018-09-01 12:37:32 -0700227 pub fn insert(&mut self, index: usize, value: T)
228 where
229 P: Default,
230 {
David Tolnayb77d1802018-01-11 16:18:35 -0800231 assert!(index <= self.len());
232
233 if index == self.len() {
234 self.push(value);
235 } else {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200236 self.inner.insert(index, (value, Default::default()));
David Tolnayb77d1802018-01-11 16:18:35 -0800237 }
238 }
David Tolnay8842c7e2018-09-01 12:37:32 -0700239
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700240 /// Parses zero or more occurrences of `T` separated by punctuation of type
241 /// `P`, with optional trailing punctuation.
242 ///
243 /// Parsing continues until the end of this parse stream. The entire content
244 /// of this parse stream must consist of `T` and `P`.
David Tolnay206edfb2018-09-01 16:02:20 -0700245 ///
246 /// *This function is available if Syn is built with the `"parsing"`
247 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700248 #[cfg(feature = "parsing")]
249 pub fn parse_terminated(input: ParseStream) -> Result<Self>
250 where
251 T: Parse,
252 P: Parse,
253 {
254 Self::parse_terminated_with(input, T::parse)
255 }
256
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700257 /// Parses zero or more occurrences of `T` using the given parse function,
258 /// separated by punctuation of type `P`, with optional trailing
259 /// punctuation.
260 ///
261 /// Like [`parse_terminated`], the entire content of this stream is expected
262 /// to be parsed.
263 ///
264 /// [`parse_terminated`]: #method.parse_terminated
David Tolnay206edfb2018-09-01 16:02:20 -0700265 ///
266 /// *This function is available if Syn is built with the `"parsing"`
267 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700268 #[cfg(feature = "parsing")]
269 pub fn parse_terminated_with(
270 input: ParseStream,
271 parser: fn(ParseStream) -> Result<T>,
272 ) -> Result<Self>
273 where
274 P: Parse,
275 {
276 let mut punctuated = Punctuated::new();
277
278 loop {
279 if input.is_empty() {
280 break;
281 }
282 let value = parser(input)?;
283 punctuated.push_value(value);
284 if input.is_empty() {
285 break;
286 }
287 let punct = input.parse()?;
288 punctuated.push_punct(punct);
289 }
290
291 Ok(punctuated)
292 }
293
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700294 /// Parses one or more occurrences of `T` separated by punctuation of type
295 /// `P`, not accepting trailing punctuation.
296 ///
297 /// Parsing continues as long as punctuation `P` is present at the head of
298 /// the stream. This method returns upon parsing a `T` and observing that it
299 /// is not followed by a `P`, even if there are remaining tokens in the
300 /// stream.
David Tolnay206edfb2018-09-01 16:02:20 -0700301 ///
302 /// *This function is available if Syn is built with the `"parsing"`
303 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700304 #[cfg(feature = "parsing")]
305 pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
306 where
307 T: Parse,
308 P: Token + Parse,
309 {
310 Self::parse_separated_nonempty_with(input, T::parse)
311 }
312
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700313 /// Parses one or more occurrences of `T` using the given parse function,
314 /// separated by punctuation of type `P`, not accepting trailing
315 /// punctuation.
316 ///
317 /// Like [`parse_separated_nonempty`], may complete early without parsing
318 /// the entire content of this stream.
319 ///
320 /// [`parse_separated_nonempty`]: #method.parse_separated_nonempty
David Tolnay206edfb2018-09-01 16:02:20 -0700321 ///
322 /// *This function is available if Syn is built with the `"parsing"`
323 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700324 #[cfg(feature = "parsing")]
325 pub fn parse_separated_nonempty_with(
326 input: ParseStream,
327 parser: fn(ParseStream) -> Result<T>,
328 ) -> Result<Self>
329 where
330 P: Token + Parse,
331 {
332 let mut punctuated = Punctuated::new();
333
334 loop {
335 let value = parser(input)?;
336 punctuated.push_value(value);
337 if !P::peek(input.cursor()) {
338 break;
339 }
340 let punct = input.parse()?;
341 punctuated.push_punct(punct);
342 }
343
344 Ok(punctuated)
345 }
David Tolnaya0834b42018-01-01 21:30:02 -0800346}
347
Nika Layzelld73a3652017-10-24 08:57:05 -0400348#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -0500349impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -0400350 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200351 let mut list = f.debug_list();
David Tolnay0c18c512018-07-22 10:39:10 -0700352 for &(ref t, ref p) in &self.inner {
353 list.entry(t);
354 list.entry(p);
355 }
356 if let Some(ref last) = self.last {
357 list.entry(last);
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200358 }
359 list.finish()
Nika Layzelld73a3652017-10-24 08:57:05 -0400360 }
361}
362
David Tolnay9ef24bc2018-01-09 10:43:55 -0800363impl<T, P> FromIterator<T> for Punctuated<T, P>
364where
365 P: Default,
366{
367 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
368 let mut ret = Punctuated::new();
369 ret.extend(i);
370 ret
371 }
372}
373
374impl<T, P> Extend<T> for Punctuated<T, P>
375where
376 P: Default,
377{
378 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
379 for value in i {
380 self.push(value);
381 }
382 }
383}
384
David Tolnay56080682018-01-06 14:01:52 -0800385impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
386 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500387 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700388 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700389 ret
390 }
391}
392
David Tolnay56080682018-01-06 14:01:52 -0800393impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
394 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200395 assert!(self.empty_or_trailing());
396 let mut nomore = false;
David Tolnay56080682018-01-06 14:01:52 -0800397 for pair in i {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200398 if nomore {
399 panic!("Punctuated extended with items after a Pair::End");
400 }
David Tolnay56080682018-01-06 14:01:52 -0800401 match pair {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200402 Pair::Punctuated(a, b) => self.inner.push((a, b)),
403 Pair::End(a) => {
404 self.last = Some(Box::new(a));
405 nomore = true;
406 }
Alex Crichton24f12822017-07-14 07:15:32 -0700407 }
408 }
409 }
410}
411
David Tolnayf2cfd722017-12-31 18:02:51 -0500412impl<T, P> IntoIterator for Punctuated<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800413 type Item = T;
David Tolnayf2cfd722017-12-31 18:02:51 -0500414 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700415
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500416 fn into_iter(self) -> Self::IntoIter {
David Tolnay82712022019-04-22 15:15:40 -0700417 let mut elements = Vec::with_capacity(self.len());
418 elements.extend(self.inner.into_iter().map(|pair| pair.0));
419 elements.extend(self.last.map(|t| *t));
420
David Tolnay51382052017-12-27 13:46:21 -0500421 IntoIter {
David Tolnay82712022019-04-22 15:15:40 -0700422 inner: elements.into_iter(),
423 marker: PhantomData,
David Tolnay51382052017-12-27 13:46:21 -0500424 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700425 }
426}
427
David Tolnay6eff4da2018-01-01 20:27:45 -0800428impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
429 type Item = &'a T;
David Tolnay8095c302018-03-31 19:34:17 +0200430 type IntoIter = Iter<'a, T>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800431
432 fn into_iter(self) -> Self::IntoIter {
433 Punctuated::iter(self)
434 }
435}
436
David Tolnaya0834b42018-01-01 21:30:02 -0800437impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
438 type Item = &'a mut T;
David Tolnay8095c302018-03-31 19:34:17 +0200439 type IntoIter = IterMut<'a, T>;
David Tolnaya0834b42018-01-01 21:30:02 -0800440
441 fn into_iter(self) -> Self::IntoIter {
442 Punctuated::iter_mut(self)
443 }
444}
445
David Tolnayf2cfd722017-12-31 18:02:51 -0500446impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700447 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500448 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700449 }
450}
451
David Tolnayf3198012018-01-06 20:00:42 -0800452/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
453///
454/// Refer to the [module documentation] for details about punctuated sequences.
455///
456/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800457pub struct Pairs<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200458 inner: slice::Iter<'a, (T, P)>,
459 last: option::IntoIter<&'a T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700460}
461
David Tolnay56080682018-01-06 14:01:52 -0800462impl<'a, T, P> Iterator for Pairs<'a, T, P> {
463 type Item = Pair<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700464
David Tolnay6eff4da2018-01-01 20:27:45 -0800465 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700466 self.inner
467 .next()
468 .map(|&(ref t, ref p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700469 .or_else(|| self.last.next().map(Pair::End))
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700470 }
471}
472
David Tolnay9700be02018-04-30 00:51:15 -0700473impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
474 fn len(&self) -> usize {
475 self.inner.len() + self.last.len()
476 }
477}
478
David Tolnay7f3f13e2019-04-22 10:55:30 -0700479// No Clone bound on T or P.
480impl<'a, T, P> Clone for Pairs<'a, T, P> {
481 fn clone(&self) -> Self {
482 Pairs {
483 inner: self.inner.clone(),
484 last: self.last.clone(),
485 }
486 }
487}
488
David Tolnayf3198012018-01-06 20:00:42 -0800489/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
490///
491/// Refer to the [module documentation] for details about punctuated sequences.
492///
493/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800494pub struct PairsMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200495 inner: slice::IterMut<'a, (T, P)>,
496 last: option::IntoIter<&'a mut T>,
Alex Crichton164c5332017-07-06 13:18:34 -0700497}
498
David Tolnay56080682018-01-06 14:01:52 -0800499impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
500 type Item = Pair<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700501
David Tolnay6eff4da2018-01-01 20:27:45 -0800502 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700503 self.inner
504 .next()
505 .map(|&mut (ref mut t, ref mut p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700506 .or_else(|| self.last.next().map(Pair::End))
Alex Crichton164c5332017-07-06 13:18:34 -0700507 }
508}
509
David Tolnay9700be02018-04-30 00:51:15 -0700510impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
511 fn len(&self) -> usize {
512 self.inner.len() + self.last.len()
513 }
514}
515
David Tolnayf3198012018-01-06 20:00:42 -0800516/// An iterator over owned pairs of type `Pair<T, P>`.
517///
518/// Refer to the [module documentation] for details about punctuated sequences.
519///
520/// [module documentation]: index.html
David Tolnay7f3f13e2019-04-22 10:55:30 -0700521#[derive(Clone)]
David Tolnay56080682018-01-06 14:01:52 -0800522pub struct IntoPairs<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200523 inner: vec::IntoIter<(T, P)>,
524 last: option::IntoIter<T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800525}
526
David Tolnay56080682018-01-06 14:01:52 -0800527impl<T, P> Iterator for IntoPairs<T, P> {
528 type Item = Pair<T, P>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800529
530 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700531 self.inner
532 .next()
533 .map(|(t, p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700534 .or_else(|| self.last.next().map(Pair::End))
David Tolnay6eff4da2018-01-01 20:27:45 -0800535 }
536}
537
David Tolnay9700be02018-04-30 00:51:15 -0700538impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
539 fn len(&self) -> usize {
540 self.inner.len() + self.last.len()
541 }
542}
543
David Tolnayf3198012018-01-06 20:00:42 -0800544/// An iterator over owned values of type `T`.
545///
546/// Refer to the [module documentation] for details about punctuated sequences.
547///
548/// [module documentation]: index.html
David Tolnay7f3f13e2019-04-22 10:55:30 -0700549#[derive(Clone)]
David Tolnayf2cfd722017-12-31 18:02:51 -0500550pub struct IntoIter<T, P> {
David Tolnay82712022019-04-22 15:15:40 -0700551 inner: vec::IntoIter<T>,
552
553 // TODO: remove P type parameter in the next breaking change
554 marker: PhantomData<P>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700555}
556
David Tolnayf2cfd722017-12-31 18:02:51 -0500557impl<T, P> Iterator for IntoIter<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800558 type Item = T;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700559
David Tolnay6eff4da2018-01-01 20:27:45 -0800560 fn next(&mut self) -> Option<Self::Item> {
David Tolnay82712022019-04-22 15:15:40 -0700561 self.inner.next()
David Tolnay6eff4da2018-01-01 20:27:45 -0800562 }
563}
564
David Tolnay9700be02018-04-30 00:51:15 -0700565impl<T, P> ExactSizeIterator for IntoIter<T, P> {
566 fn len(&self) -> usize {
David Tolnay82712022019-04-22 15:15:40 -0700567 self.inner.len()
David Tolnay9700be02018-04-30 00:51:15 -0700568 }
569}
570
David Tolnayf3198012018-01-06 20:00:42 -0800571/// An iterator over borrowed values of type `&T`.
572///
573/// Refer to the [module documentation] for details about punctuated sequences.
574///
575/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200576pub struct Iter<'a, T: 'a> {
David Tolnay7f3f13e2019-04-22 10:55:30 -0700577 // The `Item = &'a T` needs to be specified to support rustc 1.31 and older.
578 // On modern compilers we would be able to write just IterTrait<'a, T> where
579 // Item can be inferred unambiguously from the supertrait.
580 inner: Box<IterTrait<'a, T, Item = &'a T> + 'a>,
581}
582
583trait IterTrait<'a, T: 'a>: ExactSizeIterator<Item = &'a T> {
584 fn clone_box(&self) -> Box<IterTrait<'a, T, Item = &'a T> + 'a>;
David Tolnay8095c302018-03-31 19:34:17 +0200585}
586
587struct PrivateIter<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200588 inner: slice::Iter<'a, (T, P)>,
589 last: option::IntoIter<&'a T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800590}
591
David Tolnay96a09d92018-01-16 22:24:03 -0800592#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -0700593impl private {
594 pub fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
David Tolnay96a09d92018-01-16 22:24:03 -0800595 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200596 inner: Box::new(iter::empty()),
David Tolnay96a09d92018-01-16 22:24:03 -0800597 }
598 }
599}
600
David Tolnay7f3f13e2019-04-22 10:55:30 -0700601// No Clone bound on T.
602impl<'a, T> Clone for Iter<'a, T> {
603 fn clone(&self) -> Self {
604 Iter {
605 inner: self.inner.clone_box(),
606 }
607 }
608}
609
David Tolnay8095c302018-03-31 19:34:17 +0200610impl<'a, T> Iterator for Iter<'a, T> {
611 type Item = &'a T;
612
613 fn next(&mut self) -> Option<Self::Item> {
614 self.inner.next()
615 }
616}
617
David Tolnay9700be02018-04-30 00:51:15 -0700618impl<'a, T> ExactSizeIterator for Iter<'a, T> {
619 fn len(&self) -> usize {
620 self.inner.len()
621 }
622}
623
David Tolnay8095c302018-03-31 19:34:17 +0200624impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800625 type Item = &'a T;
626
627 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700628 self.inner
629 .next()
630 .map(|pair| &pair.0)
631 .or_else(|| self.last.next())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700632 }
633}
634
David Tolnay9700be02018-04-30 00:51:15 -0700635impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
636 fn len(&self) -> usize {
637 self.inner.len() + self.last.len()
638 }
639}
640
David Tolnay7f3f13e2019-04-22 10:55:30 -0700641// No Clone bound on T or P.
642impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
643 fn clone(&self) -> Self {
644 PrivateIter {
645 inner: self.inner.clone(),
646 last: self.last.clone(),
647 }
648 }
649}
650
651impl<'a, T: 'a, I: 'a> IterTrait<'a, T> for I
652where
653 I: ExactSizeIterator<Item = &'a T> + Clone,
654{
655 fn clone_box(&self) -> Box<IterTrait<'a, T, Item = &'a T> + 'a> {
656 Box::new(self.clone())
657 }
658}
659
David Tolnayf3198012018-01-06 20:00:42 -0800660/// An iterator over mutably borrowed values of type `&mut T`.
661///
662/// Refer to the [module documentation] for details about punctuated sequences.
663///
664/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200665pub struct IterMut<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700666 inner: Box<ExactSizeIterator<Item = &'a mut T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200667}
668
669struct PrivateIterMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200670 inner: slice::IterMut<'a, (T, P)>,
671 last: option::IntoIter<&'a mut T>,
David Tolnaya0834b42018-01-01 21:30:02 -0800672}
673
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600674#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -0700675impl private {
676 pub fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600677 IterMut {
678 inner: Box::new(iter::empty()),
679 }
680 }
681}
682
David Tolnay8095c302018-03-31 19:34:17 +0200683impl<'a, T> Iterator for IterMut<'a, T> {
684 type Item = &'a mut T;
685
686 fn next(&mut self) -> Option<Self::Item> {
687 self.inner.next()
688 }
689}
690
David Tolnay9700be02018-04-30 00:51:15 -0700691impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
692 fn len(&self) -> usize {
693 self.inner.len()
694 }
695}
696
David Tolnay8095c302018-03-31 19:34:17 +0200697impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
David Tolnaya0834b42018-01-01 21:30:02 -0800698 type Item = &'a mut T;
699
700 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700701 self.inner
702 .next()
703 .map(|pair| &mut pair.0)
704 .or_else(|| self.last.next())
David Tolnaya0834b42018-01-01 21:30:02 -0800705 }
706}
707
David Tolnay9700be02018-04-30 00:51:15 -0700708impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
709 fn len(&self) -> usize {
710 self.inner.len() + self.last.len()
711 }
712}
713
David Tolnayf3198012018-01-06 20:00:42 -0800714/// A single syntax tree node of type `T` followed by its trailing punctuation
715/// of type `P` if any.
716///
717/// Refer to the [module documentation] for details about punctuated sequences.
718///
719/// [module documentation]: index.html
David Tolnay7f3f13e2019-04-22 10:55:30 -0700720#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnay56080682018-01-06 14:01:52 -0800721pub enum Pair<T, P> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500722 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700723 End(T),
724}
725
David Tolnay56080682018-01-06 14:01:52 -0800726impl<T, P> Pair<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -0800727 /// Extracts the syntax tree node from this punctuated pair, discarding the
728 /// following punctuation.
David Tolnay56080682018-01-06 14:01:52 -0800729 pub fn into_value(self) -> T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700730 match self {
David Tolnay56080682018-01-06 14:01:52 -0800731 Pair::Punctuated(t, _) | Pair::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700732 }
733 }
734
David Tolnayf3198012018-01-06 20:00:42 -0800735 /// Borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800736 pub fn value(&self) -> &T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700737 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800738 Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700739 }
740 }
741
David Tolnayf3198012018-01-06 20:00:42 -0800742 /// Mutably borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800743 pub fn value_mut(&mut self) -> &mut T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700744 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800745 Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700746 }
747 }
748
David Tolnayf3198012018-01-06 20:00:42 -0800749 /// Borrows the punctuation from this punctuated pair, unless this pair is
750 /// the final one and there is no trailing punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500751 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700752 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800753 Pair::Punctuated(_, ref d) => Some(d),
754 Pair::End(_) => None,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700755 }
756 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400757
David Tolnayf3198012018-01-06 20:00:42 -0800758 /// Creates a punctuated pair out of a syntax tree node and an optional
759 /// following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500760 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500761 match d {
David Tolnay56080682018-01-06 14:01:52 -0800762 Some(d) => Pair::Punctuated(t, d),
763 None => Pair::End(t),
David Tolnay660fd1f2017-12-31 01:52:57 -0500764 }
765 }
766
David Tolnayf3198012018-01-06 20:00:42 -0800767 /// Produces this punctuated pair as a tuple of syntax tree node and
768 /// optional following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500769 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400770 match self {
David Tolnay56080682018-01-06 14:01:52 -0800771 Pair::Punctuated(t, d) => (t, Some(d)),
772 Pair::End(t) => (t, None),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400773 }
774 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700775}
776
David Tolnaybb987132018-01-08 13:51:19 -0800777impl<T, P> Index<usize> for Punctuated<T, P> {
778 type Output = T;
779
780 fn index(&self, index: usize) -> &Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200781 if index == self.len() - 1 {
782 match self.last {
783 Some(ref t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700784 None => &self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200785 }
786 } else {
787 &self.inner[index].0
788 }
David Tolnaybb987132018-01-08 13:51:19 -0800789 }
790}
791
792impl<T, P> IndexMut<usize> for Punctuated<T, P> {
793 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200794 if index == self.len() - 1 {
795 match self.last {
796 Some(ref mut t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700797 None => &mut self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200798 }
799 } else {
800 &mut self.inner[index].0
801 }
David Tolnaybb987132018-01-08 13:51:19 -0800802 }
803}
804
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700805#[cfg(feature = "printing")]
806mod printing {
807 use super::*;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700808 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700809 use quote::{ToTokens, TokenStreamExt};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700810
David Tolnayf2cfd722017-12-31 18:02:51 -0500811 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500812 where
813 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500814 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700815 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700816 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay56080682018-01-06 14:01:52 -0800817 tokens.append_all(self.pairs())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700818 }
819 }
820
David Tolnay56080682018-01-06 14:01:52 -0800821 impl<T, P> ToTokens for Pair<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500822 where
823 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500824 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700825 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700826 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700827 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800828 Pair::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700829 a.to_tokens(tokens);
830 b.to_tokens(tokens);
831 }
David Tolnay56080682018-01-06 14:01:52 -0800832 Pair::End(ref a) => a.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700833 }
834 }
835 }
836}