blob: 7bb73681ef2d87ff4bf4db5793a2213065320d76 [file] [log] [blame]
David Tolnay55535012018-01-05 16:39:23 -08001// Copyright 2018 Syn Developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
David Tolnayf3198012018-01-06 20:00:42 -08009//! A punctuated sequence of syntax tree nodes separated by punctuation.
10//!
11//! Lots of things in Rust are punctuated sequences.
12//!
13//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
14//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
15//! - The bounds on a generic parameter are `Punctuated<TypeParamBound, Token![+]>`.
16//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
17//!
18//! This module provides a common representation for these punctuated sequences
19//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
20//! syntax tree node + punctuation, where every node in the sequence is followed
21//! by punctuation except for possibly the final one.
22//!
23//! [`Punctuated<T, P>`]: struct.Punctuated.html
24//!
25//! ```text
26//! a_function_call(arg1, arg2, arg3);
27//! ^^^^^ ~~~~~ ^^^^
28//! ```
29
David Tolnay94d2b792018-04-29 12:26:10 -070030#[cfg(feature = "extra-traits")]
31use std::fmt::{self, Debug};
David Tolnay6c0a6092018-03-31 22:47:39 +020032#[cfg(any(feature = "full", feature = "derive"))]
33use std::iter;
34use std::iter::FromIterator;
David Tolnaybb987132018-01-08 13:51:19 -080035use std::ops::{Index, IndexMut};
Mateusz Naściszewski14111202018-04-11 21:17:41 +020036use std::option;
Alex Crichtonccbb45d2017-05-23 10:58:24 -070037use std::slice;
38use std::vec;
39
David Tolnayf3198012018-01-06 20:00:42 -080040#[cfg(feature = "parsing")]
David Tolnayecf0fbc2018-08-30 18:28:33 -070041use parse::{Parse, ParseStream, Result};
David Tolnay94f06632018-08-31 10:17:17 -070042#[cfg(any(feature = "full", feature = "derive"))]
43use private;
David Tolnay52619f62018-08-31 09:30:01 -070044#[cfg(feature = "parsing")]
45use token::Token;
David Tolnayf3198012018-01-06 20:00:42 -080046
47/// A punctuated sequence of syntax tree nodes of type `T` separated by
48/// punctuation of type `P`.
49///
50/// Refer to the [module documentation] for details about punctuated sequences.
51///
52/// [module documentation]: index.html
Nika Layzelld73a3652017-10-24 08:57:05 -040053#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070054#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -050055pub struct Punctuated<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020056 inner: Vec<(T, P)>,
57 last: Option<Box<T>>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070058}
59
David Tolnayf2cfd722017-12-31 18:02:51 -050060impl<T, P> Punctuated<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -080061 /// Creates an empty punctuated sequence.
David Tolnayf2cfd722017-12-31 18:02:51 -050062 pub fn new() -> Punctuated<T, P> {
David Tolnay94d2b792018-04-29 12:26:10 -070063 Punctuated {
64 inner: Vec::new(),
65 last: None,
66 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070067 }
68
David Tolnayf3198012018-01-06 20:00:42 -080069 /// Determines whether this punctuated sequence is empty, meaning it
70 /// contains no syntax tree nodes or punctuation.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071 pub fn is_empty(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020072 self.inner.len() == 0 && self.last.is_none()
Alex Crichtonccbb45d2017-05-23 10:58:24 -070073 }
74
David Tolnayf3198012018-01-06 20:00:42 -080075 /// Returns the number of syntax tree nodes in this punctuated sequence.
76 ///
77 /// This is the number of nodes of type `T`, not counting the punctuation of
78 /// type `P`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070079 pub fn len(&self) -> usize {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020080 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070081 }
82
David Tolnayf3198012018-01-06 20:00:42 -080083 /// Borrows the first punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080084 pub fn first(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020085 self.pairs().next()
Alex Crichton0aa50e02017-07-07 20:59:03 -070086 }
87
David Tolnayf3198012018-01-06 20:00:42 -080088 /// Borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080089 pub fn last(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020090 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -070091 self.last.as_ref().map(|t| Pair::End(t.as_ref()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +020092 } else {
David Tolnay94d2b792018-04-29 12:26:10 -070093 self.inner
94 .last()
Mateusz Naściszewski14111202018-04-11 21:17:41 +020095 .map(|&(ref t, ref d)| Pair::Punctuated(t, d))
96 }
Alex Crichton0aa50e02017-07-07 20:59:03 -070097 }
98
David Tolnayf3198012018-01-06 20:00:42 -080099 /// Mutably borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -0800100 pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200101 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -0700102 self.last.as_mut().map(|t| Pair::End(t.as_mut()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200103 } else {
David Tolnay94d2b792018-04-29 12:26:10 -0700104 self.inner
105 .last_mut()
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200106 .map(|&mut (ref mut t, ref mut d)| Pair::Punctuated(t, d))
107 }
Alex Crichton0aa50e02017-07-07 20:59:03 -0700108 }
109
David Tolnayf3198012018-01-06 20:00:42 -0800110 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
David Tolnay8095c302018-03-31 19:34:17 +0200111 pub fn iter(&self) -> Iter<T> {
David Tolnay51382052017-12-27 13:46:21 -0500112 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200113 inner: Box::new(PrivateIter {
114 inner: self.inner.iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200115 last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200116 }),
David Tolnay51382052017-12-27 13:46:21 -0500117 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700118 }
119
David Tolnayf3198012018-01-06 20:00:42 -0800120 /// Returns an iterator over mutably borrowed syntax tree nodes of type
121 /// `&mut T`.
David Tolnay8095c302018-03-31 19:34:17 +0200122 pub fn iter_mut(&mut self) -> IterMut<T> {
David Tolnaya0834b42018-01-01 21:30:02 -0800123 IterMut {
David Tolnay8095c302018-03-31 19:34:17 +0200124 inner: Box::new(PrivateIterMut {
125 inner: self.inner.iter_mut(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200126 last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200127 }),
David Tolnaya0834b42018-01-01 21:30:02 -0800128 }
129 }
130
David Tolnayf3198012018-01-06 20:00:42 -0800131 /// Returns an iterator over the contents of this sequence as borrowed
132 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800133 pub fn pairs(&self) -> Pairs<T, P> {
134 Pairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800135 inner: self.inner.iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200136 last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800137 }
138 }
139
David Tolnayf3198012018-01-06 20:00:42 -0800140 /// Returns an iterator over the contents of this sequence as mutably
141 /// borrowed punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800142 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
143 PairsMut {
David Tolnay51382052017-12-27 13:46:21 -0500144 inner: self.inner.iter_mut(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200145 last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500146 }
Alex Crichton164c5332017-07-06 13:18:34 -0700147 }
148
David Tolnayf3198012018-01-06 20:00:42 -0800149 /// Returns an iterator over the contents of this sequence as owned
150 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800151 pub fn into_pairs(self) -> IntoPairs<T, P> {
152 IntoPairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800153 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200154 last: self.last.map(|t| *t).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800155 }
156 }
157
David Tolnayf3198012018-01-06 20:00:42 -0800158 /// Appends a syntax tree node onto the end of this punctuated sequence. The
159 /// sequence must previously have a trailing punctuation.
160 ///
161 /// Use [`push`] instead if the punctuated sequence may or may not already
162 /// have trailing punctuation.
163 ///
164 /// [`push`]: #method.push
165 ///
166 /// # Panics
167 ///
168 /// Panics if the sequence does not already have a trailing punctuation when
169 /// this method is called.
David Tolnay56080682018-01-06 14:01:52 -0800170 pub fn push_value(&mut self, value: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -0500171 assert!(self.empty_or_trailing());
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200172 self.last = Some(Box::new(value));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700173 }
174
David Tolnayf3198012018-01-06 20:00:42 -0800175 /// Appends a trailing punctuation onto the end of this punctuated sequence.
176 /// The sequence must be non-empty and must not already have trailing
177 /// punctuation.
178 ///
179 /// # Panics
180 ///
181 /// Panics if the sequence is empty or already has a trailing punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800182 pub fn push_punct(&mut self, punctuation: P) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200183 assert!(self.last.is_some());
David Tolnay03163082018-04-11 12:10:18 -0700184 let last = self.last.take().unwrap();
185 self.inner.push((*last, punctuation));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700186 }
187
David Tolnayf3198012018-01-06 20:00:42 -0800188 /// Removes the last punctuated pair from this sequence, or `None` if the
189 /// sequence is empty.
David Tolnay56080682018-01-06 14:01:52 -0800190 pub fn pop(&mut self) -> Option<Pair<T, P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200191 if self.last.is_some() {
David Tolnay03163082018-04-11 12:10:18 -0700192 self.last.take().map(|t| Pair::End(*t))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200193 } else {
194 self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d))
195 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700196 }
197
David Tolnayf3198012018-01-06 20:00:42 -0800198 /// Determines whether this punctuated sequence ends with a trailing
199 /// punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800200 pub fn trailing_punct(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200201 self.last.is_none() && !self.is_empty()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700202 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400203
David Tolnayf2cfd722017-12-31 18:02:51 -0500204 /// Returns true if either this `Punctuated` is empty, or it has a trailing
205 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -0500206 ///
David Tolnaya0834b42018-01-01 21:30:02 -0800207 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -0400208 pub fn empty_or_trailing(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200209 self.last.is_none()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400210 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700211
David Tolnayf3198012018-01-06 20:00:42 -0800212 /// Appends a syntax tree node onto the end of this punctuated sequence.
213 ///
214 /// If there is not a trailing punctuation in this sequence when this method
215 /// is called, the default value of punctuation type `P` is inserted before
216 /// the given value of type `T`.
David Tolnay8842c7e2018-09-01 12:37:32 -0700217 pub fn push(&mut self, value: T)
218 where
219 P: Default,
220 {
David Tolnaya0834b42018-01-01 21:30:02 -0800221 if !self.empty_or_trailing() {
222 self.push_punct(Default::default());
223 }
David Tolnay56080682018-01-06 14:01:52 -0800224 self.push_value(value);
David Tolnaya0834b42018-01-01 21:30:02 -0800225 }
David Tolnayb77d1802018-01-11 16:18:35 -0800226
227 /// Inserts an element at position `index`.
228 ///
229 /// # Panics
230 ///
231 /// Panics if `index` is greater than the number of elements previously in
232 /// this punctuated sequence.
David Tolnay8842c7e2018-09-01 12:37:32 -0700233 pub fn insert(&mut self, index: usize, value: T)
234 where
235 P: Default,
236 {
David Tolnayb77d1802018-01-11 16:18:35 -0800237 assert!(index <= self.len());
238
239 if index == self.len() {
240 self.push(value);
241 } else {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200242 self.inner.insert(index, (value, Default::default()));
David Tolnayb77d1802018-01-11 16:18:35 -0800243 }
244 }
David Tolnay8842c7e2018-09-01 12:37:32 -0700245
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700246 /// Parses zero or more occurrences of `T` separated by punctuation of type
247 /// `P`, with optional trailing punctuation.
248 ///
249 /// Parsing continues until the end of this parse stream. The entire content
250 /// of this parse stream must consist of `T` and `P`.
David Tolnay206edfb2018-09-01 16:02:20 -0700251 ///
252 /// *This function is available if Syn is built with the `"parsing"`
253 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700254 #[cfg(feature = "parsing")]
255 pub fn parse_terminated(input: ParseStream) -> Result<Self>
256 where
257 T: Parse,
258 P: Parse,
259 {
260 Self::parse_terminated_with(input, T::parse)
261 }
262
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700263 /// Parses zero or more occurrences of `T` using the given parse function,
264 /// separated by punctuation of type `P`, with optional trailing
265 /// punctuation.
266 ///
267 /// Like [`parse_terminated`], the entire content of this stream is expected
268 /// to be parsed.
269 ///
270 /// [`parse_terminated`]: #method.parse_terminated
David Tolnay206edfb2018-09-01 16:02:20 -0700271 ///
272 /// *This function is available if Syn is built with the `"parsing"`
273 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700274 #[cfg(feature = "parsing")]
275 pub fn parse_terminated_with(
276 input: ParseStream,
277 parser: fn(ParseStream) -> Result<T>,
278 ) -> Result<Self>
279 where
280 P: Parse,
281 {
282 let mut punctuated = Punctuated::new();
283
284 loop {
285 if input.is_empty() {
286 break;
287 }
288 let value = parser(input)?;
289 punctuated.push_value(value);
290 if input.is_empty() {
291 break;
292 }
293 let punct = input.parse()?;
294 punctuated.push_punct(punct);
295 }
296
297 Ok(punctuated)
298 }
299
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700300 /// Parses one or more occurrences of `T` separated by punctuation of type
301 /// `P`, not accepting trailing punctuation.
302 ///
303 /// Parsing continues as long as punctuation `P` is present at the head of
304 /// the stream. This method returns upon parsing a `T` and observing that it
305 /// is not followed by a `P`, even if there are remaining tokens in the
306 /// stream.
David Tolnay206edfb2018-09-01 16:02:20 -0700307 ///
308 /// *This function is available if Syn is built with the `"parsing"`
309 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700310 #[cfg(feature = "parsing")]
311 pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
312 where
313 T: Parse,
314 P: Token + Parse,
315 {
316 Self::parse_separated_nonempty_with(input, T::parse)
317 }
318
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700319 /// Parses one or more occurrences of `T` using the given parse function,
320 /// separated by punctuation of type `P`, not accepting trailing
321 /// punctuation.
322 ///
323 /// Like [`parse_separated_nonempty`], may complete early without parsing
324 /// the entire content of this stream.
325 ///
326 /// [`parse_separated_nonempty`]: #method.parse_separated_nonempty
David Tolnay206edfb2018-09-01 16:02:20 -0700327 ///
328 /// *This function is available if Syn is built with the `"parsing"`
329 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700330 #[cfg(feature = "parsing")]
331 pub fn parse_separated_nonempty_with(
332 input: ParseStream,
333 parser: fn(ParseStream) -> Result<T>,
334 ) -> Result<Self>
335 where
336 P: Token + Parse,
337 {
338 let mut punctuated = Punctuated::new();
339
340 loop {
341 let value = parser(input)?;
342 punctuated.push_value(value);
343 if !P::peek(input.cursor()) {
344 break;
345 }
346 let punct = input.parse()?;
347 punctuated.push_punct(punct);
348 }
349
350 Ok(punctuated)
351 }
David Tolnaya0834b42018-01-01 21:30:02 -0800352}
353
Nika Layzelld73a3652017-10-24 08:57:05 -0400354#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -0500355impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -0400356 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200357 let mut list = f.debug_list();
David Tolnay0c18c512018-07-22 10:39:10 -0700358 for &(ref t, ref p) in &self.inner {
359 list.entry(t);
360 list.entry(p);
361 }
362 if let Some(ref last) = self.last {
363 list.entry(last);
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200364 }
365 list.finish()
Nika Layzelld73a3652017-10-24 08:57:05 -0400366 }
367}
368
David Tolnay9ef24bc2018-01-09 10:43:55 -0800369impl<T, P> FromIterator<T> for Punctuated<T, P>
370where
371 P: Default,
372{
373 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
374 let mut ret = Punctuated::new();
375 ret.extend(i);
376 ret
377 }
378}
379
380impl<T, P> Extend<T> for Punctuated<T, P>
381where
382 P: Default,
383{
384 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
385 for value in i {
386 self.push(value);
387 }
388 }
389}
390
David Tolnay56080682018-01-06 14:01:52 -0800391impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
392 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500393 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700394 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700395 ret
396 }
397}
398
David Tolnay56080682018-01-06 14:01:52 -0800399impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
400 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200401 assert!(self.empty_or_trailing());
402 let mut nomore = false;
David Tolnay56080682018-01-06 14:01:52 -0800403 for pair in i {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200404 if nomore {
405 panic!("Punctuated extended with items after a Pair::End");
406 }
David Tolnay56080682018-01-06 14:01:52 -0800407 match pair {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200408 Pair::Punctuated(a, b) => self.inner.push((a, b)),
409 Pair::End(a) => {
410 self.last = Some(Box::new(a));
411 nomore = true;
412 }
Alex Crichton24f12822017-07-14 07:15:32 -0700413 }
414 }
415 }
416}
417
David Tolnayf2cfd722017-12-31 18:02:51 -0500418impl<T, P> IntoIterator for Punctuated<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800419 type Item = T;
David Tolnayf2cfd722017-12-31 18:02:51 -0500420 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700421
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500422 fn into_iter(self) -> Self::IntoIter {
David Tolnay51382052017-12-27 13:46:21 -0500423 IntoIter {
424 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200425 last: self.last.map(|t| *t).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500426 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700427 }
428}
429
David Tolnay6eff4da2018-01-01 20:27:45 -0800430impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
431 type Item = &'a T;
David Tolnay8095c302018-03-31 19:34:17 +0200432 type IntoIter = Iter<'a, T>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800433
434 fn into_iter(self) -> Self::IntoIter {
435 Punctuated::iter(self)
436 }
437}
438
David Tolnaya0834b42018-01-01 21:30:02 -0800439impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
440 type Item = &'a mut T;
David Tolnay8095c302018-03-31 19:34:17 +0200441 type IntoIter = IterMut<'a, T>;
David Tolnaya0834b42018-01-01 21:30:02 -0800442
443 fn into_iter(self) -> Self::IntoIter {
444 Punctuated::iter_mut(self)
445 }
446}
447
David Tolnayf2cfd722017-12-31 18:02:51 -0500448impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700449 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500450 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700451 }
452}
453
David Tolnayf3198012018-01-06 20:00:42 -0800454/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
455///
456/// Refer to the [module documentation] for details about punctuated sequences.
457///
458/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800459pub struct Pairs<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200460 inner: slice::Iter<'a, (T, P)>,
461 last: option::IntoIter<&'a T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700462}
463
David Tolnay56080682018-01-06 14:01:52 -0800464impl<'a, T, P> Iterator for Pairs<'a, T, P> {
465 type Item = Pair<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700466
David Tolnay6eff4da2018-01-01 20:27:45 -0800467 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700468 self.inner
469 .next()
470 .map(|&(ref t, ref p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700471 .or_else(|| self.last.next().map(Pair::End))
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700472 }
473}
474
David Tolnay9700be02018-04-30 00:51:15 -0700475impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
476 fn len(&self) -> usize {
477 self.inner.len() + self.last.len()
478 }
479}
480
David Tolnayf3198012018-01-06 20:00:42 -0800481/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
482///
483/// Refer to the [module documentation] for details about punctuated sequences.
484///
485/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800486pub struct PairsMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200487 inner: slice::IterMut<'a, (T, P)>,
488 last: option::IntoIter<&'a mut T>,
Alex Crichton164c5332017-07-06 13:18:34 -0700489}
490
David Tolnay56080682018-01-06 14:01:52 -0800491impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
492 type Item = Pair<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700493
David Tolnay6eff4da2018-01-01 20:27:45 -0800494 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700495 self.inner
496 .next()
497 .map(|&mut (ref mut t, ref mut p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700498 .or_else(|| self.last.next().map(Pair::End))
Alex Crichton164c5332017-07-06 13:18:34 -0700499 }
500}
501
David Tolnay9700be02018-04-30 00:51:15 -0700502impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
503 fn len(&self) -> usize {
504 self.inner.len() + self.last.len()
505 }
506}
507
David Tolnayf3198012018-01-06 20:00:42 -0800508/// An iterator over owned pairs of type `Pair<T, P>`.
509///
510/// Refer to the [module documentation] for details about punctuated sequences.
511///
512/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800513pub struct IntoPairs<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200514 inner: vec::IntoIter<(T, P)>,
515 last: option::IntoIter<T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800516}
517
David Tolnay56080682018-01-06 14:01:52 -0800518impl<T, P> Iterator for IntoPairs<T, P> {
519 type Item = Pair<T, P>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800520
521 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700522 self.inner
523 .next()
524 .map(|(t, p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700525 .or_else(|| self.last.next().map(Pair::End))
David Tolnay6eff4da2018-01-01 20:27:45 -0800526 }
527}
528
David Tolnay9700be02018-04-30 00:51:15 -0700529impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
530 fn len(&self) -> usize {
531 self.inner.len() + self.last.len()
532 }
533}
534
David Tolnayf3198012018-01-06 20:00:42 -0800535/// An iterator over owned values of type `T`.
536///
537/// Refer to the [module documentation] for details about punctuated sequences.
538///
539/// [module documentation]: index.html
David Tolnayf2cfd722017-12-31 18:02:51 -0500540pub struct IntoIter<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200541 inner: vec::IntoIter<(T, P)>,
542 last: option::IntoIter<T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700543}
544
David Tolnayf2cfd722017-12-31 18:02:51 -0500545impl<T, P> Iterator for IntoIter<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800546 type Item = T;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700547
David Tolnay6eff4da2018-01-01 20:27:45 -0800548 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700549 self.inner
550 .next()
551 .map(|pair| pair.0)
552 .or_else(|| self.last.next())
David Tolnay6eff4da2018-01-01 20:27:45 -0800553 }
554}
555
David Tolnay9700be02018-04-30 00:51:15 -0700556impl<T, P> ExactSizeIterator for IntoIter<T, P> {
557 fn len(&self) -> usize {
558 self.inner.len() + self.last.len()
559 }
560}
561
David Tolnayf3198012018-01-06 20:00:42 -0800562/// An iterator over borrowed values of type `&T`.
563///
564/// Refer to the [module documentation] for details about punctuated sequences.
565///
566/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200567pub struct Iter<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700568 inner: Box<ExactSizeIterator<Item = &'a T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200569}
570
571struct PrivateIter<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200572 inner: slice::Iter<'a, (T, P)>,
573 last: option::IntoIter<&'a T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800574}
575
David Tolnay96a09d92018-01-16 22:24:03 -0800576#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -0700577impl private {
578 pub fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
David Tolnay96a09d92018-01-16 22:24:03 -0800579 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200580 inner: Box::new(iter::empty()),
David Tolnay96a09d92018-01-16 22:24:03 -0800581 }
582 }
583}
584
David Tolnay8095c302018-03-31 19:34:17 +0200585impl<'a, T> Iterator for Iter<'a, T> {
586 type Item = &'a T;
587
588 fn next(&mut self) -> Option<Self::Item> {
589 self.inner.next()
590 }
591}
592
David Tolnay9700be02018-04-30 00:51:15 -0700593impl<'a, T> ExactSizeIterator for Iter<'a, T> {
594 fn len(&self) -> usize {
595 self.inner.len()
596 }
597}
598
David Tolnay8095c302018-03-31 19:34:17 +0200599impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800600 type Item = &'a T;
601
602 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700603 self.inner
604 .next()
605 .map(|pair| &pair.0)
606 .or_else(|| self.last.next())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700607 }
608}
609
David Tolnay9700be02018-04-30 00:51:15 -0700610impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
611 fn len(&self) -> usize {
612 self.inner.len() + self.last.len()
613 }
614}
615
David Tolnayf3198012018-01-06 20:00:42 -0800616/// An iterator over mutably borrowed values of type `&mut T`.
617///
618/// Refer to the [module documentation] for details about punctuated sequences.
619///
620/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200621pub struct IterMut<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700622 inner: Box<ExactSizeIterator<Item = &'a mut T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200623}
624
625struct PrivateIterMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200626 inner: slice::IterMut<'a, (T, P)>,
627 last: option::IntoIter<&'a mut T>,
David Tolnaya0834b42018-01-01 21:30:02 -0800628}
629
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600630#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -0700631impl private {
632 pub fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600633 IterMut {
634 inner: Box::new(iter::empty()),
635 }
636 }
637}
638
David Tolnay8095c302018-03-31 19:34:17 +0200639impl<'a, T> Iterator for IterMut<'a, T> {
640 type Item = &'a mut T;
641
642 fn next(&mut self) -> Option<Self::Item> {
643 self.inner.next()
644 }
645}
646
David Tolnay9700be02018-04-30 00:51:15 -0700647impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
648 fn len(&self) -> usize {
649 self.inner.len()
650 }
651}
652
David Tolnay8095c302018-03-31 19:34:17 +0200653impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
David Tolnaya0834b42018-01-01 21:30:02 -0800654 type Item = &'a mut T;
655
656 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700657 self.inner
658 .next()
659 .map(|pair| &mut pair.0)
660 .or_else(|| self.last.next())
David Tolnaya0834b42018-01-01 21:30:02 -0800661 }
662}
663
David Tolnay9700be02018-04-30 00:51:15 -0700664impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
665 fn len(&self) -> usize {
666 self.inner.len() + self.last.len()
667 }
668}
669
David Tolnayf3198012018-01-06 20:00:42 -0800670/// A single syntax tree node of type `T` followed by its trailing punctuation
671/// of type `P` if any.
672///
673/// Refer to the [module documentation] for details about punctuated sequences.
674///
675/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800676pub enum Pair<T, P> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500677 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700678 End(T),
679}
680
David Tolnay56080682018-01-06 14:01:52 -0800681impl<T, P> Pair<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -0800682 /// Extracts the syntax tree node from this punctuated pair, discarding the
683 /// following punctuation.
David Tolnay56080682018-01-06 14:01:52 -0800684 pub fn into_value(self) -> T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700685 match self {
David Tolnay56080682018-01-06 14:01:52 -0800686 Pair::Punctuated(t, _) | Pair::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700687 }
688 }
689
David Tolnayf3198012018-01-06 20:00:42 -0800690 /// Borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800691 pub fn value(&self) -> &T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700692 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800693 Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700694 }
695 }
696
David Tolnayf3198012018-01-06 20:00:42 -0800697 /// Mutably borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800698 pub fn value_mut(&mut self) -> &mut T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700699 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800700 Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700701 }
702 }
703
David Tolnayf3198012018-01-06 20:00:42 -0800704 /// Borrows the punctuation from this punctuated pair, unless this pair is
705 /// the final one and there is no trailing punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500706 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700707 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800708 Pair::Punctuated(_, ref d) => Some(d),
709 Pair::End(_) => None,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700710 }
711 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400712
David Tolnayf3198012018-01-06 20:00:42 -0800713 /// Creates a punctuated pair out of a syntax tree node and an optional
714 /// following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500715 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500716 match d {
David Tolnay56080682018-01-06 14:01:52 -0800717 Some(d) => Pair::Punctuated(t, d),
718 None => Pair::End(t),
David Tolnay660fd1f2017-12-31 01:52:57 -0500719 }
720 }
721
David Tolnayf3198012018-01-06 20:00:42 -0800722 /// Produces this punctuated pair as a tuple of syntax tree node and
723 /// optional following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500724 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400725 match self {
David Tolnay56080682018-01-06 14:01:52 -0800726 Pair::Punctuated(t, d) => (t, Some(d)),
727 Pair::End(t) => (t, None),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400728 }
729 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700730}
731
David Tolnaybb987132018-01-08 13:51:19 -0800732impl<T, P> Index<usize> for Punctuated<T, P> {
733 type Output = T;
734
735 fn index(&self, index: usize) -> &Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200736 if index == self.len() - 1 {
737 match self.last {
738 Some(ref t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700739 None => &self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200740 }
741 } else {
742 &self.inner[index].0
743 }
David Tolnaybb987132018-01-08 13:51:19 -0800744 }
745}
746
747impl<T, P> IndexMut<usize> for Punctuated<T, P> {
748 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200749 if index == self.len() - 1 {
750 match self.last {
751 Some(ref mut t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700752 None => &mut self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200753 }
754 } else {
755 &mut self.inner[index].0
756 }
David Tolnaybb987132018-01-08 13:51:19 -0800757 }
758}
759
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700760#[cfg(feature = "printing")]
761mod printing {
762 use super::*;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700763 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700764 use quote::{ToTokens, TokenStreamExt};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700765
David Tolnayf2cfd722017-12-31 18:02:51 -0500766 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500767 where
768 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500769 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700770 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700771 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay56080682018-01-06 14:01:52 -0800772 tokens.append_all(self.pairs())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700773 }
774 }
775
David Tolnay56080682018-01-06 14:01:52 -0800776 impl<T, P> ToTokens for Pair<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500777 where
778 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500779 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700780 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700781 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700782 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800783 Pair::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700784 a.to_tokens(tokens);
785 b.to_tokens(tokens);
786 }
David Tolnay56080682018-01-06 14:01:52 -0800787 Pair::End(ref a) => a.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700788 }
789 }
790 }
791}