blob: de6d22d7fa4bf9323b938819b656f69061deb618 [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 Tolnay52619f62018-08-31 09:30:01 -070042#[cfg(feature = "parsing")]
43use token::Token;
David Tolnayf3198012018-01-06 20:00:42 -080044
45/// A punctuated sequence of syntax tree nodes of type `T` separated by
46/// punctuation of type `P`.
47///
48/// Refer to the [module documentation] for details about punctuated sequences.
49///
50/// [module documentation]: index.html
Nika Layzelld73a3652017-10-24 08:57:05 -040051#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070052#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -050053pub struct Punctuated<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020054 inner: Vec<(T, P)>,
55 last: Option<Box<T>>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070056}
57
David Tolnayf2cfd722017-12-31 18:02:51 -050058impl<T, P> Punctuated<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -080059 /// Creates an empty punctuated sequence.
David Tolnayf2cfd722017-12-31 18:02:51 -050060 pub fn new() -> Punctuated<T, P> {
David Tolnay94d2b792018-04-29 12:26:10 -070061 Punctuated {
62 inner: Vec::new(),
63 last: None,
64 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070065 }
66
David Tolnayf3198012018-01-06 20:00:42 -080067 /// Determines whether this punctuated sequence is empty, meaning it
68 /// contains no syntax tree nodes or punctuation.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070069 pub fn is_empty(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020070 self.inner.len() == 0 && self.last.is_none()
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071 }
72
David Tolnayf3198012018-01-06 20:00:42 -080073 /// Returns the number of syntax tree nodes in this punctuated sequence.
74 ///
75 /// This is the number of nodes of type `T`, not counting the punctuation of
76 /// type `P`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070077 pub fn len(&self) -> usize {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020078 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070079 }
80
David Tolnayf3198012018-01-06 20:00:42 -080081 /// Borrows the first punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080082 pub fn first(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020083 self.pairs().next()
Alex Crichton0aa50e02017-07-07 20:59:03 -070084 }
85
David Tolnayf3198012018-01-06 20:00:42 -080086 /// Borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080087 pub fn last(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020088 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -070089 self.last.as_ref().map(|t| Pair::End(t.as_ref()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +020090 } else {
David Tolnay94d2b792018-04-29 12:26:10 -070091 self.inner
92 .last()
Mateusz Naściszewski14111202018-04-11 21:17:41 +020093 .map(|&(ref t, ref d)| Pair::Punctuated(t, d))
94 }
Alex Crichton0aa50e02017-07-07 20:59:03 -070095 }
96
David Tolnayf3198012018-01-06 20:00:42 -080097 /// Mutably borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080098 pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020099 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -0700100 self.last.as_mut().map(|t| Pair::End(t.as_mut()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200101 } else {
David Tolnay94d2b792018-04-29 12:26:10 -0700102 self.inner
103 .last_mut()
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200104 .map(|&mut (ref mut t, ref mut d)| Pair::Punctuated(t, d))
105 }
Alex Crichton0aa50e02017-07-07 20:59:03 -0700106 }
107
David Tolnayf3198012018-01-06 20:00:42 -0800108 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
David Tolnay8095c302018-03-31 19:34:17 +0200109 pub fn iter(&self) -> Iter<T> {
David Tolnay51382052017-12-27 13:46:21 -0500110 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200111 inner: Box::new(PrivateIter {
112 inner: self.inner.iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200113 last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200114 }),
David Tolnay51382052017-12-27 13:46:21 -0500115 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700116 }
117
David Tolnayf3198012018-01-06 20:00:42 -0800118 /// Returns an iterator over mutably borrowed syntax tree nodes of type
119 /// `&mut T`.
David Tolnay8095c302018-03-31 19:34:17 +0200120 pub fn iter_mut(&mut self) -> IterMut<T> {
David Tolnaya0834b42018-01-01 21:30:02 -0800121 IterMut {
David Tolnay8095c302018-03-31 19:34:17 +0200122 inner: Box::new(PrivateIterMut {
123 inner: self.inner.iter_mut(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200124 last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200125 }),
David Tolnaya0834b42018-01-01 21:30:02 -0800126 }
127 }
128
David Tolnayf3198012018-01-06 20:00:42 -0800129 /// Returns an iterator over the contents of this sequence as borrowed
130 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800131 pub fn pairs(&self) -> Pairs<T, P> {
132 Pairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800133 inner: self.inner.iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200134 last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800135 }
136 }
137
David Tolnayf3198012018-01-06 20:00:42 -0800138 /// Returns an iterator over the contents of this sequence as mutably
139 /// borrowed punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800140 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
141 PairsMut {
David Tolnay51382052017-12-27 13:46:21 -0500142 inner: self.inner.iter_mut(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200143 last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500144 }
Alex Crichton164c5332017-07-06 13:18:34 -0700145 }
146
David Tolnayf3198012018-01-06 20:00:42 -0800147 /// Returns an iterator over the contents of this sequence as owned
148 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800149 pub fn into_pairs(self) -> IntoPairs<T, P> {
150 IntoPairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800151 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200152 last: self.last.map(|t| *t).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800153 }
154 }
155
David Tolnayf3198012018-01-06 20:00:42 -0800156 /// Appends a syntax tree node onto the end of this punctuated sequence. The
157 /// sequence must previously have a trailing punctuation.
158 ///
159 /// Use [`push`] instead if the punctuated sequence may or may not already
160 /// have trailing punctuation.
161 ///
162 /// [`push`]: #method.push
163 ///
164 /// # Panics
165 ///
166 /// Panics if the sequence does not already have a trailing punctuation when
167 /// this method is called.
David Tolnay56080682018-01-06 14:01:52 -0800168 pub fn push_value(&mut self, value: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -0500169 assert!(self.empty_or_trailing());
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200170 self.last = Some(Box::new(value));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700171 }
172
David Tolnayf3198012018-01-06 20:00:42 -0800173 /// Appends a trailing punctuation onto the end of this punctuated sequence.
174 /// The sequence must be non-empty and must not already have trailing
175 /// punctuation.
176 ///
177 /// # Panics
178 ///
179 /// Panics if the sequence is empty or already has a trailing punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800180 pub fn push_punct(&mut self, punctuation: P) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200181 assert!(self.last.is_some());
David Tolnay03163082018-04-11 12:10:18 -0700182 let last = self.last.take().unwrap();
183 self.inner.push((*last, punctuation));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700184 }
185
David Tolnayf3198012018-01-06 20:00:42 -0800186 /// Removes the last punctuated pair from this sequence, or `None` if the
187 /// sequence is empty.
David Tolnay56080682018-01-06 14:01:52 -0800188 pub fn pop(&mut self) -> Option<Pair<T, P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200189 if self.last.is_some() {
David Tolnay03163082018-04-11 12:10:18 -0700190 self.last.take().map(|t| Pair::End(*t))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200191 } else {
192 self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d))
193 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700194 }
195
David Tolnayf3198012018-01-06 20:00:42 -0800196 /// Determines whether this punctuated sequence ends with a trailing
197 /// punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800198 pub fn trailing_punct(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200199 self.last.is_none() && !self.is_empty()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700200 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400201
David Tolnayf2cfd722017-12-31 18:02:51 -0500202 /// Returns true if either this `Punctuated` is empty, or it has a trailing
203 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -0500204 ///
David Tolnaya0834b42018-01-01 21:30:02 -0800205 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -0400206 pub fn empty_or_trailing(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200207 self.last.is_none()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400208 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700209}
210
David Tolnaya0834b42018-01-01 21:30:02 -0800211impl<T, P> Punctuated<T, P>
212where
213 P: Default,
214{
David Tolnayf3198012018-01-06 20:00:42 -0800215 /// Appends a syntax tree node onto the end of this punctuated sequence.
216 ///
217 /// If there is not a trailing punctuation in this sequence when this method
218 /// is called, the default value of punctuation type `P` is inserted before
219 /// the given value of type `T`.
David Tolnay56080682018-01-06 14:01:52 -0800220 pub fn push(&mut self, value: T) {
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.
233 pub fn insert(&mut self, index: usize, value: T) {
234 assert!(index <= self.len());
235
236 if index == self.len() {
237 self.push(value);
238 } else {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200239 self.inner.insert(index, (value, Default::default()));
David Tolnayb77d1802018-01-11 16:18:35 -0800240 }
241 }
David Tolnaya0834b42018-01-01 21:30:02 -0800242}
243
Nika Layzelld73a3652017-10-24 08:57:05 -0400244#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -0500245impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -0400246 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200247 let mut list = f.debug_list();
David Tolnay0c18c512018-07-22 10:39:10 -0700248 for &(ref t, ref p) in &self.inner {
249 list.entry(t);
250 list.entry(p);
251 }
252 if let Some(ref last) = self.last {
253 list.entry(last);
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200254 }
255 list.finish()
Nika Layzelld73a3652017-10-24 08:57:05 -0400256 }
257}
258
David Tolnay9ef24bc2018-01-09 10:43:55 -0800259impl<T, P> FromIterator<T> for Punctuated<T, P>
260where
261 P: Default,
262{
263 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
264 let mut ret = Punctuated::new();
265 ret.extend(i);
266 ret
267 }
268}
269
270impl<T, P> Extend<T> for Punctuated<T, P>
271where
272 P: Default,
273{
274 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
275 for value in i {
276 self.push(value);
277 }
278 }
279}
280
David Tolnay56080682018-01-06 14:01:52 -0800281impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
282 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500283 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700284 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700285 ret
286 }
287}
288
David Tolnay56080682018-01-06 14:01:52 -0800289impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
290 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200291 assert!(self.empty_or_trailing());
292 let mut nomore = false;
David Tolnay56080682018-01-06 14:01:52 -0800293 for pair in i {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200294 if nomore {
295 panic!("Punctuated extended with items after a Pair::End");
296 }
David Tolnay56080682018-01-06 14:01:52 -0800297 match pair {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200298 Pair::Punctuated(a, b) => self.inner.push((a, b)),
299 Pair::End(a) => {
300 self.last = Some(Box::new(a));
301 nomore = true;
302 }
Alex Crichton24f12822017-07-14 07:15:32 -0700303 }
304 }
305 }
306}
307
David Tolnayf2cfd722017-12-31 18:02:51 -0500308impl<T, P> IntoIterator for Punctuated<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800309 type Item = T;
David Tolnayf2cfd722017-12-31 18:02:51 -0500310 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700311
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500312 fn into_iter(self) -> Self::IntoIter {
David Tolnay51382052017-12-27 13:46:21 -0500313 IntoIter {
314 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200315 last: self.last.map(|t| *t).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500316 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700317 }
318}
319
David Tolnay6eff4da2018-01-01 20:27:45 -0800320impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
321 type Item = &'a T;
David Tolnay8095c302018-03-31 19:34:17 +0200322 type IntoIter = Iter<'a, T>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800323
324 fn into_iter(self) -> Self::IntoIter {
325 Punctuated::iter(self)
326 }
327}
328
David Tolnaya0834b42018-01-01 21:30:02 -0800329impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
330 type Item = &'a mut T;
David Tolnay8095c302018-03-31 19:34:17 +0200331 type IntoIter = IterMut<'a, T>;
David Tolnaya0834b42018-01-01 21:30:02 -0800332
333 fn into_iter(self) -> Self::IntoIter {
334 Punctuated::iter_mut(self)
335 }
336}
337
David Tolnayf2cfd722017-12-31 18:02:51 -0500338impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700339 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500340 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700341 }
342}
343
David Tolnayf3198012018-01-06 20:00:42 -0800344/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
345///
346/// Refer to the [module documentation] for details about punctuated sequences.
347///
348/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800349pub struct Pairs<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200350 inner: slice::Iter<'a, (T, P)>,
351 last: option::IntoIter<&'a T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700352}
353
David Tolnay56080682018-01-06 14:01:52 -0800354impl<'a, T, P> Iterator for Pairs<'a, T, P> {
355 type Item = Pair<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700356
David Tolnay6eff4da2018-01-01 20:27:45 -0800357 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700358 self.inner
359 .next()
360 .map(|&(ref t, ref p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700361 .or_else(|| self.last.next().map(Pair::End))
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700362 }
363}
364
David Tolnay9700be02018-04-30 00:51:15 -0700365impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
366 fn len(&self) -> usize {
367 self.inner.len() + self.last.len()
368 }
369}
370
David Tolnayf3198012018-01-06 20:00:42 -0800371/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
372///
373/// Refer to the [module documentation] for details about punctuated sequences.
374///
375/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800376pub struct PairsMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200377 inner: slice::IterMut<'a, (T, P)>,
378 last: option::IntoIter<&'a mut T>,
Alex Crichton164c5332017-07-06 13:18:34 -0700379}
380
David Tolnay56080682018-01-06 14:01:52 -0800381impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
382 type Item = Pair<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700383
David Tolnay6eff4da2018-01-01 20:27:45 -0800384 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700385 self.inner
386 .next()
387 .map(|&mut (ref mut t, ref mut p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700388 .or_else(|| self.last.next().map(Pair::End))
Alex Crichton164c5332017-07-06 13:18:34 -0700389 }
390}
391
David Tolnay9700be02018-04-30 00:51:15 -0700392impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
393 fn len(&self) -> usize {
394 self.inner.len() + self.last.len()
395 }
396}
397
David Tolnayf3198012018-01-06 20:00:42 -0800398/// An iterator over owned pairs of type `Pair<T, P>`.
399///
400/// Refer to the [module documentation] for details about punctuated sequences.
401///
402/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800403pub struct IntoPairs<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200404 inner: vec::IntoIter<(T, P)>,
405 last: option::IntoIter<T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800406}
407
David Tolnay56080682018-01-06 14:01:52 -0800408impl<T, P> Iterator for IntoPairs<T, P> {
409 type Item = Pair<T, P>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800410
411 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700412 self.inner
413 .next()
414 .map(|(t, p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700415 .or_else(|| self.last.next().map(Pair::End))
David Tolnay6eff4da2018-01-01 20:27:45 -0800416 }
417}
418
David Tolnay9700be02018-04-30 00:51:15 -0700419impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
420 fn len(&self) -> usize {
421 self.inner.len() + self.last.len()
422 }
423}
424
David Tolnayf3198012018-01-06 20:00:42 -0800425/// An iterator over owned values of type `T`.
426///
427/// Refer to the [module documentation] for details about punctuated sequences.
428///
429/// [module documentation]: index.html
David Tolnayf2cfd722017-12-31 18:02:51 -0500430pub struct IntoIter<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200431 inner: vec::IntoIter<(T, P)>,
432 last: option::IntoIter<T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700433}
434
David Tolnayf2cfd722017-12-31 18:02:51 -0500435impl<T, P> Iterator for IntoIter<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800436 type Item = T;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700437
David Tolnay6eff4da2018-01-01 20:27:45 -0800438 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700439 self.inner
440 .next()
441 .map(|pair| pair.0)
442 .or_else(|| self.last.next())
David Tolnay6eff4da2018-01-01 20:27:45 -0800443 }
444}
445
David Tolnay9700be02018-04-30 00:51:15 -0700446impl<T, P> ExactSizeIterator for IntoIter<T, P> {
447 fn len(&self) -> usize {
448 self.inner.len() + self.last.len()
449 }
450}
451
David Tolnayf3198012018-01-06 20:00:42 -0800452/// An iterator over borrowed values of type `&T`.
453///
454/// Refer to the [module documentation] for details about punctuated sequences.
455///
456/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200457pub struct Iter<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700458 inner: Box<ExactSizeIterator<Item = &'a T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200459}
460
461struct PrivateIter<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200462 inner: slice::Iter<'a, (T, P)>,
463 last: option::IntoIter<&'a T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800464}
465
David Tolnay96a09d92018-01-16 22:24:03 -0800466#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay8095c302018-03-31 19:34:17 +0200467impl<'a, T> Iter<'a, T> {
David Tolnay96a09d92018-01-16 22:24:03 -0800468 // Not public API.
469 #[doc(hidden)]
470 pub fn private_empty() -> Self {
471 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200472 inner: Box::new(iter::empty()),
David Tolnay96a09d92018-01-16 22:24:03 -0800473 }
474 }
475}
476
David Tolnay8095c302018-03-31 19:34:17 +0200477impl<'a, T> Iterator for Iter<'a, T> {
478 type Item = &'a T;
479
480 fn next(&mut self) -> Option<Self::Item> {
481 self.inner.next()
482 }
483}
484
David Tolnay9700be02018-04-30 00:51:15 -0700485impl<'a, T> ExactSizeIterator for Iter<'a, T> {
486 fn len(&self) -> usize {
487 self.inner.len()
488 }
489}
490
David Tolnay8095c302018-03-31 19:34:17 +0200491impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800492 type Item = &'a T;
493
494 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700495 self.inner
496 .next()
497 .map(|pair| &pair.0)
498 .or_else(|| self.last.next())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700499 }
500}
501
David Tolnay9700be02018-04-30 00:51:15 -0700502impl<'a, T, P> ExactSizeIterator for PrivateIter<'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 mutably borrowed values of type `&mut T`.
509///
510/// Refer to the [module documentation] for details about punctuated sequences.
511///
512/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200513pub struct IterMut<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700514 inner: Box<ExactSizeIterator<Item = &'a mut T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200515}
516
517struct PrivateIterMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200518 inner: slice::IterMut<'a, (T, P)>,
519 last: option::IntoIter<&'a mut T>,
David Tolnaya0834b42018-01-01 21:30:02 -0800520}
521
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600522#[cfg(any(feature = "full", feature = "derive"))]
523impl<'a, T> IterMut<'a, T> {
524 // Not public API.
525 #[doc(hidden)]
526 pub fn private_empty() -> Self {
527 IterMut {
528 inner: Box::new(iter::empty()),
529 }
530 }
531}
532
David Tolnay8095c302018-03-31 19:34:17 +0200533impl<'a, T> Iterator for IterMut<'a, T> {
534 type Item = &'a mut T;
535
536 fn next(&mut self) -> Option<Self::Item> {
537 self.inner.next()
538 }
539}
540
David Tolnay9700be02018-04-30 00:51:15 -0700541impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
542 fn len(&self) -> usize {
543 self.inner.len()
544 }
545}
546
David Tolnay8095c302018-03-31 19:34:17 +0200547impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
David Tolnaya0834b42018-01-01 21:30:02 -0800548 type Item = &'a mut T;
549
550 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700551 self.inner
552 .next()
553 .map(|pair| &mut pair.0)
554 .or_else(|| self.last.next())
David Tolnaya0834b42018-01-01 21:30:02 -0800555 }
556}
557
David Tolnay9700be02018-04-30 00:51:15 -0700558impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
559 fn len(&self) -> usize {
560 self.inner.len() + self.last.len()
561 }
562}
563
David Tolnayf3198012018-01-06 20:00:42 -0800564/// A single syntax tree node of type `T` followed by its trailing punctuation
565/// of type `P` if any.
566///
567/// Refer to the [module documentation] for details about punctuated sequences.
568///
569/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800570pub enum Pair<T, P> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500571 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700572 End(T),
573}
574
David Tolnay56080682018-01-06 14:01:52 -0800575impl<T, P> Pair<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -0800576 /// Extracts the syntax tree node from this punctuated pair, discarding the
577 /// following punctuation.
David Tolnay56080682018-01-06 14:01:52 -0800578 pub fn into_value(self) -> T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700579 match self {
David Tolnay56080682018-01-06 14:01:52 -0800580 Pair::Punctuated(t, _) | Pair::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700581 }
582 }
583
David Tolnayf3198012018-01-06 20:00:42 -0800584 /// Borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800585 pub fn value(&self) -> &T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700586 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800587 Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700588 }
589 }
590
David Tolnayf3198012018-01-06 20:00:42 -0800591 /// Mutably borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800592 pub fn value_mut(&mut self) -> &mut T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700593 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800594 Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700595 }
596 }
597
David Tolnayf3198012018-01-06 20:00:42 -0800598 /// Borrows the punctuation from this punctuated pair, unless this pair is
599 /// the final one and there is no trailing punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500600 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700601 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800602 Pair::Punctuated(_, ref d) => Some(d),
603 Pair::End(_) => None,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700604 }
605 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400606
David Tolnayf3198012018-01-06 20:00:42 -0800607 /// Creates a punctuated pair out of a syntax tree node and an optional
608 /// following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500609 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500610 match d {
David Tolnay56080682018-01-06 14:01:52 -0800611 Some(d) => Pair::Punctuated(t, d),
612 None => Pair::End(t),
David Tolnay660fd1f2017-12-31 01:52:57 -0500613 }
614 }
615
David Tolnayf3198012018-01-06 20:00:42 -0800616 /// Produces this punctuated pair as a tuple of syntax tree node and
617 /// optional following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500618 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400619 match self {
David Tolnay56080682018-01-06 14:01:52 -0800620 Pair::Punctuated(t, d) => (t, Some(d)),
621 Pair::End(t) => (t, None),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400622 }
623 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700624}
625
David Tolnaybb987132018-01-08 13:51:19 -0800626impl<T, P> Index<usize> for Punctuated<T, P> {
627 type Output = T;
628
629 fn index(&self, index: usize) -> &Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200630 if index == self.len() - 1 {
631 match self.last {
632 Some(ref t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700633 None => &self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200634 }
635 } else {
636 &self.inner[index].0
637 }
David Tolnaybb987132018-01-08 13:51:19 -0800638 }
639}
640
641impl<T, P> IndexMut<usize> for Punctuated<T, P> {
642 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200643 if index == self.len() - 1 {
644 match self.last {
645 Some(ref mut t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700646 None => &mut self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200647 }
648 } else {
649 &mut self.inner[index].0
650 }
David Tolnaybb987132018-01-08 13:51:19 -0800651 }
652}
653
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700654#[cfg(feature = "parsing")]
David Tolnay52619f62018-08-31 09:30:01 -0700655impl<T, P> Punctuated<T, P> {
656 pub fn parse_terminated(input: ParseStream) -> Result<Self>
657 where
658 T: Parse,
659 P: Parse,
660 {
David Tolnayd0f80212018-08-30 18:32:14 -0700661 Self::parse_terminated_with(input, T::parse)
662 }
David Tolnayd0f80212018-08-30 18:32:14 -0700663
David Tolnayd0f80212018-08-30 18:32:14 -0700664 pub fn parse_terminated_with(
David Tolnay577d0332018-08-25 21:45:24 -0400665 input: ParseStream,
666 parser: fn(ParseStream) -> Result<T>,
David Tolnay52619f62018-08-31 09:30:01 -0700667 ) -> Result<Self>
668 where
669 P: Parse,
670 {
671 let mut punctuated = Punctuated::new();
David Tolnay577d0332018-08-25 21:45:24 -0400672
673 loop {
674 if input.is_empty() {
675 break;
676 }
677 let value = parser(input)?;
David Tolnay52619f62018-08-31 09:30:01 -0700678 punctuated.push_value(value);
David Tolnay577d0332018-08-25 21:45:24 -0400679 if input.is_empty() {
680 break;
681 }
682 let punct = input.parse()?;
David Tolnay52619f62018-08-31 09:30:01 -0700683 punctuated.push_punct(punct);
David Tolnay577d0332018-08-25 21:45:24 -0400684 }
685
David Tolnay52619f62018-08-31 09:30:01 -0700686 Ok(punctuated)
687 }
688
689 pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
690 where
691 T: Parse,
692 P: Token + Parse,
693 {
694 Self::parse_separated_nonempty_with(input, T::parse)
695 }
696
697 pub fn parse_separated_nonempty_with(
698 input: ParseStream,
699 parser: fn(ParseStream) -> Result<T>,
700 ) -> Result<Self>
701 where
702 P: Token + Parse,
703 {
704 let mut punctuated = Punctuated::new();
705
706 loop {
707 let value = parser(input)?;
708 punctuated.push_value(value);
709 if !P::peek(&input.lookahead1()) {
710 break;
711 }
712 let punct = input.parse()?;
713 punctuated.push_punct(punct);
714 }
715
716 Ok(punctuated)
David Tolnay577d0332018-08-25 21:45:24 -0400717 }
718}
719
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700720#[cfg(feature = "printing")]
721mod printing {
722 use super::*;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700723 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700724 use quote::{ToTokens, TokenStreamExt};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700725
David Tolnayf2cfd722017-12-31 18:02:51 -0500726 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500727 where
728 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500729 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700730 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700731 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay56080682018-01-06 14:01:52 -0800732 tokens.append_all(self.pairs())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700733 }
734 }
735
David Tolnay56080682018-01-06 14:01:52 -0800736 impl<T, P> ToTokens for Pair<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500737 where
738 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500739 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700740 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700741 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700742 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800743 Pair::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700744 a.to_tokens(tokens);
745 b.to_tokens(tokens);
746 }
David Tolnay56080682018-01-06 14:01:52 -0800747 Pair::End(ref a) => a.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700748 }
749 }
750 }
751}