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;
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
44pub struct Punctuated<T, P> {
51 inner: Vec<(T, P)>,
52 last: Option<Box<T>>,
53}
54
55impl<T, P> Punctuated<T, P> {
56 pub const fn new() -> Self {
58 Punctuated {
59 inner: Vec::new(),
60 last: None,
61 }
62 }
63
64 pub fn is_empty(&self) -> bool {
67 self.inner.len() == 0 && self.last.is_none()
68 }
69
70 pub fn len(&self) -> usize {
75 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
76 }
77
78 pub fn first(&self) -> Option<&T> {
80 self.iter().next()
81 }
82
83 pub fn first_mut(&mut self) -> Option<&mut T> {
85 self.iter_mut().next()
86 }
87
88 pub fn last(&self) -> Option<&T> {
90 self.iter().next_back()
91 }
92
93 pub fn last_mut(&mut self) -> Option<&mut T> {
95 self.iter_mut().next_back()
96 }
97
98 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 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 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 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 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 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 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 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 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 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 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 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 pub fn trailing_punct(&self) -> bool {
242 self.last.is_none() && !self.is_empty()
243 }
244
245 pub fn empty_or_trailing(&self) -> bool {
250 self.last.is_none()
251 }
252
253 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 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 pub fn clear(&mut self) {
292 self.inner.clear();
293 self.last = None;
294 }
295
296 #[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 #[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 #[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 #[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
573pub 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
613impl<'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
623pub 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
663pub 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
716pub 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
760pub 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
792impl<'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
850impl<'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
874pub 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
963pub enum Pair<T, P> {
970 Punctuated(T, P),
971 End(T),
972}
973
974impl<T, P> Pair<T, P> {
975 pub fn into_value(self) -> T {
978 match self {
979 Pair::Punctuated(t, _) | Pair::End(t) => t,
980 }
981 }
982
983 pub fn value(&self) -> &T {
985 match self {
986 Pair::Punctuated(t, _) | Pair::End(t) => t,
987 }
988 }
989
990 pub fn value_mut(&mut self) -> &mut T {
992 match self {
993 Pair::Punctuated(t, _) | Pair::End(t) => t,
994 }
995 }
996
997 pub fn punct(&self) -> Option<&P> {
1000 match self {
1001 Pair::Punctuated(_, p) => Some(p),
1002 Pair::End(_) => None,
1003 }
1004 }
1005
1006 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 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 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 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}