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