blob: ecd18b42bf0d316eece18fcc5bb03d55352e9142 [file] [log] [blame]
David Tolnayf3198012018-01-06 20:00:42 -08001//! A punctuated sequence of syntax tree nodes separated by punctuation.
2//!
3//! Lots of things in Rust are punctuated sequences.
4//!
5//! - The fields of a struct are `Punctuated<Field, Token![,]>`.
6//! - The segments of a path are `Punctuated<PathSegment, Token![::]>`.
7//! - The bounds on a generic parameter are `Punctuated<TypeParamBound, Token![+]>`.
8//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
9//!
10//! This module provides a common representation for these punctuated sequences
11//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
12//! syntax tree node + punctuation, where every node in the sequence is followed
13//! by punctuation except for possibly the final one.
14//!
15//! [`Punctuated<T, P>`]: struct.Punctuated.html
16//!
17//! ```text
18//! a_function_call(arg1, arg2, arg3);
19//! ^^^^^ ~~~~~ ^^^^
20//! ```
21
David Tolnay94d2b792018-04-29 12:26:10 -070022#[cfg(feature = "extra-traits")]
23use std::fmt::{self, Debug};
David Tolnay6c0a6092018-03-31 22:47:39 +020024#[cfg(any(feature = "full", feature = "derive"))]
25use std::iter;
26use std::iter::FromIterator;
David Tolnaybb987132018-01-08 13:51:19 -080027use std::ops::{Index, IndexMut};
Mateusz Naściszewski14111202018-04-11 21:17:41 +020028use std::option;
Alex Crichtonccbb45d2017-05-23 10:58:24 -070029use std::slice;
30use std::vec;
31
David Tolnayf3198012018-01-06 20:00:42 -080032#[cfg(feature = "parsing")]
David Tolnayecf0fbc2018-08-30 18:28:33 -070033use parse::{Parse, ParseStream, Result};
David Tolnay94f06632018-08-31 10:17:17 -070034#[cfg(any(feature = "full", feature = "derive"))]
35use private;
David Tolnay52619f62018-08-31 09:30:01 -070036#[cfg(feature = "parsing")]
37use token::Token;
David Tolnayf3198012018-01-06 20:00:42 -080038
39/// A punctuated sequence of syntax tree nodes of type `T` separated by
40/// punctuation of type `P`.
41///
42/// Refer to the [module documentation] for details about punctuated sequences.
43///
44/// [module documentation]: index.html
Nika Layzelld73a3652017-10-24 08:57:05 -040045#[cfg_attr(feature = "extra-traits", derive(Eq, PartialEq, Hash))]
Alex Crichton7b9e02f2017-05-30 15:54:33 -070046#[cfg_attr(feature = "clone-impls", derive(Clone))]
David Tolnayf2cfd722017-12-31 18:02:51 -050047pub struct Punctuated<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020048 inner: Vec<(T, P)>,
49 last: Option<Box<T>>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -070050}
51
David Tolnayf2cfd722017-12-31 18:02:51 -050052impl<T, P> Punctuated<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -080053 /// Creates an empty punctuated sequence.
David Tolnayf2cfd722017-12-31 18:02:51 -050054 pub fn new() -> Punctuated<T, P> {
David Tolnay94d2b792018-04-29 12:26:10 -070055 Punctuated {
56 inner: Vec::new(),
57 last: None,
58 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070059 }
60
David Tolnayf3198012018-01-06 20:00:42 -080061 /// Determines whether this punctuated sequence is empty, meaning it
62 /// contains no syntax tree nodes or punctuation.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070063 pub fn is_empty(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020064 self.inner.len() == 0 && self.last.is_none()
Alex Crichtonccbb45d2017-05-23 10:58:24 -070065 }
66
David Tolnayf3198012018-01-06 20:00:42 -080067 /// Returns the number of syntax tree nodes in this punctuated sequence.
68 ///
69 /// This is the number of nodes of type `T`, not counting the punctuation of
70 /// type `P`.
Alex Crichtonccbb45d2017-05-23 10:58:24 -070071 pub fn len(&self) -> usize {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020072 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -070073 }
74
David Tolnayf3198012018-01-06 20:00:42 -080075 /// Borrows the first punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080076 pub fn first(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020077 self.pairs().next()
Alex Crichton0aa50e02017-07-07 20:59:03 -070078 }
79
David Tolnayf3198012018-01-06 20:00:42 -080080 /// Borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080081 pub fn last(&self) -> Option<Pair<&T, &P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020082 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -070083 self.last.as_ref().map(|t| Pair::End(t.as_ref()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +020084 } else {
David Tolnay94d2b792018-04-29 12:26:10 -070085 self.inner
86 .last()
Mateusz Naściszewski14111202018-04-11 21:17:41 +020087 .map(|&(ref t, ref d)| Pair::Punctuated(t, d))
88 }
Alex Crichton0aa50e02017-07-07 20:59:03 -070089 }
90
David Tolnayf3198012018-01-06 20:00:42 -080091 /// Mutably borrows the last punctuated pair in this sequence.
David Tolnay56080682018-01-06 14:01:52 -080092 pub fn last_mut(&mut self) -> Option<Pair<&mut T, &mut P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +020093 if self.last.is_some() {
David Tolnay94d2b792018-04-29 12:26:10 -070094 self.last.as_mut().map(|t| Pair::End(t.as_mut()))
Mateusz Naściszewski14111202018-04-11 21:17:41 +020095 } else {
David Tolnay94d2b792018-04-29 12:26:10 -070096 self.inner
97 .last_mut()
Mateusz Naściszewski14111202018-04-11 21:17:41 +020098 .map(|&mut (ref mut t, ref mut d)| Pair::Punctuated(t, d))
99 }
Alex Crichton0aa50e02017-07-07 20:59:03 -0700100 }
101
David Tolnayf3198012018-01-06 20:00:42 -0800102 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
David Tolnay8095c302018-03-31 19:34:17 +0200103 pub fn iter(&self) -> Iter<T> {
David Tolnay51382052017-12-27 13:46:21 -0500104 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200105 inner: Box::new(PrivateIter {
106 inner: self.inner.iter(),
David Tolnay124e50b2019-02-28 23:53:36 -0800107 last: self.last.as_ref().map(Box::as_ref).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200108 }),
David Tolnay51382052017-12-27 13:46:21 -0500109 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700110 }
111
David Tolnayf3198012018-01-06 20:00:42 -0800112 /// Returns an iterator over mutably borrowed syntax tree nodes of type
113 /// `&mut T`.
David Tolnay8095c302018-03-31 19:34:17 +0200114 pub fn iter_mut(&mut self) -> IterMut<T> {
David Tolnaya0834b42018-01-01 21:30:02 -0800115 IterMut {
David Tolnay8095c302018-03-31 19:34:17 +0200116 inner: Box::new(PrivateIterMut {
117 inner: self.inner.iter_mut(),
David Tolnay124e50b2019-02-28 23:53:36 -0800118 last: self.last.as_mut().map(Box::as_mut).into_iter(),
David Tolnay8095c302018-03-31 19:34:17 +0200119 }),
David Tolnaya0834b42018-01-01 21:30:02 -0800120 }
121 }
122
David Tolnayf3198012018-01-06 20:00:42 -0800123 /// Returns an iterator over the contents of this sequence as borrowed
124 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800125 pub fn pairs(&self) -> Pairs<T, P> {
126 Pairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800127 inner: self.inner.iter(),
David Tolnay124e50b2019-02-28 23:53:36 -0800128 last: self.last.as_ref().map(Box::as_ref).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800129 }
130 }
131
David Tolnayf3198012018-01-06 20:00:42 -0800132 /// Returns an iterator over the contents of this sequence as mutably
133 /// borrowed punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800134 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
135 PairsMut {
David Tolnay51382052017-12-27 13:46:21 -0500136 inner: self.inner.iter_mut(),
David Tolnay124e50b2019-02-28 23:53:36 -0800137 last: self.last.as_mut().map(Box::as_mut).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500138 }
Alex Crichton164c5332017-07-06 13:18:34 -0700139 }
140
David Tolnayf3198012018-01-06 20:00:42 -0800141 /// Returns an iterator over the contents of this sequence as owned
142 /// punctuated pairs.
David Tolnay56080682018-01-06 14:01:52 -0800143 pub fn into_pairs(self) -> IntoPairs<T, P> {
144 IntoPairs {
David Tolnay6eff4da2018-01-01 20:27:45 -0800145 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200146 last: self.last.map(|t| *t).into_iter(),
David Tolnay6eff4da2018-01-01 20:27:45 -0800147 }
148 }
149
David Tolnayf3198012018-01-06 20:00:42 -0800150 /// Appends a syntax tree node onto the end of this punctuated sequence. The
151 /// sequence must previously have a trailing punctuation.
152 ///
153 /// Use [`push`] instead if the punctuated sequence may or may not already
154 /// have trailing punctuation.
155 ///
156 /// [`push`]: #method.push
157 ///
158 /// # Panics
159 ///
160 /// Panics if the sequence does not already have a trailing punctuation when
161 /// this method is called.
David Tolnay56080682018-01-06 14:01:52 -0800162 pub fn push_value(&mut self, value: T) {
David Tolnaydc03aec2017-12-30 01:54:18 -0500163 assert!(self.empty_or_trailing());
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200164 self.last = Some(Box::new(value));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700165 }
166
David Tolnayf3198012018-01-06 20:00:42 -0800167 /// Appends a trailing punctuation onto the end of this punctuated sequence.
168 /// The sequence must be non-empty and must not already have trailing
169 /// punctuation.
170 ///
171 /// # Panics
172 ///
173 /// Panics if the sequence is empty or already has a trailing punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800174 pub fn push_punct(&mut self, punctuation: P) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200175 assert!(self.last.is_some());
David Tolnay03163082018-04-11 12:10:18 -0700176 let last = self.last.take().unwrap();
177 self.inner.push((*last, punctuation));
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700178 }
179
David Tolnayf3198012018-01-06 20:00:42 -0800180 /// Removes the last punctuated pair from this sequence, or `None` if the
181 /// sequence is empty.
David Tolnay56080682018-01-06 14:01:52 -0800182 pub fn pop(&mut self) -> Option<Pair<T, P>> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200183 if self.last.is_some() {
David Tolnay03163082018-04-11 12:10:18 -0700184 self.last.take().map(|t| Pair::End(*t))
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200185 } else {
186 self.inner.pop().map(|(t, d)| Pair::Punctuated(t, d))
187 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700188 }
189
David Tolnayf3198012018-01-06 20:00:42 -0800190 /// Determines whether this punctuated sequence ends with a trailing
191 /// punctuation.
David Tolnaya0834b42018-01-01 21:30:02 -0800192 pub fn trailing_punct(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200193 self.last.is_none() && !self.is_empty()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700194 }
Michael Layzell3936ceb2017-07-08 00:28:36 -0400195
David Tolnayf2cfd722017-12-31 18:02:51 -0500196 /// Returns true if either this `Punctuated` is empty, or it has a trailing
197 /// punctuation.
David Tolnaydc03aec2017-12-30 01:54:18 -0500198 ///
David Tolnaya0834b42018-01-01 21:30:02 -0800199 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
Michael Layzell3936ceb2017-07-08 00:28:36 -0400200 pub fn empty_or_trailing(&self) -> bool {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200201 self.last.is_none()
Michael Layzell3936ceb2017-07-08 00:28:36 -0400202 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700203
David Tolnayf3198012018-01-06 20:00:42 -0800204 /// Appends a syntax tree node onto the end of this punctuated sequence.
205 ///
206 /// If there is not a trailing punctuation in this sequence when this method
207 /// is called, the default value of punctuation type `P` is inserted before
208 /// the given value of type `T`.
David Tolnay8842c7e2018-09-01 12:37:32 -0700209 pub fn push(&mut self, value: T)
210 where
211 P: Default,
212 {
David Tolnaya0834b42018-01-01 21:30:02 -0800213 if !self.empty_or_trailing() {
214 self.push_punct(Default::default());
215 }
David Tolnay56080682018-01-06 14:01:52 -0800216 self.push_value(value);
David Tolnaya0834b42018-01-01 21:30:02 -0800217 }
David Tolnayb77d1802018-01-11 16:18:35 -0800218
219 /// Inserts an element at position `index`.
220 ///
221 /// # Panics
222 ///
223 /// Panics if `index` is greater than the number of elements previously in
224 /// this punctuated sequence.
David Tolnay8842c7e2018-09-01 12:37:32 -0700225 pub fn insert(&mut self, index: usize, value: T)
226 where
227 P: Default,
228 {
David Tolnayb77d1802018-01-11 16:18:35 -0800229 assert!(index <= self.len());
230
231 if index == self.len() {
232 self.push(value);
233 } else {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200234 self.inner.insert(index, (value, Default::default()));
David Tolnayb77d1802018-01-11 16:18:35 -0800235 }
236 }
David Tolnay8842c7e2018-09-01 12:37:32 -0700237
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700238 /// Parses zero or more occurrences of `T` separated by punctuation of type
239 /// `P`, with optional trailing punctuation.
240 ///
241 /// Parsing continues until the end of this parse stream. The entire content
242 /// of this parse stream must consist of `T` and `P`.
David Tolnay206edfb2018-09-01 16:02:20 -0700243 ///
244 /// *This function is available if Syn is built with the `"parsing"`
245 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700246 #[cfg(feature = "parsing")]
247 pub fn parse_terminated(input: ParseStream) -> Result<Self>
248 where
249 T: Parse,
250 P: Parse,
251 {
252 Self::parse_terminated_with(input, T::parse)
253 }
254
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700255 /// Parses zero or more occurrences of `T` using the given parse function,
256 /// separated by punctuation of type `P`, with optional trailing
257 /// punctuation.
258 ///
259 /// Like [`parse_terminated`], the entire content of this stream is expected
260 /// to be parsed.
261 ///
262 /// [`parse_terminated`]: #method.parse_terminated
David Tolnay206edfb2018-09-01 16:02:20 -0700263 ///
264 /// *This function is available if Syn is built with the `"parsing"`
265 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700266 #[cfg(feature = "parsing")]
267 pub fn parse_terminated_with(
268 input: ParseStream,
269 parser: fn(ParseStream) -> Result<T>,
270 ) -> Result<Self>
271 where
272 P: Parse,
273 {
274 let mut punctuated = Punctuated::new();
275
276 loop {
277 if input.is_empty() {
278 break;
279 }
280 let value = parser(input)?;
281 punctuated.push_value(value);
282 if input.is_empty() {
283 break;
284 }
285 let punct = input.parse()?;
286 punctuated.push_punct(punct);
287 }
288
289 Ok(punctuated)
290 }
291
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700292 /// Parses one or more occurrences of `T` separated by punctuation of type
293 /// `P`, not accepting trailing punctuation.
294 ///
295 /// Parsing continues as long as punctuation `P` is present at the head of
296 /// the stream. This method returns upon parsing a `T` and observing that it
297 /// is not followed by a `P`, even if there are remaining tokens in the
298 /// stream.
David Tolnay206edfb2018-09-01 16:02:20 -0700299 ///
300 /// *This function is available if Syn is built with the `"parsing"`
301 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700302 #[cfg(feature = "parsing")]
303 pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
304 where
305 T: Parse,
306 P: Token + Parse,
307 {
308 Self::parse_separated_nonempty_with(input, T::parse)
309 }
310
David Tolnay0f2a4ac2018-09-01 12:44:25 -0700311 /// Parses one or more occurrences of `T` using the given parse function,
312 /// separated by punctuation of type `P`, not accepting trailing
313 /// punctuation.
314 ///
315 /// Like [`parse_separated_nonempty`], may complete early without parsing
316 /// the entire content of this stream.
317 ///
318 /// [`parse_separated_nonempty`]: #method.parse_separated_nonempty
David Tolnay206edfb2018-09-01 16:02:20 -0700319 ///
320 /// *This function is available if Syn is built with the `"parsing"`
321 /// feature.*
David Tolnay8842c7e2018-09-01 12:37:32 -0700322 #[cfg(feature = "parsing")]
323 pub fn parse_separated_nonempty_with(
324 input: ParseStream,
325 parser: fn(ParseStream) -> Result<T>,
326 ) -> Result<Self>
327 where
328 P: Token + Parse,
329 {
330 let mut punctuated = Punctuated::new();
331
332 loop {
333 let value = parser(input)?;
334 punctuated.push_value(value);
335 if !P::peek(input.cursor()) {
336 break;
337 }
338 let punct = input.parse()?;
339 punctuated.push_punct(punct);
340 }
341
342 Ok(punctuated)
343 }
David Tolnaya0834b42018-01-01 21:30:02 -0800344}
345
Nika Layzelld73a3652017-10-24 08:57:05 -0400346#[cfg(feature = "extra-traits")]
David Tolnayf2cfd722017-12-31 18:02:51 -0500347impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
Nika Layzelld73a3652017-10-24 08:57:05 -0400348 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200349 let mut list = f.debug_list();
David Tolnay0c18c512018-07-22 10:39:10 -0700350 for &(ref t, ref p) in &self.inner {
351 list.entry(t);
352 list.entry(p);
353 }
354 if let Some(ref last) = self.last {
355 list.entry(last);
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200356 }
357 list.finish()
Nika Layzelld73a3652017-10-24 08:57:05 -0400358 }
359}
360
David Tolnay9ef24bc2018-01-09 10:43:55 -0800361impl<T, P> FromIterator<T> for Punctuated<T, P>
362where
363 P: Default,
364{
365 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
366 let mut ret = Punctuated::new();
367 ret.extend(i);
368 ret
369 }
370}
371
372impl<T, P> Extend<T> for Punctuated<T, P>
373where
374 P: Default,
375{
376 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
377 for value in i {
378 self.push(value);
379 }
380 }
381}
382
David Tolnay56080682018-01-06 14:01:52 -0800383impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
384 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500385 let mut ret = Punctuated::new();
Alex Crichton24f12822017-07-14 07:15:32 -0700386 ret.extend(i);
Alex Crichton954046c2017-05-30 21:49:42 -0700387 ret
388 }
389}
390
David Tolnay56080682018-01-06 14:01:52 -0800391impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
392 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200393 assert!(self.empty_or_trailing());
394 let mut nomore = false;
David Tolnay56080682018-01-06 14:01:52 -0800395 for pair in i {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200396 if nomore {
397 panic!("Punctuated extended with items after a Pair::End");
398 }
David Tolnay56080682018-01-06 14:01:52 -0800399 match pair {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200400 Pair::Punctuated(a, b) => self.inner.push((a, b)),
401 Pair::End(a) => {
402 self.last = Some(Box::new(a));
403 nomore = true;
404 }
Alex Crichton24f12822017-07-14 07:15:32 -0700405 }
406 }
407 }
408}
409
David Tolnayf2cfd722017-12-31 18:02:51 -0500410impl<T, P> IntoIterator for Punctuated<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800411 type Item = T;
David Tolnayf2cfd722017-12-31 18:02:51 -0500412 type IntoIter = IntoIter<T, P>;
Alex Crichton954046c2017-05-30 21:49:42 -0700413
David Tolnaybb4ca9f2017-12-26 12:28:58 -0500414 fn into_iter(self) -> Self::IntoIter {
David Tolnay51382052017-12-27 13:46:21 -0500415 IntoIter {
416 inner: self.inner.into_iter(),
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200417 last: self.last.map(|t| *t).into_iter(),
David Tolnay51382052017-12-27 13:46:21 -0500418 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700419 }
420}
421
David Tolnay6eff4da2018-01-01 20:27:45 -0800422impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
423 type Item = &'a T;
David Tolnay8095c302018-03-31 19:34:17 +0200424 type IntoIter = Iter<'a, T>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800425
426 fn into_iter(self) -> Self::IntoIter {
427 Punctuated::iter(self)
428 }
429}
430
David Tolnaya0834b42018-01-01 21:30:02 -0800431impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
432 type Item = &'a mut T;
David Tolnay8095c302018-03-31 19:34:17 +0200433 type IntoIter = IterMut<'a, T>;
David Tolnaya0834b42018-01-01 21:30:02 -0800434
435 fn into_iter(self) -> Self::IntoIter {
436 Punctuated::iter_mut(self)
437 }
438}
439
David Tolnayf2cfd722017-12-31 18:02:51 -0500440impl<T, P> Default for Punctuated<T, P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700441 fn default() -> Self {
David Tolnayf2cfd722017-12-31 18:02:51 -0500442 Punctuated::new()
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700443 }
444}
445
David Tolnayf3198012018-01-06 20:00:42 -0800446/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
447///
448/// Refer to the [module documentation] for details about punctuated sequences.
449///
450/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800451pub struct Pairs<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200452 inner: slice::Iter<'a, (T, P)>,
453 last: option::IntoIter<&'a T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700454}
455
David Tolnay56080682018-01-06 14:01:52 -0800456impl<'a, T, P> Iterator for Pairs<'a, T, P> {
457 type Item = Pair<&'a T, &'a P>;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700458
David Tolnay6eff4da2018-01-01 20:27:45 -0800459 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700460 self.inner
461 .next()
462 .map(|&(ref t, ref p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700463 .or_else(|| self.last.next().map(Pair::End))
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700464 }
465}
466
David Tolnay9700be02018-04-30 00:51:15 -0700467impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
468 fn len(&self) -> usize {
469 self.inner.len() + self.last.len()
470 }
471}
472
David Tolnayf3198012018-01-06 20:00:42 -0800473/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
474///
475/// Refer to the [module documentation] for details about punctuated sequences.
476///
477/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800478pub struct PairsMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200479 inner: slice::IterMut<'a, (T, P)>,
480 last: option::IntoIter<&'a mut T>,
Alex Crichton164c5332017-07-06 13:18:34 -0700481}
482
David Tolnay56080682018-01-06 14:01:52 -0800483impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
484 type Item = Pair<&'a mut T, &'a mut P>;
Alex Crichton164c5332017-07-06 13:18:34 -0700485
David Tolnay6eff4da2018-01-01 20:27:45 -0800486 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700487 self.inner
488 .next()
489 .map(|&mut (ref mut t, ref mut p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700490 .or_else(|| self.last.next().map(Pair::End))
Alex Crichton164c5332017-07-06 13:18:34 -0700491 }
492}
493
David Tolnay9700be02018-04-30 00:51:15 -0700494impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
495 fn len(&self) -> usize {
496 self.inner.len() + self.last.len()
497 }
498}
499
David Tolnayf3198012018-01-06 20:00:42 -0800500/// An iterator over owned pairs of type `Pair<T, P>`.
501///
502/// Refer to the [module documentation] for details about punctuated sequences.
503///
504/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800505pub struct IntoPairs<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200506 inner: vec::IntoIter<(T, P)>,
507 last: option::IntoIter<T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800508}
509
David Tolnay56080682018-01-06 14:01:52 -0800510impl<T, P> Iterator for IntoPairs<T, P> {
511 type Item = Pair<T, P>;
David Tolnay6eff4da2018-01-01 20:27:45 -0800512
513 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700514 self.inner
515 .next()
516 .map(|(t, p)| Pair::Punctuated(t, p))
David Tolnay6e4a9c22018-04-11 12:20:08 -0700517 .or_else(|| self.last.next().map(Pair::End))
David Tolnay6eff4da2018-01-01 20:27:45 -0800518 }
519}
520
David Tolnay9700be02018-04-30 00:51:15 -0700521impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
522 fn len(&self) -> usize {
523 self.inner.len() + self.last.len()
524 }
525}
526
David Tolnayf3198012018-01-06 20:00:42 -0800527/// An iterator over owned values of type `T`.
528///
529/// Refer to the [module documentation] for details about punctuated sequences.
530///
531/// [module documentation]: index.html
David Tolnayf2cfd722017-12-31 18:02:51 -0500532pub struct IntoIter<T, P> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200533 inner: vec::IntoIter<(T, P)>,
534 last: option::IntoIter<T>,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700535}
536
David Tolnayf2cfd722017-12-31 18:02:51 -0500537impl<T, P> Iterator for IntoIter<T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800538 type Item = T;
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700539
David Tolnay6eff4da2018-01-01 20:27:45 -0800540 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700541 self.inner
542 .next()
543 .map(|pair| pair.0)
544 .or_else(|| self.last.next())
David Tolnay6eff4da2018-01-01 20:27:45 -0800545 }
546}
547
David Tolnay9700be02018-04-30 00:51:15 -0700548impl<T, P> ExactSizeIterator for IntoIter<T, P> {
549 fn len(&self) -> usize {
550 self.inner.len() + self.last.len()
551 }
552}
553
David Tolnayf3198012018-01-06 20:00:42 -0800554/// An iterator over borrowed values of type `&T`.
555///
556/// Refer to the [module documentation] for details about punctuated sequences.
557///
558/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200559pub struct Iter<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700560 inner: Box<ExactSizeIterator<Item = &'a T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200561}
562
563struct PrivateIter<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200564 inner: slice::Iter<'a, (T, P)>,
565 last: option::IntoIter<&'a T>,
David Tolnay6eff4da2018-01-01 20:27:45 -0800566}
567
David Tolnay96a09d92018-01-16 22:24:03 -0800568#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -0700569impl private {
570 pub fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
David Tolnay96a09d92018-01-16 22:24:03 -0800571 Iter {
David Tolnay8095c302018-03-31 19:34:17 +0200572 inner: Box::new(iter::empty()),
David Tolnay96a09d92018-01-16 22:24:03 -0800573 }
574 }
575}
576
David Tolnay8095c302018-03-31 19:34:17 +0200577impl<'a, T> Iterator for Iter<'a, T> {
578 type Item = &'a T;
579
580 fn next(&mut self) -> Option<Self::Item> {
581 self.inner.next()
582 }
583}
584
David Tolnay9700be02018-04-30 00:51:15 -0700585impl<'a, T> ExactSizeIterator for Iter<'a, T> {
586 fn len(&self) -> usize {
587 self.inner.len()
588 }
589}
590
David Tolnay8095c302018-03-31 19:34:17 +0200591impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
David Tolnay6eff4da2018-01-01 20:27:45 -0800592 type Item = &'a T;
593
594 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700595 self.inner
596 .next()
597 .map(|pair| &pair.0)
598 .or_else(|| self.last.next())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700599 }
600}
601
David Tolnay9700be02018-04-30 00:51:15 -0700602impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
603 fn len(&self) -> usize {
604 self.inner.len() + self.last.len()
605 }
606}
607
David Tolnayf3198012018-01-06 20:00:42 -0800608/// An iterator over mutably borrowed values of type `&mut T`.
609///
610/// Refer to the [module documentation] for details about punctuated sequences.
611///
612/// [module documentation]: index.html
David Tolnay8095c302018-03-31 19:34:17 +0200613pub struct IterMut<'a, T: 'a> {
David Tolnay9700be02018-04-30 00:51:15 -0700614 inner: Box<ExactSizeIterator<Item = &'a mut T> + 'a>,
David Tolnay8095c302018-03-31 19:34:17 +0200615}
616
617struct PrivateIterMut<'a, T: 'a, P: 'a> {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200618 inner: slice::IterMut<'a, (T, P)>,
619 last: option::IntoIter<&'a mut T>,
David Tolnaya0834b42018-01-01 21:30:02 -0800620}
621
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600622#[cfg(any(feature = "full", feature = "derive"))]
David Tolnay10951d52018-08-31 10:27:39 -0700623impl private {
624 pub fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
Michael Bradshaw0b13ae62018-08-02 23:43:15 -0600625 IterMut {
626 inner: Box::new(iter::empty()),
627 }
628 }
629}
630
David Tolnay8095c302018-03-31 19:34:17 +0200631impl<'a, T> Iterator for IterMut<'a, T> {
632 type Item = &'a mut T;
633
634 fn next(&mut self) -> Option<Self::Item> {
635 self.inner.next()
636 }
637}
638
David Tolnay9700be02018-04-30 00:51:15 -0700639impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
640 fn len(&self) -> usize {
641 self.inner.len()
642 }
643}
644
David Tolnay8095c302018-03-31 19:34:17 +0200645impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
David Tolnaya0834b42018-01-01 21:30:02 -0800646 type Item = &'a mut T;
647
648 fn next(&mut self) -> Option<Self::Item> {
David Tolnay94d2b792018-04-29 12:26:10 -0700649 self.inner
650 .next()
651 .map(|pair| &mut pair.0)
652 .or_else(|| self.last.next())
David Tolnaya0834b42018-01-01 21:30:02 -0800653 }
654}
655
David Tolnay9700be02018-04-30 00:51:15 -0700656impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
657 fn len(&self) -> usize {
658 self.inner.len() + self.last.len()
659 }
660}
661
David Tolnayf3198012018-01-06 20:00:42 -0800662/// A single syntax tree node of type `T` followed by its trailing punctuation
663/// of type `P` if any.
664///
665/// Refer to the [module documentation] for details about punctuated sequences.
666///
667/// [module documentation]: index.html
David Tolnay56080682018-01-06 14:01:52 -0800668pub enum Pair<T, P> {
David Tolnayf2cfd722017-12-31 18:02:51 -0500669 Punctuated(T, P),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700670 End(T),
671}
672
David Tolnay56080682018-01-06 14:01:52 -0800673impl<T, P> Pair<T, P> {
David Tolnayf3198012018-01-06 20:00:42 -0800674 /// Extracts the syntax tree node from this punctuated pair, discarding the
675 /// following punctuation.
David Tolnay56080682018-01-06 14:01:52 -0800676 pub fn into_value(self) -> T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700677 match self {
David Tolnay56080682018-01-06 14:01:52 -0800678 Pair::Punctuated(t, _) | Pair::End(t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700679 }
680 }
681
David Tolnayf3198012018-01-06 20:00:42 -0800682 /// Borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800683 pub fn value(&self) -> &T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700684 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800685 Pair::Punctuated(ref t, _) | Pair::End(ref t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700686 }
687 }
688
David Tolnayf3198012018-01-06 20:00:42 -0800689 /// Mutably borrows the syntax tree node from this punctuated pair.
David Tolnay56080682018-01-06 14:01:52 -0800690 pub fn value_mut(&mut self) -> &mut T {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700691 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800692 Pair::Punctuated(ref mut t, _) | Pair::End(ref mut t) => t,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700693 }
694 }
695
David Tolnayf3198012018-01-06 20:00:42 -0800696 /// Borrows the punctuation from this punctuated pair, unless this pair is
697 /// the final one and there is no trailing punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500698 pub fn punct(&self) -> Option<&P> {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700699 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800700 Pair::Punctuated(_, ref d) => Some(d),
701 Pair::End(_) => None,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700702 }
703 }
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400704
David Tolnayf3198012018-01-06 20:00:42 -0800705 /// Creates a punctuated pair out of a syntax tree node and an optional
706 /// following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500707 pub fn new(t: T, d: Option<P>) -> Self {
David Tolnay660fd1f2017-12-31 01:52:57 -0500708 match d {
David Tolnay56080682018-01-06 14:01:52 -0800709 Some(d) => Pair::Punctuated(t, d),
710 None => Pair::End(t),
David Tolnay660fd1f2017-12-31 01:52:57 -0500711 }
712 }
713
David Tolnayf3198012018-01-06 20:00:42 -0800714 /// Produces this punctuated pair as a tuple of syntax tree node and
715 /// optional following punctuation.
David Tolnayf2cfd722017-12-31 18:02:51 -0500716 pub fn into_tuple(self) -> (T, Option<P>) {
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400717 match self {
David Tolnay56080682018-01-06 14:01:52 -0800718 Pair::Punctuated(t, d) => (t, Some(d)),
719 Pair::End(t) => (t, None),
Nika Layzellcda7ebd2017-10-24 23:10:44 -0400720 }
721 }
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700722}
723
David Tolnaybb987132018-01-08 13:51:19 -0800724impl<T, P> Index<usize> for Punctuated<T, P> {
725 type Output = T;
726
727 fn index(&self, index: usize) -> &Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200728 if index == self.len() - 1 {
729 match self.last {
730 Some(ref t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700731 None => &self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200732 }
733 } else {
734 &self.inner[index].0
735 }
David Tolnaybb987132018-01-08 13:51:19 -0800736 }
737}
738
739impl<T, P> IndexMut<usize> for Punctuated<T, P> {
740 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200741 if index == self.len() - 1 {
742 match self.last {
743 Some(ref mut t) => t,
David Tolnay94d2b792018-04-29 12:26:10 -0700744 None => &mut self.inner[index].0,
Mateusz Naściszewski14111202018-04-11 21:17:41 +0200745 }
746 } else {
747 &mut self.inner[index].0
748 }
David Tolnaybb987132018-01-08 13:51:19 -0800749 }
750}
751
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700752#[cfg(feature = "printing")]
753mod printing {
754 use super::*;
Alex Crichtona74a1c82018-05-16 10:20:44 -0700755 use proc_macro2::TokenStream;
David Tolnay65fb5662018-05-20 20:02:28 -0700756 use quote::{ToTokens, TokenStreamExt};
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700757
David Tolnayf2cfd722017-12-31 18:02:51 -0500758 impl<T, P> ToTokens for Punctuated<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500759 where
760 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500761 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700762 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700763 fn to_tokens(&self, tokens: &mut TokenStream) {
David Tolnay56080682018-01-06 14:01:52 -0800764 tokens.append_all(self.pairs())
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700765 }
766 }
767
David Tolnay56080682018-01-06 14:01:52 -0800768 impl<T, P> ToTokens for Pair<T, P>
David Tolnay51382052017-12-27 13:46:21 -0500769 where
770 T: ToTokens,
David Tolnayf2cfd722017-12-31 18:02:51 -0500771 P: ToTokens,
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700772 {
Alex Crichtona74a1c82018-05-16 10:20:44 -0700773 fn to_tokens(&self, tokens: &mut TokenStream) {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700774 match *self {
David Tolnay56080682018-01-06 14:01:52 -0800775 Pair::Punctuated(ref a, ref b) => {
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700776 a.to_tokens(tokens);
777 b.to_tokens(tokens);
778 }
David Tolnay56080682018-01-06 14:01:52 -0800779 Pair::End(ref a) => a.to_tokens(tokens),
Alex Crichtonccbb45d2017-05-23 10:58:24 -0700780 }
781 }
782 }
783}