1//! 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,
8//! Token![+]>`.
9//! - The arguments to a function call are `Punctuated<Expr, Token![,]>`.
10//!
11//! This module provides a common representation for these punctuated sequences
12//! in the form of the [`Punctuated<T, P>`] type. We store a vector of pairs of
13//! syntax tree node + punctuation, where every node in the sequence is followed
14//! by punctuation except for possibly the final one.
15//!
16//! [`Punctuated<T, P>`]: Punctuated
17//!
18//! ```text
19//! a_function_call(arg1, arg2, arg3);
20//! ~~~~^ ~~~~^ ~~~~
21//! ```
22
23#[cfg(feature = "extra-traits")]
24use std::fmt::{self, Debug};
25#[cfg(feature = "extra-traits")]
26use std::hash::{Hash, Hasher};
27#[cfg(any(feature = "full", feature = "derive"))]
28use std::iter;
29use std::ops::{Index, IndexMut};
30use std::option;
31use std::slice;
32use std::vec;
33
34use crate::drops::{NoDrop, TrivialDrop};
35#[cfg(feature = "parsing")]
36use crate::parse::{Parse, ParseStream, Result};
37#[cfg(feature = "parsing")]
38use crate::token::Token;
39
40/// **A punctuated sequence of syntax tree nodes of type `T` separated by
41/// punctuation of type `P`.**
42///
43/// Refer to the [module documentation] for details about punctuated sequences.
44///
45/// [module documentation]: self
46pub struct Punctuated<T, P> {
47 inner: Vec<(T, P)>,
48 last: Option<Box<T>>,
49}
50
51impl<T, P> Punctuated<T, P> {
52 /// Creates an empty punctuated sequence.
53 pub const fn new() -> Self {
54 Punctuated {
55 inner: Vec::new(),
56 last: None,
57 }
58 }
59
60 /// Determines whether this punctuated sequence is empty, meaning it
61 /// contains no syntax tree nodes or punctuation.
62 pub fn is_empty(&self) -> bool {
63 self.inner.len() == 0 && self.last.is_none()
64 }
65
66 /// Returns the number of syntax tree nodes in this punctuated sequence.
67 ///
68 /// This is the number of nodes of type `T`, not counting the punctuation of
69 /// type `P`.
70 pub fn len(&self) -> usize {
71 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
72 }
73
74 /// Borrows the first element in this sequence.
75 pub fn first(&self) -> Option<&T> {
76 self.iter().next()
77 }
78
79 /// Mutably borrows the first element in this sequence.
80 pub fn first_mut(&mut self) -> Option<&mut T> {
81 self.iter_mut().next()
82 }
83
84 /// Borrows the last element in this sequence.
85 pub fn last(&self) -> Option<&T> {
86 self.iter().next_back()
87 }
88
89 /// Mutably borrows the last element in this sequence.
90 pub fn last_mut(&mut self) -> Option<&mut T> {
91 self.iter_mut().next_back()
92 }
93
94 /// Returns an iterator over borrowed syntax tree nodes of type `&T`.
95 pub fn iter(&self) -> Iter<T> {
96 Iter {
97 inner: Box::new(NoDrop::new(PrivateIter {
98 inner: self.inner.iter(),
99 last: self.last.as_ref().map(Box::as_ref).into_iter(),
100 })),
101 }
102 }
103
104 /// Returns an iterator over mutably borrowed syntax tree nodes of type
105 /// `&mut T`.
106 pub fn iter_mut(&mut self) -> IterMut<T> {
107 IterMut {
108 inner: Box::new(NoDrop::new(PrivateIterMut {
109 inner: self.inner.iter_mut(),
110 last: self.last.as_mut().map(Box::as_mut).into_iter(),
111 })),
112 }
113 }
114
115 /// Returns an iterator over the contents of this sequence as borrowed
116 /// punctuated pairs.
117 pub fn pairs(&self) -> Pairs<T, P> {
118 Pairs {
119 inner: self.inner.iter(),
120 last: self.last.as_ref().map(Box::as_ref).into_iter(),
121 }
122 }
123
124 /// Returns an iterator over the contents of this sequence as mutably
125 /// borrowed punctuated pairs.
126 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
127 PairsMut {
128 inner: self.inner.iter_mut(),
129 last: self.last.as_mut().map(Box::as_mut).into_iter(),
130 }
131 }
132
133 /// Returns an iterator over the contents of this sequence as owned
134 /// punctuated pairs.
135 pub fn into_pairs(self) -> IntoPairs<T, P> {
136 IntoPairs {
137 inner: self.inner.into_iter(),
138 last: self.last.map(|t| *t).into_iter(),
139 }
140 }
141
142 /// Appends a syntax tree node onto the end of this punctuated sequence. The
143 /// sequence must already have a trailing punctuation, or be empty.
144 ///
145 /// Use [`push`] instead if the punctuated sequence may or may not already
146 /// have trailing punctuation.
147 ///
148 /// [`push`]: Punctuated::push
149 ///
150 /// # Panics
151 ///
152 /// Panics if the sequence is nonempty and does not already have a trailing
153 /// punctuation.
154 pub fn push_value(&mut self, value: T) {
155 assert!(
156 self.empty_or_trailing(),
157 "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation",
158 );
159
160 self.last = Some(Box::new(value));
161 }
162
163 /// Appends a trailing punctuation onto the end of this punctuated sequence.
164 /// The sequence must be non-empty and must not already have trailing
165 /// punctuation.
166 ///
167 /// # Panics
168 ///
169 /// Panics if the sequence is empty or already has a trailing punctuation.
170 pub fn push_punct(&mut self, punctuation: P) {
171 assert!(
172 self.last.is_some(),
173 "Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation",
174 );
175
176 let last = self.last.take().unwrap();
177 self.inner.push((*last, punctuation));
178 }
179
180 /// Removes the last punctuated pair from this sequence, or `None` if the
181 /// sequence is empty.
182 pub fn pop(&mut self) -> Option<Pair<T, P>> {
183 if self.last.is_some() {
184 self.last.take().map(|t| Pair::End(*t))
185 } else {
186 self.inner.pop().map(|(t, p)| Pair::Punctuated(t, p))
187 }
188 }
189
190 /// Removes the trailing punctuation from this punctuated sequence, or
191 /// `None` if there isn't any.
192 pub fn pop_punct(&mut self) -> Option<P> {
193 if self.last.is_some() {
194 None
195 } else {
196 let (t, p) = self.inner.pop()?;
197 self.last = Some(Box::new(t));
198 Some(p)
199 }
200 }
201
202 /// Determines whether this punctuated sequence ends with a trailing
203 /// punctuation.
204 pub fn trailing_punct(&self) -> bool {
205 self.last.is_none() && !self.is_empty()
206 }
207
208 /// Returns true if either this `Punctuated` is empty, or it has a trailing
209 /// punctuation.
210 ///
211 /// Equivalent to `punctuated.is_empty() || punctuated.trailing_punct()`.
212 pub fn empty_or_trailing(&self) -> bool {
213 self.last.is_none()
214 }
215
216 /// Appends a syntax tree node onto the end of this punctuated sequence.
217 ///
218 /// If there is not a trailing punctuation in this sequence when this method
219 /// is called, the default value of punctuation type `P` is inserted before
220 /// the given value of type `T`.
221 pub fn push(&mut self, value: T)
222 where
223 P: Default,
224 {
225 if !self.empty_or_trailing() {
226 self.push_punct(Default::default());
227 }
228 self.push_value(value);
229 }
230
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 where
239 P: Default,
240 {
241 assert!(
242 index <= self.len(),
243 "Punctuated::insert: index out of range",
244 );
245
246 if index == self.len() {
247 self.push(value);
248 } else {
249 self.inner.insert(index, (value, Default::default()));
250 }
251 }
252
253 /// Clears the sequence of all values and punctuation, making it empty.
254 pub fn clear(&mut self) {
255 self.inner.clear();
256 self.last = None;
257 }
258
259 /// Parses zero or more occurrences of `T` separated by punctuation of type
260 /// `P`, with optional trailing punctuation.
261 ///
262 /// Parsing continues until the end of this parse stream. The entire content
263 /// of this parse stream must consist of `T` and `P`.
264 #[cfg(feature = "parsing")]
265 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
266 pub fn parse_terminated(input: ParseStream) -> Result<Self>
267 where
268 T: Parse,
269 P: Parse,
270 {
271 Self::parse_terminated_with(input, T::parse)
272 }
273
274 /// Parses zero or more occurrences of `T` using the given parse function,
275 /// separated by punctuation of type `P`, with optional trailing
276 /// punctuation.
277 ///
278 /// Like [`parse_terminated`], the entire content of this stream is expected
279 /// to be parsed.
280 ///
281 /// [`parse_terminated`]: Punctuated::parse_terminated
282 #[cfg(feature = "parsing")]
283 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
284 pub fn parse_terminated_with(
285 input: ParseStream,
286 parser: fn(ParseStream) -> Result<T>,
287 ) -> Result<Self>
288 where
289 P: Parse,
290 {
291 let mut punctuated = Punctuated::new();
292
293 loop {
294 if input.is_empty() {
295 break;
296 }
297 let value = parser(input)?;
298 punctuated.push_value(value);
299 if input.is_empty() {
300 break;
301 }
302 let punct = input.parse()?;
303 punctuated.push_punct(punct);
304 }
305
306 Ok(punctuated)
307 }
308
309 /// Parses one or more occurrences of `T` separated by punctuation of type
310 /// `P`, not accepting trailing punctuation.
311 ///
312 /// Parsing continues as long as punctuation `P` is present at the head of
313 /// the stream. This method returns upon parsing a `T` and observing that it
314 /// is not followed by a `P`, even if there are remaining tokens in the
315 /// stream.
316 #[cfg(feature = "parsing")]
317 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
318 pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
319 where
320 T: Parse,
321 P: Token + Parse,
322 {
323 Self::parse_separated_nonempty_with(input, T::parse)
324 }
325
326 /// Parses one or more occurrences of `T` using the given parse function,
327 /// separated by punctuation of type `P`, not accepting trailing
328 /// punctuation.
329 ///
330 /// Like [`parse_separated_nonempty`], may complete early without parsing
331 /// the entire content of this stream.
332 ///
333 /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty
334 #[cfg(feature = "parsing")]
335 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
336 pub fn parse_separated_nonempty_with(
337 input: ParseStream,
338 parser: fn(ParseStream) -> Result<T>,
339 ) -> Result<Self>
340 where
341 P: Token + Parse,
342 {
343 let mut punctuated = Punctuated::new();
344
345 loop {
346 let value = parser(input)?;
347 punctuated.push_value(value);
348 if !P::peek(input.cursor()) {
349 break;
350 }
351 let punct = input.parse()?;
352 punctuated.push_punct(punct);
353 }
354
355 Ok(punctuated)
356 }
357}
358
359#[cfg(feature = "clone-impls")]
360#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
361impl<T, P> Clone for Punctuated<T, P>
362where
363 T: Clone,
364 P: Clone,
365{
366 fn clone(&self) -> Self {
367 Punctuated {
368 inner: self.inner.clone(),
369 last: self.last.clone(),
370 }
371 }
372
373 fn clone_from(&mut self, other: &Self) {
374 self.inner.clone_from(&other.inner);
375 self.last.clone_from(&other.last);
376 }
377}
378
379#[cfg(feature = "extra-traits")]
380#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
381impl<T, P> Eq for Punctuated<T, P>
382where
383 T: Eq,
384 P: Eq,
385{
386}
387
388#[cfg(feature = "extra-traits")]
389#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
390impl<T, P> PartialEq for Punctuated<T, P>
391where
392 T: PartialEq,
393 P: PartialEq,
394{
395 fn eq(&self, other: &Self) -> bool {
396 let Punctuated { inner, last } = self;
397 *inner == other.inner && *last == other.last
398 }
399}
400
401#[cfg(feature = "extra-traits")]
402#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
403impl<T, P> Hash for Punctuated<T, P>
404where
405 T: Hash,
406 P: Hash,
407{
408 fn hash<H: Hasher>(&self, state: &mut H) {
409 let Punctuated { inner, last } = self;
410 inner.hash(state);
411 last.hash(state);
412 }
413}
414
415#[cfg(feature = "extra-traits")]
416#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
417impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
418 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
419 let mut list = f.debug_list();
420 for (t, p) in &self.inner {
421 list.entry(t);
422 list.entry(p);
423 }
424 if let Some(last) = &self.last {
425 list.entry(last);
426 }
427 list.finish()
428 }
429}
430
431impl<T, P> FromIterator<T> for Punctuated<T, P>
432where
433 P: Default,
434{
435 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
436 let mut ret = Punctuated::new();
437 ret.extend(i);
438 ret
439 }
440}
441
442impl<T, P> Extend<T> for Punctuated<T, P>
443where
444 P: Default,
445{
446 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
447 for value in i {
448 self.push(value);
449 }
450 }
451}
452
453impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
454 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
455 let mut ret = Punctuated::new();
456 do_extend(&mut ret, i.into_iter());
457 ret
458 }
459}
460
461impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P>
462where
463 P: Default,
464{
465 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
466 if !self.empty_or_trailing() {
467 self.push_punct(P::default());
468 }
469 do_extend(self, i.into_iter());
470 }
471}
472
473fn do_extend<T, P, I>(punctuated: &mut Punctuated<T, P>, i: I)
474where
475 I: Iterator<Item = Pair<T, P>>,
476{
477 let mut nomore = false;
478 for pair in i {
479 if nomore {
480 panic!("Punctuated extended with items after a Pair::End");
481 }
482 match pair {
483 Pair::Punctuated(a, b) => punctuated.inner.push((a, b)),
484 Pair::End(a) => {
485 punctuated.last = Some(Box::new(a));
486 nomore = true;
487 }
488 }
489 }
490}
491
492impl<T, P> IntoIterator for Punctuated<T, P> {
493 type Item = T;
494 type IntoIter = IntoIter<T>;
495
496 fn into_iter(self) -> Self::IntoIter {
497 let mut elements = Vec::with_capacity(self.len());
498 elements.extend(self.inner.into_iter().map(|pair| pair.0));
499 elements.extend(self.last.map(|t| *t));
500
501 IntoIter {
502 inner: elements.into_iter(),
503 }
504 }
505}
506
507impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
508 type Item = &'a T;
509 type IntoIter = Iter<'a, T>;
510
511 fn into_iter(self) -> Self::IntoIter {
512 Punctuated::iter(self)
513 }
514}
515
516impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
517 type Item = &'a mut T;
518 type IntoIter = IterMut<'a, T>;
519
520 fn into_iter(self) -> Self::IntoIter {
521 Punctuated::iter_mut(self)
522 }
523}
524
525impl<T, P> Default for Punctuated<T, P> {
526 fn default() -> Self {
527 Punctuated::new()
528 }
529}
530
531/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
532///
533/// Refer to the [module documentation] for details about punctuated sequences.
534///
535/// [module documentation]: self
536pub struct Pairs<'a, T: 'a, P: 'a> {
537 inner: slice::Iter<'a, (T, P)>,
538 last: option::IntoIter<&'a T>,
539}
540
541impl<'a, T, P> Iterator for Pairs<'a, T, P> {
542 type Item = Pair<&'a T, &'a P>;
543
544 fn next(&mut self) -> Option<Self::Item> {
545 self.inner
546 .next()
547 .map(|(t, p)| Pair::Punctuated(t, p))
548 .or_else(|| self.last.next().map(Pair::End))
549 }
550
551 fn size_hint(&self) -> (usize, Option<usize>) {
552 (self.len(), Some(self.len()))
553 }
554}
555
556impl<'a, T, P> DoubleEndedIterator for Pairs<'a, T, P> {
557 fn next_back(&mut self) -> Option<Self::Item> {
558 self.last
559 .next()
560 .map(Pair::End)
561 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
562 }
563}
564
565impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
566 fn len(&self) -> usize {
567 self.inner.len() + self.last.len()
568 }
569}
570
571// No Clone bound on T or P.
572impl<'a, T, P> Clone for Pairs<'a, T, P> {
573 fn clone(&self) -> Self {
574 Pairs {
575 inner: self.inner.clone(),
576 last: self.last.clone(),
577 }
578 }
579}
580
581/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
582///
583/// Refer to the [module documentation] for details about punctuated sequences.
584///
585/// [module documentation]: self
586pub struct PairsMut<'a, T: 'a, P: 'a> {
587 inner: slice::IterMut<'a, (T, P)>,
588 last: option::IntoIter<&'a mut T>,
589}
590
591impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
592 type Item = Pair<&'a mut T, &'a mut P>;
593
594 fn next(&mut self) -> Option<Self::Item> {
595 self.inner
596 .next()
597 .map(|(t, p)| Pair::Punctuated(t, p))
598 .or_else(|| self.last.next().map(Pair::End))
599 }
600
601 fn size_hint(&self) -> (usize, Option<usize>) {
602 (self.len(), Some(self.len()))
603 }
604}
605
606impl<'a, T, P> DoubleEndedIterator for PairsMut<'a, T, P> {
607 fn next_back(&mut self) -> Option<Self::Item> {
608 self.last
609 .next()
610 .map(Pair::End)
611 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
612 }
613}
614
615impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
616 fn len(&self) -> usize {
617 self.inner.len() + self.last.len()
618 }
619}
620
621/// An iterator over owned pairs of type `Pair<T, P>`.
622///
623/// Refer to the [module documentation] for details about punctuated sequences.
624///
625/// [module documentation]: self
626pub struct IntoPairs<T, P> {
627 inner: vec::IntoIter<(T, P)>,
628 last: option::IntoIter<T>,
629}
630
631impl<T, P> Iterator for IntoPairs<T, P> {
632 type Item = Pair<T, P>;
633
634 fn next(&mut self) -> Option<Self::Item> {
635 self.inner
636 .next()
637 .map(|(t, p)| Pair::Punctuated(t, p))
638 .or_else(|| self.last.next().map(Pair::End))
639 }
640
641 fn size_hint(&self) -> (usize, Option<usize>) {
642 (self.len(), Some(self.len()))
643 }
644}
645
646impl<T, P> DoubleEndedIterator for IntoPairs<T, P> {
647 fn next_back(&mut self) -> Option<Self::Item> {
648 self.last
649 .next()
650 .map(Pair::End)
651 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
652 }
653}
654
655impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
656 fn len(&self) -> usize {
657 self.inner.len() + self.last.len()
658 }
659}
660
661impl<T, P> Clone for IntoPairs<T, P>
662where
663 T: Clone,
664 P: Clone,
665{
666 fn clone(&self) -> Self {
667 IntoPairs {
668 inner: self.inner.clone(),
669 last: self.last.clone(),
670 }
671 }
672}
673
674/// An iterator over owned values of type `T`.
675///
676/// Refer to the [module documentation] for details about punctuated sequences.
677///
678/// [module documentation]: self
679pub struct IntoIter<T> {
680 inner: vec::IntoIter<T>,
681}
682
683impl<T> Iterator for IntoIter<T> {
684 type Item = T;
685
686 fn next(&mut self) -> Option<Self::Item> {
687 self.inner.next()
688 }
689
690 fn size_hint(&self) -> (usize, Option<usize>) {
691 (self.len(), Some(self.len()))
692 }
693}
694
695impl<T> DoubleEndedIterator for IntoIter<T> {
696 fn next_back(&mut self) -> Option<Self::Item> {
697 self.inner.next_back()
698 }
699}
700
701impl<T> ExactSizeIterator for IntoIter<T> {
702 fn len(&self) -> usize {
703 self.inner.len()
704 }
705}
706
707impl<T> Clone for IntoIter<T>
708where
709 T: Clone,
710{
711 fn clone(&self) -> Self {
712 IntoIter {
713 inner: self.inner.clone(),
714 }
715 }
716}
717
718/// An iterator over borrowed values of type `&T`.
719///
720/// Refer to the [module documentation] for details about punctuated sequences.
721///
722/// [module documentation]: self
723pub struct Iter<'a, T: 'a> {
724 inner: Box<NoDrop<dyn IterTrait<'a, T> + 'a>>,
725}
726
727trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> + DoubleEndedIterator + ExactSizeIterator {
728 fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>>;
729}
730
731struct PrivateIter<'a, T: 'a, P: 'a> {
732 inner: slice::Iter<'a, (T, P)>,
733 last: option::IntoIter<&'a T>,
734}
735
736impl<'a, T, P> TrivialDrop for PrivateIter<'a, T, P>
737where
738 slice::Iter<'a, (T, P)>: TrivialDrop,
739 option::IntoIter<&'a T>: TrivialDrop,
740{
741}
742
743#[cfg(any(feature = "full", feature = "derive"))]
744pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
745 Iter {
746 inner: Box::new(NoDrop::new(iter::empty())),
747 }
748}
749
750// No Clone bound on T.
751impl<'a, T> Clone for Iter<'a, T> {
752 fn clone(&self) -> Self {
753 Iter {
754 inner: self.inner.clone_box(),
755 }
756 }
757}
758
759impl<'a, T> Iterator for Iter<'a, T> {
760 type Item = &'a T;
761
762 fn next(&mut self) -> Option<Self::Item> {
763 self.inner.next()
764 }
765
766 fn size_hint(&self) -> (usize, Option<usize>) {
767 (self.len(), Some(self.len()))
768 }
769}
770
771impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
772 fn next_back(&mut self) -> Option<Self::Item> {
773 self.inner.next_back()
774 }
775}
776
777impl<'a, T> ExactSizeIterator for Iter<'a, T> {
778 fn len(&self) -> usize {
779 self.inner.len()
780 }
781}
782
783impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
784 type Item = &'a T;
785
786 fn next(&mut self) -> Option<Self::Item> {
787 self.inner
788 .next()
789 .map(|pair| &pair.0)
790 .or_else(|| self.last.next())
791 }
792}
793
794impl<'a, T, P> DoubleEndedIterator for PrivateIter<'a, T, P> {
795 fn next_back(&mut self) -> Option<Self::Item> {
796 self.last
797 .next()
798 .or_else(|| self.inner.next_back().map(|pair| &pair.0))
799 }
800}
801
802impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
803 fn len(&self) -> usize {
804 self.inner.len() + self.last.len()
805 }
806}
807
808// No Clone bound on T or P.
809impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
810 fn clone(&self) -> Self {
811 PrivateIter {
812 inner: self.inner.clone(),
813 last: self.last.clone(),
814 }
815 }
816}
817
818impl<'a, T, I> IterTrait<'a, T> for I
819where
820 T: 'a,
821 I: DoubleEndedIterator<Item = &'a T>
822 + ExactSizeIterator<Item = &'a T>
823 + Clone
824 + TrivialDrop
825 + 'a,
826{
827 fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>> {
828 Box::new(NoDrop::new(self.clone()))
829 }
830}
831
832/// An iterator over mutably borrowed values of type `&mut T`.
833///
834/// Refer to the [module documentation] for details about punctuated sequences.
835///
836/// [module documentation]: self
837pub struct IterMut<'a, T: 'a> {
838 inner: Box<NoDrop<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>>,
839}
840
841trait IterMutTrait<'a, T: 'a>:
842 DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T>
843{
844}
845
846struct PrivateIterMut<'a, T: 'a, P: 'a> {
847 inner: slice::IterMut<'a, (T, P)>,
848 last: option::IntoIter<&'a mut T>,
849}
850
851impl<'a, T, P> TrivialDrop for PrivateIterMut<'a, T, P>
852where
853 slice::IterMut<'a, (T, P)>: TrivialDrop,
854 option::IntoIter<&'a mut T>: TrivialDrop,
855{
856}
857
858#[cfg(any(feature = "full", feature = "derive"))]
859pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
860 IterMut {
861 inner: Box::new(NoDrop::new(iter::empty())),
862 }
863}
864
865impl<'a, T> Iterator for IterMut<'a, T> {
866 type Item = &'a mut T;
867
868 fn next(&mut self) -> Option<Self::Item> {
869 self.inner.next()
870 }
871
872 fn size_hint(&self) -> (usize, Option<usize>) {
873 (self.len(), Some(self.len()))
874 }
875}
876
877impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
878 fn next_back(&mut self) -> Option<Self::Item> {
879 self.inner.next_back()
880 }
881}
882
883impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
884 fn len(&self) -> usize {
885 self.inner.len()
886 }
887}
888
889impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
890 type Item = &'a mut T;
891
892 fn next(&mut self) -> Option<Self::Item> {
893 self.inner
894 .next()
895 .map(|pair| &mut pair.0)
896 .or_else(|| self.last.next())
897 }
898}
899
900impl<'a, T, P> DoubleEndedIterator for PrivateIterMut<'a, T, P> {
901 fn next_back(&mut self) -> Option<Self::Item> {
902 self.last
903 .next()
904 .or_else(|| self.inner.next_back().map(|pair| &mut pair.0))
905 }
906}
907
908impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
909 fn len(&self) -> usize {
910 self.inner.len() + self.last.len()
911 }
912}
913
914impl<'a, T, I> IterMutTrait<'a, T> for I
915where
916 T: 'a,
917 I: DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T> + 'a,
918{
919}
920
921/// A single syntax tree node of type `T` followed by its trailing punctuation
922/// of type `P` if any.
923///
924/// Refer to the [module documentation] for details about punctuated sequences.
925///
926/// [module documentation]: self
927pub enum Pair<T, P> {
928 Punctuated(T, P),
929 End(T),
930}
931
932impl<T, P> Pair<T, P> {
933 /// Extracts the syntax tree node from this punctuated pair, discarding the
934 /// following punctuation.
935 pub fn into_value(self) -> T {
936 match self {
937 Pair::Punctuated(t, _) | Pair::End(t) => t,
938 }
939 }
940
941 /// Borrows the syntax tree node from this punctuated pair.
942 pub fn value(&self) -> &T {
943 match self {
944 Pair::Punctuated(t, _) | Pair::End(t) => t,
945 }
946 }
947
948 /// Mutably borrows the syntax tree node from this punctuated pair.
949 pub fn value_mut(&mut self) -> &mut T {
950 match self {
951 Pair::Punctuated(t, _) | Pair::End(t) => t,
952 }
953 }
954
955 /// Borrows the punctuation from this punctuated pair, unless this pair is
956 /// the final one and there is no trailing punctuation.
957 pub fn punct(&self) -> Option<&P> {
958 match self {
959 Pair::Punctuated(_, p) => Some(p),
960 Pair::End(_) => None,
961 }
962 }
963
964 /// Mutably borrows the punctuation from this punctuated pair, unless the
965 /// pair is the final one and there is no trailing punctuation.
966 ///
967 /// # Example
968 ///
969 /// ```
970 /// # use proc_macro2::Span;
971 /// # use syn::punctuated::Punctuated;
972 /// # use syn::{parse_quote, Token, TypeParamBound};
973 /// #
974 /// # let mut punctuated = Punctuated::<TypeParamBound, Token![+]>::new();
975 /// # let span = Span::call_site();
976 /// #
977 /// punctuated.insert(0, parse_quote!('lifetime));
978 /// if let Some(punct) = punctuated.pairs_mut().next().unwrap().punct_mut() {
979 /// punct.span = span;
980 /// }
981 /// ```
982 pub fn punct_mut(&mut self) -> Option<&mut P> {
983 match self {
984 Pair::Punctuated(_, p) => Some(p),
985 Pair::End(_) => None,
986 }
987 }
988
989 /// Creates a punctuated pair out of a syntax tree node and an optional
990 /// following punctuation.
991 pub fn new(t: T, p: Option<P>) -> Self {
992 match p {
993 Some(p) => Pair::Punctuated(t, p),
994 None => Pair::End(t),
995 }
996 }
997
998 /// Produces this punctuated pair as a tuple of syntax tree node and
999 /// optional following punctuation.
1000 pub fn into_tuple(self) -> (T, Option<P>) {
1001 match self {
1002 Pair::Punctuated(t, p) => (t, Some(p)),
1003 Pair::End(t) => (t, None),
1004 }
1005 }
1006}
1007
1008#[cfg(feature = "clone-impls")]
1009#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
1010impl<T, P> Pair<&T, &P> {
1011 pub fn cloned(self) -> Pair<T, P>
1012 where
1013 T: Clone,
1014 P: Clone,
1015 {
1016 match self {
1017 Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
1018 Pair::End(t) => Pair::End(t.clone()),
1019 }
1020 }
1021}
1022
1023#[cfg(feature = "clone-impls")]
1024#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
1025impl<T, P> Clone for Pair<T, P>
1026where
1027 T: Clone,
1028 P: Clone,
1029{
1030 fn clone(&self) -> Self {
1031 match self {
1032 Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
1033 Pair::End(t) => Pair::End(t.clone()),
1034 }
1035 }
1036}
1037
1038#[cfg(feature = "clone-impls")]
1039#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
1040impl<T, P> Copy for Pair<T, P>
1041where
1042 T: Copy,
1043 P: Copy,
1044{
1045}
1046
1047impl<T, P> Index<usize> for Punctuated<T, P> {
1048 type Output = T;
1049
1050 fn index(&self, index: usize) -> &Self::Output {
1051 if index == self.len() - 1 {
1052 match &self.last {
1053 Some(t) => t,
1054 None => &self.inner[index].0,
1055 }
1056 } else {
1057 &self.inner[index].0
1058 }
1059 }
1060}
1061
1062impl<T, P> IndexMut<usize> for Punctuated<T, P> {
1063 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1064 if index == self.len() - 1 {
1065 match &mut self.last {
1066 Some(t) => t,
1067 None => &mut self.inner[index].0,
1068 }
1069 } else {
1070 &mut self.inner[index].0
1071 }
1072 }
1073}
1074
1075#[cfg(feature = "printing")]
1076mod printing {
1077 use super::*;
1078 use proc_macro2::TokenStream;
1079 use quote::{ToTokens, TokenStreamExt};
1080
1081 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1082 impl<T, P> ToTokens for Punctuated<T, P>
1083 where
1084 T: ToTokens,
1085 P: ToTokens,
1086 {
1087 fn to_tokens(&self, tokens: &mut TokenStream) {
1088 tokens.append_all(self.pairs());
1089 }
1090 }
1091
1092 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1093 impl<T, P> ToTokens for Pair<T, P>
1094 where
1095 T: ToTokens,
1096 P: ToTokens,
1097 {
1098 fn to_tokens(&self, tokens: &mut TokenStream) {
1099 match self {
1100 Pair::Punctuated(a, b) => {
1101 a.to_tokens(tokens);
1102 b.to_tokens(tokens);
1103 }
1104 Pair::End(a) => a.to_tokens(tokens),
1105 }
1106 }
1107 }
1108}
1109