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        if !self.empty_or_trailing() {
    {
        ::core::panicking::panic_fmt(format_args!("Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation"));
    }
};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        if !self.last.is_some() {
    {
        ::core::panicking::panic_fmt(format_args!("Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation"));
    }
};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        if !(index <= self.len()) {
    {
        ::core::panicking::panic_fmt(format_args!("Punctuated::insert: index out of range"));
    }
};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    /// Parses zero or more occurrences of `T` separated by punctuation of type
297    /// `P`, with optional trailing punctuation.
298    ///
299    /// Parsing continues until the end of this parse stream. The entire content
300    /// of this parse stream must consist of `T` and `P`.
301    #[cfg(feature = "parsing")]
302    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
303    pub fn parse_terminated(input: ParseStream) -> Result<Self>
304    where
305        T: Parse,
306        P: Parse,
307    {
308        Self::parse_terminated_with(input, T::parse)
309    }
310
311    /// Parses zero or more occurrences of `T` using the given parse function,
312    /// separated by punctuation of type `P`, with optional trailing
313    /// punctuation.
314    ///
315    /// Like [`parse_terminated`], the entire content of this stream is expected
316    /// to be parsed.
317    ///
318    /// [`parse_terminated`]: Punctuated::parse_terminated
319    #[cfg(feature = "parsing")]
320    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
321    pub fn parse_terminated_with<'a>(
322        input: ParseStream<'a>,
323        parser: fn(ParseStream<'a>) -> Result<T>,
324    ) -> Result<Self>
325    where
326        P: Parse,
327    {
328        let mut punctuated = Punctuated::new();
329
330        loop {
331            if input.is_empty() {
332                break;
333            }
334            let value = parser(input)?;
335            punctuated.push_value(value);
336            if input.is_empty() {
337                break;
338            }
339            let punct = input.parse()?;
340            punctuated.push_punct(punct);
341        }
342
343        Ok(punctuated)
344    }
345
346    /// Parses one or more occurrences of `T` separated by punctuation of type
347    /// `P`, not accepting trailing punctuation.
348    ///
349    /// Parsing continues as long as punctuation `P` is present at the head of
350    /// the stream. This method returns upon parsing a `T` and observing that it
351    /// is not followed by a `P`, even if there are remaining tokens in the
352    /// stream.
353    #[cfg(feature = "parsing")]
354    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
355    pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
356    where
357        T: Parse,
358        P: Token + Parse,
359    {
360        Self::parse_separated_nonempty_with(input, T::parse)
361    }
362
363    /// Parses one or more occurrences of `T` using the given parse function,
364    /// separated by punctuation of type `P`, not accepting trailing
365    /// punctuation.
366    ///
367    /// Like [`parse_separated_nonempty`], may complete early without parsing
368    /// the entire content of this stream.
369    ///
370    /// [`parse_separated_nonempty`]: Punctuated::parse_separated_nonempty
371    #[cfg(feature = "parsing")]
372    #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
373    pub fn parse_separated_nonempty_with<'a>(
374        input: ParseStream<'a>,
375        parser: fn(ParseStream<'a>) -> Result<T>,
376    ) -> Result<Self>
377    where
378        P: Token + Parse,
379    {
380        let mut punctuated = Punctuated::new();
381
382        loop {
383            let value = parser(input)?;
384            punctuated.push_value(value);
385            if !P::peek(input.cursor()) {
386                break;
387            }
388            let punct = input.parse()?;
389            punctuated.push_punct(punct);
390        }
391
392        Ok(punctuated)
393    }
394}
395
396#[cfg(feature = "clone-impls")]
397#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
398impl<T, P> Clone for Punctuated<T, P>
399where
400    T: Clone,
401    P: Clone,
402{
403    fn clone(&self) -> Self {
404        Punctuated {
405            inner: self.inner.clone(),
406            last: self.last.clone(),
407        }
408    }
409
410    fn clone_from(&mut self, other: &Self) {
411        self.inner.clone_from(&other.inner);
412        self.last.clone_from(&other.last);
413    }
414}
415
416#[cfg(feature = "extra-traits")]
417#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
418impl<T, P> Eq for Punctuated<T, P>
419where
420    T: Eq,
421    P: Eq,
422{
423}
424
425#[cfg(feature = "extra-traits")]
426#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
427impl<T, P> PartialEq for Punctuated<T, P>
428where
429    T: PartialEq,
430    P: PartialEq,
431{
432    fn eq(&self, other: &Self) -> bool {
433        let Punctuated { inner, last } = self;
434        *inner == other.inner && *last == other.last
435    }
436}
437
438#[cfg(feature = "extra-traits")]
439#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
440impl<T, P> Hash for Punctuated<T, P>
441where
442    T: Hash,
443    P: Hash,
444{
445    fn hash<H: Hasher>(&self, state: &mut H) {
446        let Punctuated { inner, last } = self;
447        inner.hash(state);
448        last.hash(state);
449    }
450}
451
452#[cfg(feature = "extra-traits")]
453#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
454impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
455    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
456        let mut list = f.debug_list();
457        for (t, p) in &self.inner {
458            list.entry(t);
459            list.entry(p);
460        }
461        if let Some(last) = &self.last {
462            list.entry(last);
463        }
464        list.finish()
465    }
466}
467
468impl<T, P> FromIterator<T> for Punctuated<T, P>
469where
470    P: Default,
471{
472    fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
473        let mut ret = Punctuated::new();
474        ret.extend(i);
475        ret
476    }
477}
478
479impl<T, P> Extend<T> for Punctuated<T, P>
480where
481    P: Default,
482{
483    fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
484        for value in i {
485            self.push(value);
486        }
487    }
488}
489
490impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
491    fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
492        let mut ret = Punctuated::new();
493        do_extend(&mut ret, i.into_iter());
494        ret
495    }
496}
497
498impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P>
499where
500    P: Default,
501{
502    fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
503        if !self.empty_or_trailing() {
504            self.push_punct(P::default());
505        }
506        do_extend(self, i.into_iter());
507    }
508}
509
510fn do_extend<T, P, I>(punctuated: &mut Punctuated<T, P>, i: I)
511where
512    I: Iterator<Item = Pair<T, P>>,
513{
514    let mut nomore = false;
515    for pair in i {
516        if nomore {
517            {
    ::core::panicking::panic_fmt(format_args!("punctuated extended with items after a Pair::End"));
};panic!("punctuated extended with items after a Pair::End");
518        }
519        match pair {
520            Pair::Punctuated(a, b) => punctuated.inner.push((a, b)),
521            Pair::End(a) => {
522                punctuated.last = Some(Box::new(a));
523                nomore = true;
524            }
525        }
526    }
527}
528
529impl<T, P> IntoIterator for Punctuated<T, P> {
530    type Item = T;
531    type IntoIter = IntoIter<T>;
532
533    fn into_iter(self) -> Self::IntoIter {
534        let mut elements = Vec::with_capacity(self.len());
535
536        for (t, _) in self.inner {
537            elements.push(t);
538        }
539        if let Some(t) = self.last {
540            elements.push(*t);
541        }
542
543        IntoIter {
544            inner: elements.into_iter(),
545        }
546    }
547}
548
549impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
550    type Item = &'a T;
551    type IntoIter = Iter<'a, T>;
552
553    fn into_iter(self) -> Self::IntoIter {
554        Punctuated::iter(self)
555    }
556}
557
558impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
559    type Item = &'a mut T;
560    type IntoIter = IterMut<'a, T>;
561
562    fn into_iter(self) -> Self::IntoIter {
563        Punctuated::iter_mut(self)
564    }
565}
566
567impl<T, P> Default for Punctuated<T, P> {
568    fn default() -> Self {
569        Punctuated::new()
570    }
571}
572
573/// An iterator over borrowed pairs of type `Pair<&T, &P>`.
574///
575/// Refer to the [module documentation] for details about punctuated sequences.
576///
577/// [module documentation]: self
578pub struct Pairs<'a, T: 'a, P: 'a> {
579    inner: slice::Iter<'a, (T, P)>,
580    last: option::IntoIter<&'a T>,
581}
582
583impl<'a, T, P> Iterator for Pairs<'a, T, P> {
584    type Item = Pair<&'a T, &'a P>;
585
586    fn next(&mut self) -> Option<Self::Item> {
587        self.inner
588            .next()
589            .map(|(t, p)| Pair::Punctuated(t, p))
590            .or_else(|| self.last.next().map(Pair::End))
591    }
592
593    fn size_hint(&self) -> (usize, Option<usize>) {
594        (self.len(), Some(self.len()))
595    }
596}
597
598impl<'a, T, P> DoubleEndedIterator for Pairs<'a, T, P> {
599    fn next_back(&mut self) -> Option<Self::Item> {
600        self.last
601            .next()
602            .map(Pair::End)
603            .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
604    }
605}
606
607impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
608    fn len(&self) -> usize {
609        self.inner.len() + self.last.len()
610    }
611}
612
613// No Clone bound on T or P.
614impl<'a, T, P> Clone for Pairs<'a, T, P> {
615    fn clone(&self) -> Self {
616        Pairs {
617            inner: self.inner.clone(),
618            last: self.last.clone(),
619        }
620    }
621}
622
623/// An iterator over mutably borrowed pairs of type `Pair<&mut T, &mut P>`.
624///
625/// Refer to the [module documentation] for details about punctuated sequences.
626///
627/// [module documentation]: self
628pub struct PairsMut<'a, T: 'a, P: 'a> {
629    inner: slice::IterMut<'a, (T, P)>,
630    last: option::IntoIter<&'a mut T>,
631}
632
633impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
634    type Item = Pair<&'a mut T, &'a mut P>;
635
636    fn next(&mut self) -> Option<Self::Item> {
637        self.inner
638            .next()
639            .map(|(t, p)| Pair::Punctuated(t, p))
640            .or_else(|| self.last.next().map(Pair::End))
641    }
642
643    fn size_hint(&self) -> (usize, Option<usize>) {
644        (self.len(), Some(self.len()))
645    }
646}
647
648impl<'a, T, P> DoubleEndedIterator for PairsMut<'a, T, P> {
649    fn next_back(&mut self) -> Option<Self::Item> {
650        self.last
651            .next()
652            .map(Pair::End)
653            .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
654    }
655}
656
657impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
658    fn len(&self) -> usize {
659        self.inner.len() + self.last.len()
660    }
661}
662
663/// An iterator over owned pairs of type `Pair<T, P>`.
664///
665/// Refer to the [module documentation] for details about punctuated sequences.
666///
667/// [module documentation]: self
668pub struct IntoPairs<T, P> {
669    inner: vec::IntoIter<(T, P)>,
670    last: option::IntoIter<T>,
671}
672
673impl<T, P> Iterator for IntoPairs<T, P> {
674    type Item = Pair<T, P>;
675
676    fn next(&mut self) -> Option<Self::Item> {
677        self.inner
678            .next()
679            .map(|(t, p)| Pair::Punctuated(t, p))
680            .or_else(|| self.last.next().map(Pair::End))
681    }
682
683    fn size_hint(&self) -> (usize, Option<usize>) {
684        (self.len(), Some(self.len()))
685    }
686}
687
688impl<T, P> DoubleEndedIterator for IntoPairs<T, P> {
689    fn next_back(&mut self) -> Option<Self::Item> {
690        self.last
691            .next()
692            .map(Pair::End)
693            .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
694    }
695}
696
697impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
698    fn len(&self) -> usize {
699        self.inner.len() + self.last.len()
700    }
701}
702
703impl<T, P> Clone for IntoPairs<T, P>
704where
705    T: Clone,
706    P: Clone,
707{
708    fn clone(&self) -> Self {
709        IntoPairs {
710            inner: self.inner.clone(),
711            last: self.last.clone(),
712        }
713    }
714}
715
716/// An iterator over owned values of type `T`.
717///
718/// Refer to the [module documentation] for details about punctuated sequences.
719///
720/// [module documentation]: self
721pub struct IntoIter<T> {
722    inner: vec::IntoIter<T>,
723}
724
725impl<T> Iterator for IntoIter<T> {
726    type Item = T;
727
728    fn next(&mut self) -> Option<Self::Item> {
729        self.inner.next()
730    }
731
732    fn size_hint(&self) -> (usize, Option<usize>) {
733        (self.len(), Some(self.len()))
734    }
735}
736
737impl<T> DoubleEndedIterator for IntoIter<T> {
738    fn next_back(&mut self) -> Option<Self::Item> {
739        self.inner.next_back()
740    }
741}
742
743impl<T> ExactSizeIterator for IntoIter<T> {
744    fn len(&self) -> usize {
745        self.inner.len()
746    }
747}
748
749impl<T> Clone for IntoIter<T>
750where
751    T: Clone,
752{
753    fn clone(&self) -> Self {
754        IntoIter {
755            inner: self.inner.clone(),
756        }
757    }
758}
759
760/// An iterator over borrowed values of type `&T`.
761///
762/// Refer to the [module documentation] for details about punctuated sequences.
763///
764/// [module documentation]: self
765pub struct Iter<'a, T: 'a> {
766    inner: Box<NoDrop<dyn IterTrait<'a, T> + 'a>>,
767}
768
769trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> + DoubleEndedIterator + ExactSizeIterator {
770    fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>>;
771}
772
773struct PrivateIter<'a, T: 'a, P: 'a> {
774    inner: slice::Iter<'a, (T, P)>,
775    last: option::IntoIter<&'a T>,
776}
777
778impl<'a, T, P> TrivialDrop for PrivateIter<'a, T, P>
779where
780    slice::Iter<'a, (T, P)>: TrivialDrop,
781    option::IntoIter<&'a T>: TrivialDrop,
782{
783}
784
785#[cfg(any(feature = "full", feature = "derive"))]
786pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
787    Iter {
788        inner: Box::new(NoDrop::new(iter::empty())),
789    }
790}
791
792// No Clone bound on T.
793impl<'a, T> Clone for Iter<'a, T> {
794    fn clone(&self) -> Self {
795        Iter {
796            inner: self.inner.clone_box(),
797        }
798    }
799}
800
801impl<'a, T> Iterator for Iter<'a, T> {
802    type Item = &'a T;
803
804    fn next(&mut self) -> Option<Self::Item> {
805        self.inner.next()
806    }
807
808    fn size_hint(&self) -> (usize, Option<usize>) {
809        (self.len(), Some(self.len()))
810    }
811}
812
813impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
814    fn next_back(&mut self) -> Option<Self::Item> {
815        self.inner.next_back()
816    }
817}
818
819impl<'a, T> ExactSizeIterator for Iter<'a, T> {
820    fn len(&self) -> usize {
821        self.inner.len()
822    }
823}
824
825impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
826    type Item = &'a T;
827
828    fn next(&mut self) -> Option<Self::Item> {
829        self.inner
830            .next()
831            .map(|pair| &pair.0)
832            .or_else(|| self.last.next())
833    }
834}
835
836impl<'a, T, P> DoubleEndedIterator for PrivateIter<'a, T, P> {
837    fn next_back(&mut self) -> Option<Self::Item> {
838        self.last
839            .next()
840            .or_else(|| self.inner.next_back().map(|pair| &pair.0))
841    }
842}
843
844impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
845    fn len(&self) -> usize {
846        self.inner.len() + self.last.len()
847    }
848}
849
850// No Clone bound on T or P.
851impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
852    fn clone(&self) -> Self {
853        PrivateIter {
854            inner: self.inner.clone(),
855            last: self.last.clone(),
856        }
857    }
858}
859
860impl<'a, T, I> IterTrait<'a, T> for I
861where
862    T: 'a,
863    I: DoubleEndedIterator<Item = &'a T>
864        + ExactSizeIterator<Item = &'a T>
865        + Clone
866        + TrivialDrop
867        + 'a,
868{
869    fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>> {
870        Box::new(NoDrop::new(self.clone()))
871    }
872}
873
874/// An iterator over mutably borrowed values of type `&mut T`.
875///
876/// Refer to the [module documentation] for details about punctuated sequences.
877///
878/// [module documentation]: self
879pub struct IterMut<'a, T: 'a> {
880    inner: Box<NoDrop<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>>,
881}
882
883trait IterMutTrait<'a, T: 'a>:
884    DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T>
885{
886}
887
888struct PrivateIterMut<'a, T: 'a, P: 'a> {
889    inner: slice::IterMut<'a, (T, P)>,
890    last: option::IntoIter<&'a mut T>,
891}
892
893impl<'a, T, P> TrivialDrop for PrivateIterMut<'a, T, P>
894where
895    slice::IterMut<'a, (T, P)>: TrivialDrop,
896    option::IntoIter<&'a mut T>: TrivialDrop,
897{
898}
899
900#[cfg(any(feature = "full", feature = "derive"))]
901pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
902    IterMut {
903        inner: Box::new(NoDrop::new(iter::empty())),
904    }
905}
906
907impl<'a, T> Iterator for IterMut<'a, T> {
908    type Item = &'a mut T;
909
910    fn next(&mut self) -> Option<Self::Item> {
911        self.inner.next()
912    }
913
914    fn size_hint(&self) -> (usize, Option<usize>) {
915        (self.len(), Some(self.len()))
916    }
917}
918
919impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
920    fn next_back(&mut self) -> Option<Self::Item> {
921        self.inner.next_back()
922    }
923}
924
925impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
926    fn len(&self) -> usize {
927        self.inner.len()
928    }
929}
930
931impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
932    type Item = &'a mut T;
933
934    fn next(&mut self) -> Option<Self::Item> {
935        self.inner
936            .next()
937            .map(|pair| &mut pair.0)
938            .or_else(|| self.last.next())
939    }
940}
941
942impl<'a, T, P> DoubleEndedIterator for PrivateIterMut<'a, T, P> {
943    fn next_back(&mut self) -> Option<Self::Item> {
944        self.last
945            .next()
946            .or_else(|| self.inner.next_back().map(|pair| &mut pair.0))
947    }
948}
949
950impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
951    fn len(&self) -> usize {
952        self.inner.len() + self.last.len()
953    }
954}
955
956impl<'a, T, I> IterMutTrait<'a, T> for I
957where
958    T: 'a,
959    I: DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T> + 'a,
960{
961}
962
963/// A single syntax tree node of type `T` followed by its trailing punctuation
964/// of type `P` if any.
965///
966/// Refer to the [module documentation] for details about punctuated sequences.
967///
968/// [module documentation]: self
969pub enum Pair<T, P> {
970    Punctuated(T, P),
971    End(T),
972}
973
974impl<T, P> Pair<T, P> {
975    /// Extracts the syntax tree node from this punctuated pair, discarding the
976    /// following punctuation.
977    pub fn into_value(self) -> T {
978        match self {
979            Pair::Punctuated(t, _) | Pair::End(t) => t,
980        }
981    }
982
983    /// Borrows the syntax tree node from this punctuated pair.
984    pub fn value(&self) -> &T {
985        match self {
986            Pair::Punctuated(t, _) | Pair::End(t) => t,
987        }
988    }
989
990    /// Mutably borrows the syntax tree node from this punctuated pair.
991    pub fn value_mut(&mut self) -> &mut T {
992        match self {
993            Pair::Punctuated(t, _) | Pair::End(t) => t,
994        }
995    }
996
997    /// Borrows the punctuation from this punctuated pair, unless this pair is
998    /// the final one and there is no trailing punctuation.
999    pub fn punct(&self) -> Option<&P> {
1000        match self {
1001            Pair::Punctuated(_, p) => Some(p),
1002            Pair::End(_) => None,
1003        }
1004    }
1005
1006    /// Mutably borrows the punctuation from this punctuated pair, unless the
1007    /// pair is the final one and there is no trailing punctuation.
1008    ///
1009    /// # Example
1010    ///
1011    /// ```
1012    /// # use proc_macro2::Span;
1013    /// # use syn::punctuated::Punctuated;
1014    /// # use syn::{parse_quote, Token, TypeParamBound};
1015    /// #
1016    /// # let mut punctuated = Punctuated::<TypeParamBound, Token![+]>::new();
1017    /// # let span = Span::call_site();
1018    /// #
1019    /// punctuated.insert(0, parse_quote!('lifetime));
1020    /// if let Some(punct) = punctuated.pairs_mut().next().unwrap().punct_mut() {
1021    ///     punct.span = span;
1022    /// }
1023    /// ```
1024    pub fn punct_mut(&mut self) -> Option<&mut P> {
1025        match self {
1026            Pair::Punctuated(_, p) => Some(p),
1027            Pair::End(_) => None,
1028        }
1029    }
1030
1031    /// Creates a punctuated pair out of a syntax tree node and an optional
1032    /// following punctuation.
1033    pub fn new(t: T, p: Option<P>) -> Self {
1034        match p {
1035            Some(p) => Pair::Punctuated(t, p),
1036            None => Pair::End(t),
1037        }
1038    }
1039
1040    /// Produces this punctuated pair as a tuple of syntax tree node and
1041    /// optional following punctuation.
1042    pub fn into_tuple(self) -> (T, Option<P>) {
1043        match self {
1044            Pair::Punctuated(t, p) => (t, Some(p)),
1045            Pair::End(t) => (t, None),
1046        }
1047    }
1048}
1049
1050#[cfg(feature = "clone-impls")]
1051#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
1052impl<T, P> Pair<&T, &P> {
1053    pub fn cloned(self) -> Pair<T, P>
1054    where
1055        T: Clone,
1056        P: Clone,
1057    {
1058        match self {
1059            Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
1060            Pair::End(t) => Pair::End(t.clone()),
1061        }
1062    }
1063}
1064
1065#[cfg(feature = "clone-impls")]
1066#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
1067impl<T, P> Clone for Pair<T, P>
1068where
1069    T: Clone,
1070    P: Clone,
1071{
1072    fn clone(&self) -> Self {
1073        match self {
1074            Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
1075            Pair::End(t) => Pair::End(t.clone()),
1076        }
1077    }
1078}
1079
1080#[cfg(feature = "clone-impls")]
1081#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
1082impl<T, P> Copy for Pair<T, P>
1083where
1084    T: Copy,
1085    P: Copy,
1086{
1087}
1088
1089impl<T, P> Index<usize> for Punctuated<T, P> {
1090    type Output = T;
1091
1092    fn index(&self, index: usize) -> &Self::Output {
1093        if index.checked_add(1) == Some(self.len()) {
1094            match &self.last {
1095                Some(t) => t,
1096                None => &self.inner[index].0,
1097            }
1098        } else {
1099            &self.inner[index].0
1100        }
1101    }
1102}
1103
1104impl<T, P> IndexMut<usize> for Punctuated<T, P> {
1105    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1106        if index.checked_add(1) == Some(self.len()) {
1107            match &mut self.last {
1108                Some(t) => t,
1109                None => &mut self.inner[index].0,
1110            }
1111        } else {
1112            &mut self.inner[index].0
1113        }
1114    }
1115}
1116
1117#[cfg(all(feature = "fold", any(feature = "full", feature = "derive")))]
1118pub(crate) fn fold<T, P, V, F>(
1119    punctuated: Punctuated<T, P>,
1120    fold: &mut V,
1121    mut f: F,
1122) -> Punctuated<T, P>
1123where
1124    V: ?Sized,
1125    F: FnMut(&mut V, T) -> T,
1126{
1127    let Punctuated { inner, last } = punctuated;
1128
1129    // Convert into VecDeque to prevent needing to allocate a new Vec<(T, P)>
1130    // for the folded elements.
1131    let mut inner = VecDeque::from(inner);
1132    for _ in 0..inner.len() {
1133        if let Some((t, p)) = inner.pop_front() {
1134            inner.push_back((f(fold, t), p));
1135        }
1136    }
1137
1138    Punctuated {
1139        inner: Vec::from(inner),
1140        last: match last {
1141            Some(t) => Some(Box::new(f(fold, *t))),
1142            None => None,
1143        },
1144    }
1145}
1146
1147#[cfg(feature = "printing")]
1148mod printing {
1149    use crate::punctuated::{Pair, Punctuated};
1150    use proc_macro2::TokenStream;
1151    use quote::{ToTokens, TokenStreamExt as _};
1152
1153    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1154    impl<T, P> ToTokens for Punctuated<T, P>
1155    where
1156        T: ToTokens,
1157        P: ToTokens,
1158    {
1159        fn to_tokens(&self, tokens: &mut TokenStream) {
1160            tokens.append_all(self.pairs());
1161        }
1162    }
1163
1164    #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1165    impl<T, P> ToTokens for Pair<T, P>
1166    where
1167        T: ToTokens,
1168        P: ToTokens,
1169    {
1170        fn to_tokens(&self, tokens: &mut TokenStream) {
1171            match self {
1172                Pair::Punctuated(a, b) => {
1173                    a.to_tokens(tokens);
1174                    b.to_tokens(tokens);
1175                }
1176                Pair::End(a) => a.to_tokens(tokens),
1177            }
1178        }
1179    }
1180}