1use 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;
30#[cfg(all(feature = "fold", any(feature = "full", feature = "derive")))]
31use std::collections::VecDeque;
32#[cfg(feature = "extra-traits")]
33use std::fmt::{self, Debug};
34#[cfg(feature = "extra-traits")]
35use std::hash::{Hash, Hasher};
36#[cfg(any(feature = "full", feature = "derive"))]
37use std::iter;
38use std::ops::{Index, IndexMut};
39use std::option;
40use std::slice;
41use std::vec;
42
43pub struct Punctuated<T, P> {
50 inner: Vec<(T, P)>,
51 last: Option<Box<T>>,
52}
53
54impl<T, P> Punctuated<T, P> {
55 pub const fn new() -> Self {
57 Punctuated {
58 inner: Vec::new(),
59 last: None,
60 }
61 }
62
63 pub fn is_empty(&self) -> bool {
66 self.inner.len() == 0 && self.last.is_none()
67 }
68
69 pub fn len(&self) -> usize {
74 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
75 }
76
77 pub fn first(&self) -> Option<&T> {
79 self.iter().next()
80 }
81
82 pub fn first_mut(&mut self) -> Option<&mut T> {
84 self.iter_mut().next()
85 }
86
87 pub fn last(&self) -> Option<&T> {
89 self.iter().next_back()
90 }
91
92 pub fn last_mut(&mut self) -> Option<&mut T> {
94 self.iter_mut().next_back()
95 }
96
97 pub fn get(&self, index: usize) -> Option<&T> {
99 if let Some((value, _punct)) = self.inner.get(index) {
100 Some(value)
101 } else if index == self.inner.len() {
102 self.last.as_deref()
103 } else {
104 None
105 }
106 }
107
108 pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
110 let inner_len = self.inner.len();
111 if let Some((value, _punct)) = self.inner.get_mut(index) {
112 Some(value)
113 } else if index == inner_len {
114 self.last.as_deref_mut()
115 } else {
116 None
117 }
118 }
119
120 pub fn iter(&self) -> Iter<T> {
122 Iter {
123 inner: Box::new(NoDrop::new(PrivateIter {
124 inner: self.inner.iter(),
125 last: self.last.as_ref().map(Box::as_ref).into_iter(),
126 })),
127 }
128 }
129
130 pub fn iter_mut(&mut self) -> IterMut<T> {
133 IterMut {
134 inner: Box::new(NoDrop::new(PrivateIterMut {
135 inner: self.inner.iter_mut(),
136 last: self.last.as_mut().map(Box::as_mut).into_iter(),
137 })),
138 }
139 }
140
141 pub fn pairs(&self) -> Pairs<T, P> {
144 Pairs {
145 inner: self.inner.iter(),
146 last: self.last.as_ref().map(Box::as_ref).into_iter(),
147 }
148 }
149
150 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
153 PairsMut {
154 inner: self.inner.iter_mut(),
155 last: self.last.as_mut().map(Box::as_mut).into_iter(),
156 }
157 }
158
159 pub fn into_pairs(self) -> IntoPairs<T, P> {
162 IntoPairs {
163 inner: self.inner.into_iter(),
164 last: self.last.map(|t| *t).into_iter(),
165 }
166 }
167
168 pub fn push_value(&mut self, value: T) {
181 if !self.empty_or_trailing() {
{
::core::panicking::panic_fmt(format_args!("Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation"));
}
};assert!(
182 self.empty_or_trailing(),
183 "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation",
184 );
185
186 self.last = Some(Box::new(value));
187 }
188
189 pub fn push_punct(&mut self, punctuation: P) {
197 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!(
198 self.last.is_some(),
199 "Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation",
200 );
201
202 let last = self.last.take().unwrap();
203 self.inner.push((*last, punctuation));
204 }
205
206 pub fn pop(&mut self) -> Option<Pair<T, P>> {
209 if self.last.is_some() {
210 self.last.take().map(|t| Pair::End(*t))
211 } else {
212 self.inner.pop().map(|(t, p)| Pair::Punctuated(t, p))
213 }
214 }
215
216 pub fn pop_punct(&mut self) -> Option<P> {
219 if self.last.is_some() {
220 None
221 } else {
222 let (t, p) = self.inner.pop()?;
223 self.last = Some(Box::new(t));
224 Some(p)
225 }
226 }
227
228 pub fn trailing_punct(&self) -> bool {
231 self.last.is_none() && !self.is_empty()
232 }
233
234 pub fn empty_or_trailing(&self) -> bool {
239 self.last.is_none()
240 }
241
242 pub fn push(&mut self, value: T)
248 where
249 P: Default,
250 {
251 if !self.empty_or_trailing() {
252 self.push_punct(Default::default());
253 }
254 self.push_value(value);
255 }
256
257 pub fn insert(&mut self, index: usize, value: T)
264 where
265 P: Default,
266 {
267 if !(index <= self.len()) {
{
::core::panicking::panic_fmt(format_args!("Punctuated::insert: index out of range"));
}
};assert!(
268 index <= self.len(),
269 "Punctuated::insert: index out of range",
270 );
271
272 if index == self.len() {
273 self.push(value);
274 } else {
275 self.inner.insert(index, (value, Default::default()));
276 }
277 }
278
279 pub fn clear(&mut self) {
281 self.inner.clear();
282 self.last = None;
283 }
284
285 #[cfg(feature = "parsing")]
291 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
292 pub fn parse_terminated(input: ParseStream) -> Result<Self>
293 where
294 T: Parse,
295 P: Parse,
296 {
297 Self::parse_terminated_with(input, T::parse)
298 }
299
300 #[cfg(feature = "parsing")]
309 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
310 pub fn parse_terminated_with<'a>(
311 input: ParseStream<'a>,
312 parser: fn(ParseStream<'a>) -> Result<T>,
313 ) -> Result<Self>
314 where
315 P: Parse,
316 {
317 let mut punctuated = Punctuated::new();
318
319 loop {
320 if input.is_empty() {
321 break;
322 }
323 let value = parser(input)?;
324 punctuated.push_value(value);
325 if input.is_empty() {
326 break;
327 }
328 let punct = input.parse()?;
329 punctuated.push_punct(punct);
330 }
331
332 Ok(punctuated)
333 }
334
335 #[cfg(feature = "parsing")]
343 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
344 pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
345 where
346 T: Parse,
347 P: Token + Parse,
348 {
349 Self::parse_separated_nonempty_with(input, T::parse)
350 }
351
352 #[cfg(feature = "parsing")]
361 #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
362 pub fn parse_separated_nonempty_with<'a>(
363 input: ParseStream<'a>,
364 parser: fn(ParseStream<'a>) -> Result<T>,
365 ) -> Result<Self>
366 where
367 P: Token + Parse,
368 {
369 let mut punctuated = Punctuated::new();
370
371 loop {
372 let value = parser(input)?;
373 punctuated.push_value(value);
374 if !P::peek(input.cursor()) {
375 break;
376 }
377 let punct = input.parse()?;
378 punctuated.push_punct(punct);
379 }
380
381 Ok(punctuated)
382 }
383}
384
385#[cfg(feature = "clone-impls")]
386#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
387impl<T, P> Clone for Punctuated<T, P>
388where
389 T: Clone,
390 P: Clone,
391{
392 fn clone(&self) -> Self {
393 Punctuated {
394 inner: self.inner.clone(),
395 last: self.last.clone(),
396 }
397 }
398
399 fn clone_from(&mut self, other: &Self) {
400 self.inner.clone_from(&other.inner);
401 self.last.clone_from(&other.last);
402 }
403}
404
405#[cfg(feature = "extra-traits")]
406#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
407impl<T, P> Eq for Punctuated<T, P>
408where
409 T: Eq,
410 P: Eq,
411{
412}
413
414#[cfg(feature = "extra-traits")]
415#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
416impl<T, P> PartialEq for Punctuated<T, P>
417where
418 T: PartialEq,
419 P: PartialEq,
420{
421 fn eq(&self, other: &Self) -> bool {
422 let Punctuated { inner, last } = self;
423 *inner == other.inner && *last == other.last
424 }
425}
426
427#[cfg(feature = "extra-traits")]
428#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
429impl<T, P> Hash for Punctuated<T, P>
430where
431 T: Hash,
432 P: Hash,
433{
434 fn hash<H: Hasher>(&self, state: &mut H) {
435 let Punctuated { inner, last } = self;
436 inner.hash(state);
437 last.hash(state);
438 }
439}
440
441#[cfg(feature = "extra-traits")]
442#[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
443impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
444 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
445 let mut list = f.debug_list();
446 for (t, p) in &self.inner {
447 list.entry(t);
448 list.entry(p);
449 }
450 if let Some(last) = &self.last {
451 list.entry(last);
452 }
453 list.finish()
454 }
455}
456
457impl<T, P> FromIterator<T> for Punctuated<T, P>
458where
459 P: Default,
460{
461 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
462 let mut ret = Punctuated::new();
463 ret.extend(i);
464 ret
465 }
466}
467
468impl<T, P> Extend<T> for Punctuated<T, P>
469where
470 P: Default,
471{
472 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
473 for value in i {
474 self.push(value);
475 }
476 }
477}
478
479impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
480 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
481 let mut ret = Punctuated::new();
482 do_extend(&mut ret, i.into_iter());
483 ret
484 }
485}
486
487impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P>
488where
489 P: Default,
490{
491 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
492 if !self.empty_or_trailing() {
493 self.push_punct(P::default());
494 }
495 do_extend(self, i.into_iter());
496 }
497}
498
499fn do_extend<T, P, I>(punctuated: &mut Punctuated<T, P>, i: I)
500where
501 I: Iterator<Item = Pair<T, P>>,
502{
503 let mut nomore = false;
504 for pair in i {
505 if nomore {
506 {
::core::panicking::panic_fmt(format_args!("punctuated extended with items after a Pair::End"));
};panic!("punctuated extended with items after a Pair::End");
507 }
508 match pair {
509 Pair::Punctuated(a, b) => punctuated.inner.push((a, b)),
510 Pair::End(a) => {
511 punctuated.last = Some(Box::new(a));
512 nomore = true;
513 }
514 }
515 }
516}
517
518impl<T, P> IntoIterator for Punctuated<T, P> {
519 type Item = T;
520 type IntoIter = IntoIter<T>;
521
522 fn into_iter(self) -> Self::IntoIter {
523 let mut elements = Vec::with_capacity(self.len());
524
525 for (t, _) in self.inner {
526 elements.push(t);
527 }
528 if let Some(t) = self.last {
529 elements.push(*t);
530 }
531
532 IntoIter {
533 inner: elements.into_iter(),
534 }
535 }
536}
537
538impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
539 type Item = &'a T;
540 type IntoIter = Iter<'a, T>;
541
542 fn into_iter(self) -> Self::IntoIter {
543 Punctuated::iter(self)
544 }
545}
546
547impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
548 type Item = &'a mut T;
549 type IntoIter = IterMut<'a, T>;
550
551 fn into_iter(self) -> Self::IntoIter {
552 Punctuated::iter_mut(self)
553 }
554}
555
556impl<T, P> Default for Punctuated<T, P> {
557 fn default() -> Self {
558 Punctuated::new()
559 }
560}
561
562pub struct Pairs<'a, T: 'a, P: 'a> {
568 inner: slice::Iter<'a, (T, P)>,
569 last: option::IntoIter<&'a T>,
570}
571
572impl<'a, T, P> Iterator for Pairs<'a, T, P> {
573 type Item = Pair<&'a T, &'a P>;
574
575 fn next(&mut self) -> Option<Self::Item> {
576 self.inner
577 .next()
578 .map(|(t, p)| Pair::Punctuated(t, p))
579 .or_else(|| self.last.next().map(Pair::End))
580 }
581
582 fn size_hint(&self) -> (usize, Option<usize>) {
583 (self.len(), Some(self.len()))
584 }
585}
586
587impl<'a, T, P> DoubleEndedIterator for Pairs<'a, T, P> {
588 fn next_back(&mut self) -> Option<Self::Item> {
589 self.last
590 .next()
591 .map(Pair::End)
592 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
593 }
594}
595
596impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
597 fn len(&self) -> usize {
598 self.inner.len() + self.last.len()
599 }
600}
601
602impl<'a, T, P> Clone for Pairs<'a, T, P> {
604 fn clone(&self) -> Self {
605 Pairs {
606 inner: self.inner.clone(),
607 last: self.last.clone(),
608 }
609 }
610}
611
612pub struct PairsMut<'a, T: 'a, P: 'a> {
618 inner: slice::IterMut<'a, (T, P)>,
619 last: option::IntoIter<&'a mut T>,
620}
621
622impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
623 type Item = Pair<&'a mut T, &'a mut P>;
624
625 fn next(&mut self) -> Option<Self::Item> {
626 self.inner
627 .next()
628 .map(|(t, p)| Pair::Punctuated(t, p))
629 .or_else(|| self.last.next().map(Pair::End))
630 }
631
632 fn size_hint(&self) -> (usize, Option<usize>) {
633 (self.len(), Some(self.len()))
634 }
635}
636
637impl<'a, T, P> DoubleEndedIterator for PairsMut<'a, T, P> {
638 fn next_back(&mut self) -> Option<Self::Item> {
639 self.last
640 .next()
641 .map(Pair::End)
642 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
643 }
644}
645
646impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
647 fn len(&self) -> usize {
648 self.inner.len() + self.last.len()
649 }
650}
651
652pub struct IntoPairs<T, P> {
658 inner: vec::IntoIter<(T, P)>,
659 last: option::IntoIter<T>,
660}
661
662impl<T, P> Iterator for IntoPairs<T, P> {
663 type Item = Pair<T, P>;
664
665 fn next(&mut self) -> Option<Self::Item> {
666 self.inner
667 .next()
668 .map(|(t, p)| Pair::Punctuated(t, p))
669 .or_else(|| self.last.next().map(Pair::End))
670 }
671
672 fn size_hint(&self) -> (usize, Option<usize>) {
673 (self.len(), Some(self.len()))
674 }
675}
676
677impl<T, P> DoubleEndedIterator for IntoPairs<T, P> {
678 fn next_back(&mut self) -> Option<Self::Item> {
679 self.last
680 .next()
681 .map(Pair::End)
682 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
683 }
684}
685
686impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
687 fn len(&self) -> usize {
688 self.inner.len() + self.last.len()
689 }
690}
691
692impl<T, P> Clone for IntoPairs<T, P>
693where
694 T: Clone,
695 P: Clone,
696{
697 fn clone(&self) -> Self {
698 IntoPairs {
699 inner: self.inner.clone(),
700 last: self.last.clone(),
701 }
702 }
703}
704
705pub struct IntoIter<T> {
711 inner: vec::IntoIter<T>,
712}
713
714impl<T> Iterator for IntoIter<T> {
715 type Item = T;
716
717 fn next(&mut self) -> Option<Self::Item> {
718 self.inner.next()
719 }
720
721 fn size_hint(&self) -> (usize, Option<usize>) {
722 (self.len(), Some(self.len()))
723 }
724}
725
726impl<T> DoubleEndedIterator for IntoIter<T> {
727 fn next_back(&mut self) -> Option<Self::Item> {
728 self.inner.next_back()
729 }
730}
731
732impl<T> ExactSizeIterator for IntoIter<T> {
733 fn len(&self) -> usize {
734 self.inner.len()
735 }
736}
737
738impl<T> Clone for IntoIter<T>
739where
740 T: Clone,
741{
742 fn clone(&self) -> Self {
743 IntoIter {
744 inner: self.inner.clone(),
745 }
746 }
747}
748
749pub struct Iter<'a, T: 'a> {
755 inner: Box<NoDrop<dyn IterTrait<'a, T> + 'a>>,
756}
757
758trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> + DoubleEndedIterator + ExactSizeIterator {
759 fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>>;
760}
761
762struct PrivateIter<'a, T: 'a, P: 'a> {
763 inner: slice::Iter<'a, (T, P)>,
764 last: option::IntoIter<&'a T>,
765}
766
767impl<'a, T, P> TrivialDrop for PrivateIter<'a, T, P>
768where
769 slice::Iter<'a, (T, P)>: TrivialDrop,
770 option::IntoIter<&'a T>: TrivialDrop,
771{
772}
773
774#[cfg(any(feature = "full", feature = "derive"))]
775pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
776 Iter {
777 inner: Box::new(NoDrop::new(iter::empty())),
778 }
779}
780
781impl<'a, T> Clone for Iter<'a, T> {
783 fn clone(&self) -> Self {
784 Iter {
785 inner: self.inner.clone_box(),
786 }
787 }
788}
789
790impl<'a, T> Iterator for Iter<'a, T> {
791 type Item = &'a T;
792
793 fn next(&mut self) -> Option<Self::Item> {
794 self.inner.next()
795 }
796
797 fn size_hint(&self) -> (usize, Option<usize>) {
798 (self.len(), Some(self.len()))
799 }
800}
801
802impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
803 fn next_back(&mut self) -> Option<Self::Item> {
804 self.inner.next_back()
805 }
806}
807
808impl<'a, T> ExactSizeIterator for Iter<'a, T> {
809 fn len(&self) -> usize {
810 self.inner.len()
811 }
812}
813
814impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
815 type Item = &'a T;
816
817 fn next(&mut self) -> Option<Self::Item> {
818 self.inner
819 .next()
820 .map(|pair| &pair.0)
821 .or_else(|| self.last.next())
822 }
823}
824
825impl<'a, T, P> DoubleEndedIterator for PrivateIter<'a, T, P> {
826 fn next_back(&mut self) -> Option<Self::Item> {
827 self.last
828 .next()
829 .or_else(|| self.inner.next_back().map(|pair| &pair.0))
830 }
831}
832
833impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
834 fn len(&self) -> usize {
835 self.inner.len() + self.last.len()
836 }
837}
838
839impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
841 fn clone(&self) -> Self {
842 PrivateIter {
843 inner: self.inner.clone(),
844 last: self.last.clone(),
845 }
846 }
847}
848
849impl<'a, T, I> IterTrait<'a, T> for I
850where
851 T: 'a,
852 I: DoubleEndedIterator<Item = &'a T>
853 + ExactSizeIterator<Item = &'a T>
854 + Clone
855 + TrivialDrop
856 + 'a,
857{
858 fn clone_box(&self) -> Box<NoDrop<dyn IterTrait<'a, T> + 'a>> {
859 Box::new(NoDrop::new(self.clone()))
860 }
861}
862
863pub struct IterMut<'a, T: 'a> {
869 inner: Box<NoDrop<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>>,
870}
871
872trait IterMutTrait<'a, T: 'a>:
873 DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T>
874{
875}
876
877struct PrivateIterMut<'a, T: 'a, P: 'a> {
878 inner: slice::IterMut<'a, (T, P)>,
879 last: option::IntoIter<&'a mut T>,
880}
881
882impl<'a, T, P> TrivialDrop for PrivateIterMut<'a, T, P>
883where
884 slice::IterMut<'a, (T, P)>: TrivialDrop,
885 option::IntoIter<&'a mut T>: TrivialDrop,
886{
887}
888
889#[cfg(any(feature = "full", feature = "derive"))]
890pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
891 IterMut {
892 inner: Box::new(NoDrop::new(iter::empty())),
893 }
894}
895
896impl<'a, T> Iterator for IterMut<'a, T> {
897 type Item = &'a mut T;
898
899 fn next(&mut self) -> Option<Self::Item> {
900 self.inner.next()
901 }
902
903 fn size_hint(&self) -> (usize, Option<usize>) {
904 (self.len(), Some(self.len()))
905 }
906}
907
908impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
909 fn next_back(&mut self) -> Option<Self::Item> {
910 self.inner.next_back()
911 }
912}
913
914impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
915 fn len(&self) -> usize {
916 self.inner.len()
917 }
918}
919
920impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
921 type Item = &'a mut T;
922
923 fn next(&mut self) -> Option<Self::Item> {
924 self.inner
925 .next()
926 .map(|pair| &mut pair.0)
927 .or_else(|| self.last.next())
928 }
929}
930
931impl<'a, T, P> DoubleEndedIterator for PrivateIterMut<'a, T, P> {
932 fn next_back(&mut self) -> Option<Self::Item> {
933 self.last
934 .next()
935 .or_else(|| self.inner.next_back().map(|pair| &mut pair.0))
936 }
937}
938
939impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
940 fn len(&self) -> usize {
941 self.inner.len() + self.last.len()
942 }
943}
944
945impl<'a, T, I> IterMutTrait<'a, T> for I
946where
947 T: 'a,
948 I: DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T> + 'a,
949{
950}
951
952pub enum Pair<T, P> {
959 Punctuated(T, P),
960 End(T),
961}
962
963impl<T, P> Pair<T, P> {
964 pub fn into_value(self) -> T {
967 match self {
968 Pair::Punctuated(t, _) | Pair::End(t) => t,
969 }
970 }
971
972 pub fn value(&self) -> &T {
974 match self {
975 Pair::Punctuated(t, _) | Pair::End(t) => t,
976 }
977 }
978
979 pub fn value_mut(&mut self) -> &mut T {
981 match self {
982 Pair::Punctuated(t, _) | Pair::End(t) => t,
983 }
984 }
985
986 pub fn punct(&self) -> Option<&P> {
989 match self {
990 Pair::Punctuated(_, p) => Some(p),
991 Pair::End(_) => None,
992 }
993 }
994
995 pub fn punct_mut(&mut self) -> Option<&mut P> {
1014 match self {
1015 Pair::Punctuated(_, p) => Some(p),
1016 Pair::End(_) => None,
1017 }
1018 }
1019
1020 pub fn new(t: T, p: Option<P>) -> Self {
1023 match p {
1024 Some(p) => Pair::Punctuated(t, p),
1025 None => Pair::End(t),
1026 }
1027 }
1028
1029 pub fn into_tuple(self) -> (T, Option<P>) {
1032 match self {
1033 Pair::Punctuated(t, p) => (t, Some(p)),
1034 Pair::End(t) => (t, None),
1035 }
1036 }
1037}
1038
1039#[cfg(feature = "clone-impls")]
1040#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
1041impl<T, P> Pair<&T, &P> {
1042 pub fn cloned(self) -> Pair<T, P>
1043 where
1044 T: Clone,
1045 P: Clone,
1046 {
1047 match self {
1048 Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
1049 Pair::End(t) => Pair::End(t.clone()),
1050 }
1051 }
1052}
1053
1054#[cfg(feature = "clone-impls")]
1055#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
1056impl<T, P> Clone for Pair<T, P>
1057where
1058 T: Clone,
1059 P: Clone,
1060{
1061 fn clone(&self) -> Self {
1062 match self {
1063 Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
1064 Pair::End(t) => Pair::End(t.clone()),
1065 }
1066 }
1067}
1068
1069#[cfg(feature = "clone-impls")]
1070#[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
1071impl<T, P> Copy for Pair<T, P>
1072where
1073 T: Copy,
1074 P: Copy,
1075{
1076}
1077
1078impl<T, P> Index<usize> for Punctuated<T, P> {
1079 type Output = T;
1080
1081 fn index(&self, index: usize) -> &Self::Output {
1082 if index.checked_add(1) == Some(self.len()) {
1083 match &self.last {
1084 Some(t) => t,
1085 None => &self.inner[index].0,
1086 }
1087 } else {
1088 &self.inner[index].0
1089 }
1090 }
1091}
1092
1093impl<T, P> IndexMut<usize> for Punctuated<T, P> {
1094 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1095 if index.checked_add(1) == Some(self.len()) {
1096 match &mut self.last {
1097 Some(t) => t,
1098 None => &mut self.inner[index].0,
1099 }
1100 } else {
1101 &mut self.inner[index].0
1102 }
1103 }
1104}
1105
1106#[cfg(all(feature = "fold", any(feature = "full", feature = "derive")))]
1107pub(crate) fn fold<T, P, V, F>(
1108 punctuated: Punctuated<T, P>,
1109 fold: &mut V,
1110 mut f: F,
1111) -> Punctuated<T, P>
1112where
1113 V: ?Sized,
1114 F: FnMut(&mut V, T) -> T,
1115{
1116 let Punctuated { inner, last } = punctuated;
1117
1118 let mut inner = VecDeque::from(inner);
1121 for _ in 0..inner.len() {
1122 if let Some((t, p)) = inner.pop_front() {
1123 inner.push_back((f(fold, t), p));
1124 }
1125 }
1126
1127 Punctuated {
1128 inner: Vec::from(inner),
1129 last: match last {
1130 Some(t) => Some(Box::new(f(fold, *t))),
1131 None => None,
1132 },
1133 }
1134}
1135
1136#[cfg(feature = "printing")]
1137mod printing {
1138 use crate::punctuated::{Pair, Punctuated};
1139 use proc_macro2::TokenStream;
1140 use quote::{ToTokens, TokenStreamExt as _};
1141
1142 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1143 impl<T, P> ToTokens for Punctuated<T, P>
1144 where
1145 T: ToTokens,
1146 P: ToTokens,
1147 {
1148 fn to_tokens(&self, tokens: &mut TokenStream) {
1149 tokens.append_all(self.pairs());
1150 }
1151 }
1152
1153 #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
1154 impl<T, P> ToTokens for Pair<T, P>
1155 where
1156 T: ToTokens,
1157 P: ToTokens,
1158 {
1159 fn to_tokens(&self, tokens: &mut TokenStream) {
1160 match self {
1161 Pair::Punctuated(a, b) => {
1162 a.to_tokens(tokens);
1163 b.to_tokens(tokens);
1164 }
1165 Pair::End(a) => a.to_tokens(tokens),
1166 }
1167 }
1168 }
1169}