blob: 171e549c1ea14e29b687ec6a9842560fa14c7d62 [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 Tolnayf3198012018-01-06 20:00:42 -080041use buffer::Cursor;
42#[cfg(feature = "parsing")]
David Tolnay577d0332018-08-25 21:45:24 -040043use parse::{Parse, ParseStream, Result};
44#[cfg(feature = "parsing")]
David Tolnayf3198012018-01-06 20:00:42 -080045use parse_error;
David Tolnay94d2b792018-04-29 12:26:10 -070046#[cfg(feature = "parsing")]
47use synom::{PResult, Synom};
David Tolnayf3198012018-01-06 20:00:42 -080048
49/// A punctuated sequence of syntax tree nodes of type `T` separated by
50/// punctuation of type `P`.
51///
52/// Refer to the [module documentation] for details about punctuated sequences.
53///
54/// [module documentation]: index.html
Nika Layzelld73a3652017-10-24 08:57:05 -040055#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070056#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -050057pub struct Punctuated<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020058 inner: Vec<(T, P)>,
59 last: Option<Box<T>>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070060}
61
David Tolnayf2cfd722017-12-31 18:02:51 -050062impl<T, P> Punctuated<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -080063 /// Creates an empty punctuated sequence.
David Tolnayf2cfd722017-12-31 18:02:51 -050064 pub fn new() -> Punctuated<T, P> {
David Tolnay94d2b792018-04-29 12:26:10 -070065 Punctuated {
66 inner: Vec::new(),
67 last: None,
68 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070069 }
70
David Tolnayf3198012018-01-06 20:00:42 -080071 /// Determines whether this punctuated sequence is empty, meaning it
72 /// contains no syntax tree nodes or punctuation.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070073 pub fn is_empty(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020074 self.inner.len() == 0 && self.last.is_none()
Alex Crichtonccbb45d2017-05-23 10:58:24 -070075 }
76
David Tolnayf3198012018-01-06 20:00:42 -080077 /// Returns the number of syntax tree nodes in this punctuated sequence.
78 ///
79 /// This is the number of nodes of type `T`, not counting the punctuation of
80 /// type `P`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070081 pub fn len(&self) -> usize {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020082 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070083 }
84
David Tolnayf3198012018-01-06 20:00:42 -080085 /// Borrows the first punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080086 pub fn first(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020087 self.pairs().next()
Alex Crichton0aa50e02017-07-07 20:59:03 -070088 }
89
David Tolnayf3198012018-01-06 20:00:42 -080090 /// Borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080091 pub fn last(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020092 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -070093 self.last.as_ref().map(|t| Pair::End(t.as_ref()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +020094 } else {
David Tolnay94d2b792018-04-29 12:26:10 -070095 self.inner
96 .last()
Mateusz Naściszewski14111202018-04-11 21:17:41 +020097 .map(|&(ref t, ref d)| Pair::Punctuated(t, d))
98 }
Alex Crichton0aa50e02017-07-07 20:59:03 -070099 }
100
David Tolnayf3198012018-01-06 20:00:42 -0800101 /// Mutably borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -0800102 pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200103 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -0700104 self.last.as_mut().map(|t| Pair::End(t.as_mut()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200105 } else {
David Tolnay94d2b792018-04-29 12:26:10 -0700106 self.inner
107 .last_mut()
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200108 .map(|&mut (ref mut t, ref mut d)| Pair::Punctuated(t, d))
109 }
Alex Crichton0aa50e02017-07-07 20:59:03 -0700110 }
111
David Tolnayf3198012018-01-06 20:00:42 -0800112 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
David Tolnay8095c302018-03-31 19:34:17 +0200113 pub fn iter(&self) -> Iter<T> {
David Tolnay51382052017-12-27 13:46:21 -0500114 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200115 inner: Box::new(PrivateIter {
116 inner: self.inner.iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200117 last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200118 }),
David Tolnay51382052017-12-27 13:46:21 -0500119 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700120 }
121
David Tolnayf3198012018-01-06 20:00:42 -0800122 /// Returns an iterator over mutably borrowed syntax tree nodes of type
123 /// `&mut T`.
David Tolnay8095c302018-03-31 19:34:17 +0200124 pub fn iter_mut(&mut self) -> IterMut<T> {
David Tolnaya0834b42018-01-01 21:30:02 -0800125 IterMut {
David Tolnay8095c302018-03-31 19:34:17 +0200126 inner: Box::new(PrivateIterMut {
127 inner: self.inner.iter_mut(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200128 last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200129 }),
David Tolnaya0834b42018-01-01 21:30:02 -0800130 }
131 }
132
David Tolnayf3198012018-01-06 20:00:42 -0800133 /// Returns an iterator over the contents of this sequence as borrowed
134 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800135 pub fn pairs(&self) -> Pairs<T, P> {
136 Pairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800137 inner: self.inner.iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200138 last: self.last.as_ref().map(|t| t.as_ref()).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800139 }
140 }
141
David Tolnayf3198012018-01-06 20:00:42 -0800142 /// Returns an iterator over the contents of this sequence as mutably
143 /// borrowed punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800144 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
145 PairsMut {
David Tolnay51382052017-12-27 13:46:21 -0500146 inner: self.inner.iter_mut(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200147 last: self.last.as_mut().map(|t| t.as_mut()).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500148 }
Alex Crichton164c5332017-07-06 13:18:34 -0700149 }
150
David Tolnayf3198012018-01-06 20:00:42 -0800151 /// Returns an iterator over the contents of this sequence as owned
152 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800153 pub fn into_pairs(self) -> IntoPairs<T, P> {
154 IntoPairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800155 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200156 last: self.last.map(|t| *t).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800157 }
158 }
159
David Tolnayf3198012018-01-06 20:00:42 -0800160 /// Appends a syntax tree node onto the end of this punctuated sequence. The
161 /// sequence must previously have a trailing punctuation.
162 ///
163 /// Use [`push`] instead if the punctuated sequence may or may not already
164 /// have trailing punctuation.
165 ///
166 /// [`push`]: #method.push
167 ///
168 /// # Panics
169 ///
170 /// Panics if the sequence does not already have a trailing punctuation when
171 /// this method is called.
David Tolnay56080682018-01-06 14:01:52 -0800172 pub fn push_value(&mut self, value: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -0500173 assert!(self.empty_or_trailing());
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200174 self.last = Some(Box::new(value));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700175 }
176
David Tolnayf3198012018-01-06 20:00:42 -0800177 /// Appends a trailing punctuation onto the end of this punctuated sequence.
178 /// The sequence must be non-empty and must not already have trailing
179 /// punctuation.
180 ///
181 /// # Panics
182 ///
183 /// Panics if the sequence is empty or already has a trailing punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800184 pub fn push_punct(&mut self, punctuation: P) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200185 assert!(self.last.is_some());
David Tolnay03163082018-04-11 12:10:18 -0700186 let last = self.last.take().unwrap();
187 self.inner.push((*last, punctuation));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700188 }
189
David Tolnayf3198012018-01-06 20:00:42 -0800190 /// Removes the last punctuated pair from this sequence, or `None` if the
191 /// sequence is empty.
David Tolnay56080682018-01-06 14:01:52 -0800192 pub fn pop(&mut self) -> Option<Pair<T, P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200193 if self.last.is_some() {
David Tolnay03163082018-04-11 12:10:18 -0700194 self.last.take().map(|t| Pair::End(*t))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200195 } else {
196 self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d))
197 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700198 }
199
David Tolnayf3198012018-01-06 20:00:42 -0800200 /// Determines whether this punctuated sequence ends with a trailing
201 /// punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800202 pub fn trailing_punct(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200203 self.last.is_none() && !self.is_empty()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700204 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400205
David Tolnayf2cfd722017-12-31 18:02:51 -0500206 /// Returns true if either this `Punctuated` is empty, or it has a trailing
207 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -0500208 ///
David Tolnaya0834b42018-01-01 21:30:02 -0800209 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -0400210 pub fn empty_or_trailing(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200211 self.last.is_none()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400212 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700213}
214
David Tolnaya0834b42018-01-01 21:30:02 -0800215impl<T, P> Punctuated<T, P>
216where
217 P: Default,
218{
David Tolnayf3198012018-01-06 20:00:42 -0800219 /// Appends a syntax tree node onto the end of this punctuated sequence.
220 ///
221 /// If there is not a trailing punctuation in this sequence when this method
222 /// is called, the default value of punctuation type `P` is inserted before
223 /// the given value of type `T`.
David Tolnay56080682018-01-06 14:01:52 -0800224 pub fn push(&mut self, value: T) {
David Tolnaya0834b42018-01-01 21:30:02 -0800225 if !self.empty_or_trailing() {
226 self.push_punct(Default::default());
227 }
David Tolnay56080682018-01-06 14:01:52 -0800228 self.push_value(value);
David Tolnaya0834b42018-01-01 21:30:02 -0800229 }
David Tolnayb77d1802018-01-11 16:18:35 -0800230
231 /// Inserts an element at position `index`.
232 ///
233 /// # Panics
234 ///
235 /// Panics if `index` is greater than the number of elements previously in
236 /// this punctuated sequence.
237 pub fn insert(&mut self, index: usize, value: T) {
238 assert!(index <= self.len());
239
240 if index == self.len() {
241 self.push(value);
242 } else {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200243 self.inner.insert(index, (value, Default::default()));
David Tolnayb77d1802018-01-11 16:18:35 -0800244 }
245 }
David Tolnaya0834b42018-01-01 21:30:02 -0800246}
247
Nika Layzelld73a3652017-10-24 08:57:05 -0400248#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -0500249impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -0400250 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200251 let mut list = f.debug_list();
David Tolnay0c18c512018-07-22 10:39:10 -0700252 for &(ref t, ref p) in &self.inner {
253 list.entry(t);
254 list.entry(p);
255 }
256 if let Some(ref last) = self.last {
257 list.entry(last);
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200258 }
259 list.finish()
Nika Layzelld73a3652017-10-24 08:57:05 -0400260 }
261}
262
David Tolnay9ef24bc2018-01-09 10:43:55 -0800263impl<T, P> FromIterator<T> for Punctuated<T, P>
264where
265 P: Default,
266{
267 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
268 let mut ret = Punctuated::new();
269 ret.extend(i);
270 ret
271 }
272}
273
274impl<T, P> Extend<T> for Punctuated<T, P>
275where
276 P: Default,
277{
278 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
279 for value in i {
280 self.push(value);
281 }
282 }
283}
284
David Tolnay56080682018-01-06 14:01:52 -0800285impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
286 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500287 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700288 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700289 ret
290 }
291}
292
David Tolnay56080682018-01-06 14:01:52 -0800293impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
294 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200295 assert!(self.empty_or_trailing());
296 let mut nomore = false;
David Tolnay56080682018-01-06 14:01:52 -0800297 for pair in i {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200298 if nomore {
299 panic!("Punctuated extended with items after a Pair::End");
300 }
David Tolnay56080682018-01-06 14:01:52 -0800301 match pair {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200302 Pair::Punctuated(a, b) => self.inner.push((a, b)),
303 Pair::End(a) => {
304 self.last = Some(Box::new(a));
305 nomore = true;
306 }
Alex Crichton24f12822017-07-14 07:15:32 -0700307 }
308 }
309 }
310}
311
David Tolnayf2cfd722017-12-31 18:02:51 -0500312impl<T, P> IntoIterator for Punctuated<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800313 type Item = T;
David Tolnayf2cfd722017-12-31 18:02:51 -0500314 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700315
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500316 fn into_iter(self) -> Self::IntoIter {
David Tolnay51382052017-12-27 13:46:21 -0500317 IntoIter {
318 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200319 last: self.last.map(|t| *t).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500320 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700321 }
322}
323
David Tolnay6eff4da2018-01-01 20:27:45 -0800324impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
325 type Item = &'a T;
David Tolnay8095c302018-03-31 19:34:17 +0200326 type IntoIter = Iter<'a, T>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800327
328 fn into_iter(self) -> Self::IntoIter {
329 Punctuated::iter(self)
330 }
331}
332
David Tolnaya0834b42018-01-01 21:30:02 -0800333impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
334 type Item = &'a mut T;
David Tolnay8095c302018-03-31 19:34:17 +0200335 type IntoIter = IterMut<'a, T>;
David Tolnaya0834b42018-01-01 21:30:02 -0800336
337 fn into_iter(self) -> Self::IntoIter {
338 Punctuated::iter_mut(self)
339 }
340}
341
David Tolnayf2cfd722017-12-31 18:02:51 -0500342impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700343 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500344 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700345 }
346}
347
David Tolnayf3198012018-01-06 20:00:42 -0800348/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
349///
350/// Refer to the [module documentation] for details about punctuated sequences.
351///
352/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800353pub struct Pairs<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200354 inner: slice::Iter<'a, (T, P)>,
355 last: option::IntoIter<&'a T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700356}
357
David Tolnay56080682018-01-06 14:01:52 -0800358impl<'a, T, P> Iterator for Pairs<'a, T, P> {
359 type Item = Pair<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700360
David Tolnay6eff4da2018-01-01 20:27:45 -0800361 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700362 self.inner
363 .next()
364 .map(|&(ref t, ref p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700365 .or_else(|| self.last.next().map(Pair::End))
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700366 }
367}
368
David Tolnay9700be02018-04-30 00:51:15 -0700369impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
370 fn len(&self) -> usize {
371 self.inner.len() + self.last.len()
372 }
373}
374
David Tolnayf3198012018-01-06 20:00:42 -0800375/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
376///
377/// Refer to the [module documentation] for details about punctuated sequences.
378///
379/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800380pub struct PairsMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200381 inner: slice::IterMut<'a, (T, P)>,
382 last: option::IntoIter<&'a mut T>,
Alex Crichton164c5332017-07-06 13:18:34 -0700383}
384
David Tolnay56080682018-01-06 14:01:52 -0800385impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
386 type Item = Pair<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700387
David Tolnay6eff4da2018-01-01 20:27:45 -0800388 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700389 self.inner
390 .next()
391 .map(|&mut (ref mut t, ref mut p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700392 .or_else(|| self.last.next().map(Pair::End))
Alex Crichton164c5332017-07-06 13:18:34 -0700393 }
394}
395
David Tolnay9700be02018-04-30 00:51:15 -0700396impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
397 fn len(&self) -> usize {
398 self.inner.len() + self.last.len()
399 }
400}
401
David Tolnayf3198012018-01-06 20:00:42 -0800402/// An iterator over owned pairs of type `Pair<T, P>`.
403///
404/// Refer to the [module documentation] for details about punctuated sequences.
405///
406/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800407pub struct IntoPairs<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200408 inner: vec::IntoIter<(T, P)>,
409 last: option::IntoIter<T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800410}
411
David Tolnay56080682018-01-06 14:01:52 -0800412impl<T, P> Iterator for IntoPairs<T, P> {
413 type Item = Pair<T, P>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800414
415 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700416 self.inner
417 .next()
418 .map(|(t, p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700419 .or_else(|| self.last.next().map(Pair::End))
David Tolnay6eff4da2018-01-01 20:27:45 -0800420 }
421}
422
David Tolnay9700be02018-04-30 00:51:15 -0700423impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
424 fn len(&self) -> usize {
425 self.inner.len() + self.last.len()
426 }
427}
428
David Tolnayf3198012018-01-06 20:00:42 -0800429/// An iterator over owned values of type `T`.
430///
431/// Refer to the [module documentation] for details about punctuated sequences.
432///
433/// [module documentation]: index.html
David Tolnayf2cfd722017-12-31 18:02:51 -0500434pub struct IntoIter<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200435 inner: vec::IntoIter<(T, P)>,
436 last: option::IntoIter<T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700437}
438
David Tolnayf2cfd722017-12-31 18:02:51 -0500439impl<T, P> Iterator for IntoIter<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800440 type Item = T;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700441
David Tolnay6eff4da2018-01-01 20:27:45 -0800442 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700443 self.inner
444 .next()
445 .map(|pair| pair.0)
446 .or_else(|| self.last.next())
David Tolnay6eff4da2018-01-01 20:27:45 -0800447 }
448}
449
David Tolnay9700be02018-04-30 00:51:15 -0700450impl<T, P> ExactSizeIterator for IntoIter<T, P> {
451 fn len(&self) -> usize {
452 self.inner.len() + self.last.len()
453 }
454}
455
David Tolnayf3198012018-01-06 20:00:42 -0800456/// An iterator over borrowed values of type `&T`.
457///
458/// Refer to the [module documentation] for details about punctuated sequences.
459///
460/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200461pub struct Iter<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700462 inner: Box<ExactSizeIterator<Item = &'a T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200463}
464
465struct PrivateIter<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200466 inner: slice::Iter<'a, (T, P)>,
467 last: option::IntoIter<&'a T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800468}
469
David Tolnay96a09d92018-01-16 22:24:03 -0800470#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay8095c302018-03-31 19:34:17 +0200471impl<'a, T> Iter<'a, T> {
David Tolnay96a09d92018-01-16 22:24:03 -0800472 // Not public API.
473 #[doc(hidden)]
474 pub fn private_empty() -> Self {
475 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200476 inner: Box::new(iter::empty()),
David Tolnay96a09d92018-01-16 22:24:03 -0800477 }
478 }
479}
480
David Tolnay8095c302018-03-31 19:34:17 +0200481impl<'a, T> Iterator for Iter<'a, T> {
482 type Item = &'a T;
483
484 fn next(&mut self) -> Option<Self::Item> {
485 self.inner.next()
486 }
487}
488
David Tolnay9700be02018-04-30 00:51:15 -0700489impl<'a, T> ExactSizeIterator for Iter<'a, T> {
490 fn len(&self) -> usize {
491 self.inner.len()
492 }
493}
494
David Tolnay8095c302018-03-31 19:34:17 +0200495impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800496 type Item = &'a T;
497
498 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700499 self.inner
500 .next()
501 .map(|pair| &pair.0)
502 .or_else(|| self.last.next())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700503 }
504}
505
David Tolnay9700be02018-04-30 00:51:15 -0700506impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
507 fn len(&self) -> usize {
508 self.inner.len() + self.last.len()
509 }
510}
511
David Tolnayf3198012018-01-06 20:00:42 -0800512/// An iterator over mutably borrowed values of type `&mut T`.
513///
514/// Refer to the [module documentation] for details about punctuated sequences.
515///
516/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200517pub struct IterMut<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700518 inner: Box<ExactSizeIterator<Item = &'a mut T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200519}
520
521struct PrivateIterMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200522 inner: slice::IterMut<'a, (T, P)>,
523 last: option::IntoIter<&'a mut T>,
David Tolnaya0834b42018-01-01 21:30:02 -0800524}
525
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600526#[cfg(any(feature = "full", feature = "derive"))]
527impl<'a, T> IterMut<'a, T> {
528 // Not public API.
529 #[doc(hidden)]
530 pub fn private_empty() -> Self {
531 IterMut {
532 inner: Box::new(iter::empty()),
533 }
534 }
535}
536
David Tolnay8095c302018-03-31 19:34:17 +0200537impl<'a, T> Iterator for IterMut<'a, T> {
538 type Item = &'a mut T;
539
540 fn next(&mut self) -> Option<Self::Item> {
541 self.inner.next()
542 }
543}
544
David Tolnay9700be02018-04-30 00:51:15 -0700545impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
546 fn len(&self) -> usize {
547 self.inner.len()
548 }
549}
550
David Tolnay8095c302018-03-31 19:34:17 +0200551impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
David Tolnaya0834b42018-01-01 21:30:02 -0800552 type Item = &'a mut T;
553
554 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700555 self.inner
556 .next()
557 .map(|pair| &mut pair.0)
558 .or_else(|| self.last.next())
David Tolnaya0834b42018-01-01 21:30:02 -0800559 }
560}
561
David Tolnay9700be02018-04-30 00:51:15 -0700562impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
563 fn len(&self) -> usize {
564 self.inner.len() + self.last.len()
565 }
566}
567
David Tolnayf3198012018-01-06 20:00:42 -0800568/// A single syntax tree node of type `T` followed by its trailing punctuation
569/// of type `P` if any.
570///
571/// Refer to the [module documentation] for details about punctuated sequences.
572///
573/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800574pub enum Pair<T, P> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500575 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700576 End(T),
577}
578
David Tolnay56080682018-01-06 14:01:52 -0800579impl<T, P> Pair<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -0800580 /// Extracts the syntax tree node from this punctuated pair, discarding the
581 /// following punctuation.
David Tolnay56080682018-01-06 14:01:52 -0800582 pub fn into_value(self) -> T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700583 match self {
David Tolnay56080682018-01-06 14:01:52 -0800584 Pair::Punctuated(t, _) | Pair::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700585 }
586 }
587
David Tolnayf3198012018-01-06 20:00:42 -0800588 /// Borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800589 pub fn value(&self) -> &T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700590 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800591 Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700592 }
593 }
594
David Tolnayf3198012018-01-06 20:00:42 -0800595 /// Mutably borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800596 pub fn value_mut(&mut self) -> &mut T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700597 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800598 Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700599 }
600 }
601
David Tolnayf3198012018-01-06 20:00:42 -0800602 /// Borrows the punctuation from this punctuated pair, unless this pair is
603 /// the final one and there is no trailing punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500604 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700605 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800606 Pair::Punctuated(_, ref d) => Some(d),
607 Pair::End(_) => None,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700608 }
609 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400610
David Tolnayf3198012018-01-06 20:00:42 -0800611 /// Creates a punctuated pair out of a syntax tree node and an optional
612 /// following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500613 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500614 match d {
David Tolnay56080682018-01-06 14:01:52 -0800615 Some(d) => Pair::Punctuated(t, d),
616 None => Pair::End(t),
David Tolnay660fd1f2017-12-31 01:52:57 -0500617 }
618 }
619
David Tolnayf3198012018-01-06 20:00:42 -0800620 /// Produces this punctuated pair as a tuple of syntax tree node and
621 /// optional following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500622 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400623 match self {
David Tolnay56080682018-01-06 14:01:52 -0800624 Pair::Punctuated(t, d) => (t, Some(d)),
625 Pair::End(t) => (t, None),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400626 }
627 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700628}
629
David Tolnaybb987132018-01-08 13:51:19 -0800630impl<T, P> Index<usize> for Punctuated<T, P> {
631 type Output = T;
632
633 fn index(&self, index: usize) -> &Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200634 if index == self.len() - 1 {
635 match self.last {
636 Some(ref t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700637 None => &self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200638 }
639 } else {
640 &self.inner[index].0
641 }
David Tolnaybb987132018-01-08 13:51:19 -0800642 }
643}
644
645impl<T, P> IndexMut<usize> for Punctuated<T, P> {
646 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200647 if index == self.len() - 1 {
648 match self.last {
649 Some(ref mut t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700650 None => &mut self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200651 }
652 } else {
653 &mut self.inner[index].0
654 }
David Tolnaybb987132018-01-08 13:51:19 -0800655 }
656}
657
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700658#[cfg(feature = "parsing")]
David Tolnayf3198012018-01-06 20:00:42 -0800659impl<T, P> Punctuated<T, P>
660where
661 T: Synom,
662 P: Synom,
663{
664 /// Parse **zero or more** syntax tree nodes with punctuation in between and
665 /// **no trailing** punctuation.
666 pub fn parse_separated(input: Cursor) -> PResult<Self> {
667 Self::parse_separated_with(input, T::parse)
668 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700669
David Tolnayf3198012018-01-06 20:00:42 -0800670 /// Parse **one or more** syntax tree nodes with punctuation in bewteen and
671 /// **no trailing** punctuation.
672 /// allowing trailing punctuation.
673 pub fn parse_separated_nonempty(input: Cursor) -> PResult<Self> {
674 Self::parse_separated_nonempty_with(input, T::parse)
675 }
Alex Crichton954046c2017-05-30 21:49:42 -0700676
David Tolnayf3198012018-01-06 20:00:42 -0800677 /// Parse **zero or more** syntax tree nodes with punctuation in between and
678 /// **optional trailing** punctuation.
679 pub fn parse_terminated(input: Cursor) -> PResult<Self> {
680 Self::parse_terminated_with(input, T::parse)
681 }
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700682
David Tolnayf3198012018-01-06 20:00:42 -0800683 /// Parse **one or more** syntax tree nodes with punctuation in between and
684 /// **optional trailing** punctuation.
685 pub fn parse_terminated_nonempty(input: Cursor) -> PResult<Self> {
686 Self::parse_terminated_nonempty_with(input, T::parse)
687 }
688}
Nika Layzellb49a9e52017-12-05 13:31:52 -0500689
David Tolnayf3198012018-01-06 20:00:42 -0800690#[cfg(feature = "parsing")]
691impl<T, P> Punctuated<T, P>
692where
693 P: Synom,
694{
695 /// Parse **zero or more** syntax tree nodes using the given parser with
696 /// punctuation in between and **no trailing** punctuation.
David Tolnay94d2b792018-04-29 12:26:10 -0700697 pub fn parse_separated_with(input: Cursor, parse: fn(Cursor) -> PResult<T>) -> PResult<Self> {
David Tolnayf3198012018-01-06 20:00:42 -0800698 Self::parse(input, parse, false)
699 }
700
701 /// Parse **one or more** syntax tree nodes using the given parser with
702 /// punctuation in between and **no trailing** punctuation.
703 pub fn parse_separated_nonempty_with(
704 input: Cursor,
705 parse: fn(Cursor) -> PResult<T>,
706 ) -> PResult<Self> {
707 match Self::parse(input, parse, false) {
708 Ok((ref b, _)) if b.is_empty() => parse_error(),
709 other => other,
Nika Layzellb49a9e52017-12-05 13:31:52 -0500710 }
Alex Crichton954046c2017-05-30 21:49:42 -0700711 }
712
David Tolnayf3198012018-01-06 20:00:42 -0800713 /// Parse **zero or more** syntax tree nodes using the given parser with
714 /// punctuation in between and **optional trailing** punctuation.
David Tolnay94d2b792018-04-29 12:26:10 -0700715 pub fn parse_terminated_with(input: Cursor, parse: fn(Cursor) -> PResult<T>) -> PResult<Self> {
David Tolnayf3198012018-01-06 20:00:42 -0800716 Self::parse(input, parse, true)
717 }
718
719 /// Parse **one or more** syntax tree nodes using the given parser with
720 /// punctuation in between and **optional trailing** punctuation.
721 pub fn parse_terminated_nonempty_with(
722 input: Cursor,
723 parse: fn(Cursor) -> PResult<T>,
724 ) -> PResult<Self> {
725 match Self::parse(input, parse, true) {
726 Ok((ref b, _)) if b.is_empty() => parse_error(),
727 other => other,
David Tolnaydc03aec2017-12-30 01:54:18 -0500728 }
David Tolnayf3198012018-01-06 20:00:42 -0800729 }
David Tolnaydc03aec2017-12-30 01:54:18 -0500730
David Tolnayf3198012018-01-06 20:00:42 -0800731 fn parse(
732 mut input: Cursor,
733 parse: fn(Cursor) -> PResult<T>,
734 terminated: bool,
735 ) -> PResult<Self> {
736 let mut res = Punctuated::new();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700737
David Tolnayf3198012018-01-06 20:00:42 -0800738 // get the first element
739 match parse(input) {
740 Err(_) => Ok((res, input)),
741 Ok((o, i)) => {
742 if i == input {
743 return parse_error();
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700744 }
David Tolnayf3198012018-01-06 20:00:42 -0800745 input = i;
746 res.push_value(o);
747
748 // get the separator first
749 while let Ok((s, i2)) = P::parse(input) {
750 if i2 == input {
751 break;
752 }
753
754 // get the element next
755 if let Ok((o3, i3)) = parse(i2) {
756 if i3 == i2 {
757 break;
758 }
759 res.push_punct(s);
760 res.push_value(o3);
761 input = i3;
762 } else {
763 break;
764 }
765 }
766 if terminated {
767 if let Ok((sep, after)) = P::parse(input) {
768 res.push_punct(sep);
769 input = after;
770 }
771 }
772 Ok((res, input))
Alex Crichton7b9e02f2017-05-30 15:54:33 -0700773 }
774 }
775 }
776}
777
David Tolnay577d0332018-08-25 21:45:24 -0400778#[cfg(feature = "parsing")]
779impl<T, P> Punctuated<T, P>
780where
781 P: Parse,
782{
783 pub fn parse_terminated2(
784 input: ParseStream,
785 parser: fn(ParseStream) -> Result<T>,
786 ) -> Result<Self> {
787 let mut res = Punctuated::new();
788
789 loop {
790 if input.is_empty() {
791 break;
792 }
793 let value = parser(input)?;
794 res.push_value(value);
795 if input.is_empty() {
796 break;
797 }
798 let punct = input.parse()?;
799 res.push_punct(punct);
800 }
801
802 Ok(res)
803 }
804}
805
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700806#[cfg(feature = "printing")]
807mod printing {
808 use super::*;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700809 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700810 use quote::{ToTokens, TokenStreamExt};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700811
David Tolnayf2cfd722017-12-31 18:02:51 -0500812 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500813 where
814 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500815 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700816 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700817 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay56080682018-01-06 14:01:52 -0800818 tokens.append_all(self.pairs())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700819 }
820 }
821
David Tolnay56080682018-01-06 14:01:52 -0800822 impl<T, P> ToTokens for Pair<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500823 where
824 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500825 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700826 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700827 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700828 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800829 Pair::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700830 a.to_tokens(tokens);
831 b.to_tokens(tokens);
832 }
David Tolnay56080682018-01-06 14:01:52 -0800833 Pair::End(ref a) => a.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700834 }
835 }
836 }
837}