Skip to main content

syn/
punctuated.rs

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