1#[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
35#[cfg(feature = "parsing")]
36use crate::parse::{Parse, ParseStream, Result};
37#[cfg(feature = "parsing")]
38use crate::token::Token;
39
40pub struct Punctuated<T, P> {
47 inner: Vec<(T, P)>,
48 last: Option<Box<T>>,
49}
50
51impl<T, P> Punctuated<T, P> {
52 #[cfg(not(syn_no_const_vec_new))]
54 pub const fn new() -> Self {
55 Punctuated {
56 inner: Vec::new(),
57 last: None,
58 }
59 }
60
61 #[cfg(syn_no_const_vec_new)]
63 pub fn new() -> Self {
64 Punctuated {
65 inner: Vec::new(),
66 last: None,
67 }
68 }
69
70 pub fn is_empty(&self) -> bool {
73 self.inner.len() == 0 && self.last.is_none()
74 }
75
76 pub fn len(&self) -> usize {
81 self.inner.len() + if self.last.is_some() { 1 } else { 0 }
82 }
83
84 pub fn first(&self) -> Option<&T> {
86 self.iter().next()
87 }
88
89 pub fn first_mut(&mut self) -> Option<&mut T> {
91 self.iter_mut().next()
92 }
93
94 pub fn last(&self) -> Option<&T> {
96 self.iter().next_back()
97 }
98
99 pub fn last_mut(&mut self) -> Option<&mut T> {
101 self.iter_mut().next_back()
102 }
103
104 pub fn iter(&self) -> Iter<T> {
106 Iter {
107 inner: Box::new(PrivateIter {
108 inner: self.inner.iter(),
109 last: self.last.as_ref().map(Box::as_ref).into_iter(),
110 }),
111 }
112 }
113
114 pub fn iter_mut(&mut self) -> IterMut<T> {
117 IterMut {
118 inner: Box::new(PrivateIterMut {
119 inner: self.inner.iter_mut(),
120 last: self.last.as_mut().map(Box::as_mut).into_iter(),
121 }),
122 }
123 }
124
125 pub fn pairs(&self) -> Pairs<T, P> {
128 Pairs {
129 inner: self.inner.iter(),
130 last: self.last.as_ref().map(Box::as_ref).into_iter(),
131 }
132 }
133
134 pub fn pairs_mut(&mut self) -> PairsMut<T, P> {
137 PairsMut {
138 inner: self.inner.iter_mut(),
139 last: self.last.as_mut().map(Box::as_mut).into_iter(),
140 }
141 }
142
143 pub fn into_pairs(self) -> IntoPairs<T, P> {
146 IntoPairs {
147 inner: self.inner.into_iter(),
148 last: self.last.map(|t| *t).into_iter(),
149 }
150 }
151
152 pub fn push_value(&mut self, value: T) {
165 assert!(
166 self.empty_or_trailing(),
167 "Punctuated::push_value: cannot push value if Punctuated is missing trailing punctuation",
168 );
169
170 self.last = Some(Box::new(value));
171 }
172
173 pub fn push_punct(&mut self, punctuation: P) {
181 assert!(
182 self.last.is_some(),
183 "Punctuated::push_punct: cannot push punctuation if Punctuated is empty or already has trailing punctuation",
184 );
185
186 let last = self.last.take().unwrap();
187 self.inner.push((*last, punctuation));
188 }
189
190 pub fn pop(&mut self) -> Option<Pair<T, P>> {
193 if self.last.is_some() {
194 self.last.take().map(|t| Pair::End(*t))
195 } else {
196 self.inner.pop().map(|(t, p)| Pair::Punctuated(t, p))
197 }
198 }
199
200 pub fn trailing_punct(&self) -> bool {
203 self.last.is_none() && !self.is_empty()
204 }
205
206 pub fn empty_or_trailing(&self) -> bool {
211 self.last.is_none()
212 }
213
214 pub fn push(&mut self, value: T)
220 where
221 P: Default,
222 {
223 if !self.empty_or_trailing() {
224 self.push_punct(Default::default());
225 }
226 self.push_value(value);
227 }
228
229 pub fn insert(&mut self, index: usize, value: T)
236 where
237 P: Default,
238 {
239 assert!(
240 index <= self.len(),
241 "Punctuated::insert: index out of range",
242 );
243
244 if index == self.len() {
245 self.push(value);
246 } else {
247 self.inner.insert(index, (value, Default::default()));
248 }
249 }
250
251 pub fn clear(&mut self) {
253 self.inner.clear();
254 self.last = None;
255 }
256
257 #[cfg(feature = "parsing")]
266 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
267 pub fn parse_terminated(input: ParseStream) -> Result<Self>
268 where
269 T: Parse,
270 P: Parse,
271 {
272 Self::parse_terminated_with(input, T::parse)
273 }
274
275 #[cfg(feature = "parsing")]
287 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
288 pub fn parse_terminated_with(
289 input: ParseStream,
290 parser: fn(ParseStream) -> Result<T>,
291 ) -> Result<Self>
292 where
293 P: Parse,
294 {
295 let mut punctuated = Punctuated::new();
296
297 loop {
298 if input.is_empty() {
299 break;
300 }
301 let value = parser(input)?;
302 punctuated.push_value(value);
303 if input.is_empty() {
304 break;
305 }
306 let punct = input.parse()?;
307 punctuated.push_punct(punct);
308 }
309
310 Ok(punctuated)
311 }
312
313 #[cfg(feature = "parsing")]
324 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
325 pub fn parse_separated_nonempty(input: ParseStream) -> Result<Self>
326 where
327 T: Parse,
328 P: Token + Parse,
329 {
330 Self::parse_separated_nonempty_with(input, T::parse)
331 }
332
333 #[cfg(feature = "parsing")]
345 #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))]
346 pub fn parse_separated_nonempty_with(
347 input: ParseStream,
348 parser: fn(ParseStream) -> Result<T>,
349 ) -> Result<Self>
350 where
351 P: Token + Parse,
352 {
353 let mut punctuated = Punctuated::new();
354
355 loop {
356 let value = parser(input)?;
357 punctuated.push_value(value);
358 if !P::peek(input.cursor()) {
359 break;
360 }
361 let punct = input.parse()?;
362 punctuated.push_punct(punct);
363 }
364
365 Ok(punctuated)
366 }
367}
368
369#[cfg(feature = "clone-impls")]
370#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
371impl<T, P> Clone for Punctuated<T, P>
372where
373 T: Clone,
374 P: Clone,
375{
376 fn clone(&self) -> Self {
377 Punctuated {
378 inner: self.inner.clone(),
379 last: self.last.clone(),
380 }
381 }
382}
383
384#[cfg(feature = "extra-traits")]
385#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
386impl<T, P> Eq for Punctuated<T, P>
387where
388 T: Eq,
389 P: Eq,
390{
391}
392
393#[cfg(feature = "extra-traits")]
394#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
395impl<T, P> PartialEq for Punctuated<T, P>
396where
397 T: PartialEq,
398 P: PartialEq,
399{
400 fn eq(&self, other: &Self) -> bool {
401 let Punctuated { inner, last } = self;
402 *inner == other.inner && *last == other.last
403 }
404}
405
406#[cfg(feature = "extra-traits")]
407#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
408impl<T, P> Hash for Punctuated<T, P>
409where
410 T: Hash,
411 P: Hash,
412{
413 fn hash<H: Hasher>(&self, state: &mut H) {
414 let Punctuated { inner, last } = self;
415 inner.hash(state);
416 last.hash(state);
417 }
418}
419
420#[cfg(feature = "extra-traits")]
421#[cfg_attr(doc_cfg, doc(cfg(feature = "extra-traits")))]
422impl<T: Debug, P: Debug> Debug for Punctuated<T, P> {
423 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
424 let mut list = f.debug_list();
425 for (t, p) in &self.inner {
426 list.entry(t);
427 list.entry(p);
428 }
429 if let Some(last) = &self.last {
430 list.entry(last);
431 }
432 list.finish()
433 }
434}
435
436impl<T, P> FromIterator<T> for Punctuated<T, P>
437where
438 P: Default,
439{
440 fn from_iter<I: IntoIterator<Item = T>>(i: I) -> Self {
441 let mut ret = Punctuated::new();
442 ret.extend(i);
443 ret
444 }
445}
446
447impl<T, P> Extend<T> for Punctuated<T, P>
448where
449 P: Default,
450{
451 fn extend<I: IntoIterator<Item = T>>(&mut self, i: I) {
452 for value in i {
453 self.push(value);
454 }
455 }
456}
457
458impl<T, P> FromIterator<Pair<T, P>> for Punctuated<T, P> {
459 fn from_iter<I: IntoIterator<Item = Pair<T, P>>>(i: I) -> Self {
460 let mut ret = Punctuated::new();
461 ret.extend(i);
462 ret
463 }
464}
465
466impl<T, P> Extend<Pair<T, P>> for Punctuated<T, P> {
467 fn extend<I: IntoIterator<Item = Pair<T, P>>>(&mut self, i: I) {
468 assert!(
469 self.empty_or_trailing(),
470 "Punctuated::extend: Punctuated is not empty or does not have a trailing punctuation",
471 );
472
473 let mut nomore = false;
474 for pair in i {
475 if nomore {
476 panic!("Punctuated extended with items after a Pair::End");
477 }
478 match pair {
479 Pair::Punctuated(a, b) => self.inner.push((a, b)),
480 Pair::End(a) => {
481 self.last = Some(Box::new(a));
482 nomore = true;
483 }
484 }
485 }
486 }
487}
488
489impl<T, P> IntoIterator for Punctuated<T, P> {
490 type Item = T;
491 type IntoIter = IntoIter<T>;
492
493 fn into_iter(self) -> Self::IntoIter {
494 let mut elements = Vec::with_capacity(self.len());
495 elements.extend(self.inner.into_iter().map(|pair| pair.0));
496 elements.extend(self.last.map(|t| *t));
497
498 IntoIter {
499 inner: elements.into_iter(),
500 }
501 }
502}
503
504impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
505 type Item = &'a T;
506 type IntoIter = Iter<'a, T>;
507
508 fn into_iter(self) -> Self::IntoIter {
509 Punctuated::iter(self)
510 }
511}
512
513impl<'a, T, P> IntoIterator for &'a mut Punctuated<T, P> {
514 type Item = &'a mut T;
515 type IntoIter = IterMut<'a, T>;
516
517 fn into_iter(self) -> Self::IntoIter {
518 Punctuated::iter_mut(self)
519 }
520}
521
522impl<T, P> Default for Punctuated<T, P> {
523 fn default() -> Self {
524 Punctuated::new()
525 }
526}
527
528pub struct Pairs<'a, T: 'a, P: 'a> {
534 inner: slice::Iter<'a, (T, P)>,
535 last: option::IntoIter<&'a T>,
536}
537
538impl<'a, T, P> Iterator for Pairs<'a, T, P> {
539 type Item = Pair<&'a T, &'a P>;
540
541 fn next(&mut self) -> Option<Self::Item> {
542 self.inner
543 .next()
544 .map(|(t, p)| Pair::Punctuated(t, p))
545 .or_else(|| self.last.next().map(Pair::End))
546 }
547
548 fn size_hint(&self) -> (usize, Option<usize>) {
549 (self.len(), Some(self.len()))
550 }
551}
552
553impl<'a, T, P> DoubleEndedIterator for Pairs<'a, T, P> {
554 fn next_back(&mut self) -> Option<Self::Item> {
555 self.last
556 .next()
557 .map(Pair::End)
558 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
559 }
560}
561
562impl<'a, T, P> ExactSizeIterator for Pairs<'a, T, P> {
563 fn len(&self) -> usize {
564 self.inner.len() + self.last.len()
565 }
566}
567
568impl<'a, T, P> Clone for Pairs<'a, T, P> {
570 fn clone(&self) -> Self {
571 Pairs {
572 inner: self.inner.clone(),
573 last: self.last.clone(),
574 }
575 }
576}
577
578pub struct PairsMut<'a, T: 'a, P: 'a> {
584 inner: slice::IterMut<'a, (T, P)>,
585 last: option::IntoIter<&'a mut T>,
586}
587
588impl<'a, T, P> Iterator for PairsMut<'a, T, P> {
589 type Item = Pair<&'a mut T, &'a mut P>;
590
591 fn next(&mut self) -> Option<Self::Item> {
592 self.inner
593 .next()
594 .map(|(t, p)| Pair::Punctuated(t, p))
595 .or_else(|| self.last.next().map(Pair::End))
596 }
597
598 fn size_hint(&self) -> (usize, Option<usize>) {
599 (self.len(), Some(self.len()))
600 }
601}
602
603impl<'a, T, P> DoubleEndedIterator for PairsMut<'a, T, P> {
604 fn next_back(&mut self) -> Option<Self::Item> {
605 self.last
606 .next()
607 .map(Pair::End)
608 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
609 }
610}
611
612impl<'a, T, P> ExactSizeIterator for PairsMut<'a, T, P> {
613 fn len(&self) -> usize {
614 self.inner.len() + self.last.len()
615 }
616}
617
618pub struct IntoPairs<T, P> {
624 inner: vec::IntoIter<(T, P)>,
625 last: option::IntoIter<T>,
626}
627
628impl<T, P> Iterator for IntoPairs<T, P> {
629 type Item = Pair<T, P>;
630
631 fn next(&mut self) -> Option<Self::Item> {
632 self.inner
633 .next()
634 .map(|(t, p)| Pair::Punctuated(t, p))
635 .or_else(|| self.last.next().map(Pair::End))
636 }
637
638 fn size_hint(&self) -> (usize, Option<usize>) {
639 (self.len(), Some(self.len()))
640 }
641}
642
643impl<T, P> DoubleEndedIterator for IntoPairs<T, P> {
644 fn next_back(&mut self) -> Option<Self::Item> {
645 self.last
646 .next()
647 .map(Pair::End)
648 .or_else(|| self.inner.next_back().map(|(t, p)| Pair::Punctuated(t, p)))
649 }
650}
651
652impl<T, P> ExactSizeIterator for IntoPairs<T, P> {
653 fn len(&self) -> usize {
654 self.inner.len() + self.last.len()
655 }
656}
657
658impl<T, P> Clone for IntoPairs<T, P>
659where
660 T: Clone,
661 P: Clone,
662{
663 fn clone(&self) -> Self {
664 IntoPairs {
665 inner: self.inner.clone(),
666 last: self.last.clone(),
667 }
668 }
669}
670
671pub struct IntoIter<T> {
677 inner: vec::IntoIter<T>,
678}
679
680impl<T> Iterator for IntoIter<T> {
681 type Item = T;
682
683 fn next(&mut self) -> Option<Self::Item> {
684 self.inner.next()
685 }
686
687 fn size_hint(&self) -> (usize, Option<usize>) {
688 (self.len(), Some(self.len()))
689 }
690}
691
692impl<T> DoubleEndedIterator for IntoIter<T> {
693 fn next_back(&mut self) -> Option<Self::Item> {
694 self.inner.next_back()
695 }
696}
697
698impl<T> ExactSizeIterator for IntoIter<T> {
699 fn len(&self) -> usize {
700 self.inner.len()
701 }
702}
703
704impl<T> Clone for IntoIter<T>
705where
706 T: Clone,
707{
708 fn clone(&self) -> Self {
709 IntoIter {
710 inner: self.inner.clone(),
711 }
712 }
713}
714
715pub struct Iter<'a, T: 'a> {
721 inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
725}
726
727trait IterTrait<'a, T: 'a>:
728 DoubleEndedIterator<Item = &'a T> + ExactSizeIterator<Item = &'a T>
729{
730 fn clone_box(&self) -> Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>;
731}
732
733struct PrivateIter<'a, T: 'a, P: 'a> {
734 inner: slice::Iter<'a, (T, P)>,
735 last: option::IntoIter<&'a T>,
736}
737
738#[cfg(any(feature = "full", feature = "derive"))]
739pub(crate) fn empty_punctuated_iter<'a, T>() -> Iter<'a, T> {
740 Iter {
741 inner: Box::new(iter::empty()),
742 }
743}
744
745impl<'a, T> Clone for Iter<'a, T> {
747 fn clone(&self) -> Self {
748 Iter {
749 inner: self.inner.clone_box(),
750 }
751 }
752}
753
754impl<'a, T> Iterator for Iter<'a, T> {
755 type Item = &'a T;
756
757 fn next(&mut self) -> Option<Self::Item> {
758 self.inner.next()
759 }
760
761 fn size_hint(&self) -> (usize, Option<usize>) {
762 (self.len(), Some(self.len()))
763 }
764}
765
766impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
767 fn next_back(&mut self) -> Option<Self::Item> {
768 self.inner.next_back()
769 }
770}
771
772impl<'a, T> ExactSizeIterator for Iter<'a, T> {
773 fn len(&self) -> usize {
774 self.inner.len()
775 }
776}
777
778impl<'a, T, P> Iterator for PrivateIter<'a, T, P> {
779 type Item = &'a T;
780
781 fn next(&mut self) -> Option<Self::Item> {
782 self.inner
783 .next()
784 .map(|pair| &pair.0)
785 .or_else(|| self.last.next())
786 }
787}
788
789impl<'a, T, P> DoubleEndedIterator for PrivateIter<'a, T, P> {
790 fn next_back(&mut self) -> Option<Self::Item> {
791 self.last
792 .next()
793 .or_else(|| self.inner.next_back().map(|pair| &pair.0))
794 }
795}
796
797impl<'a, T, P> ExactSizeIterator for PrivateIter<'a, T, P> {
798 fn len(&self) -> usize {
799 self.inner.len() + self.last.len()
800 }
801}
802
803impl<'a, T, P> Clone for PrivateIter<'a, T, P> {
805 fn clone(&self) -> Self {
806 PrivateIter {
807 inner: self.inner.clone(),
808 last: self.last.clone(),
809 }
810 }
811}
812
813impl<'a, T, I> IterTrait<'a, T> for I
814where
815 T: 'a,
816 I: DoubleEndedIterator<Item = &'a T> + ExactSizeIterator<Item = &'a T> + Clone + 'a,
817{
818 fn clone_box(&self) -> Box<dyn IterTrait<'a, T, Item = &'a T> + 'a> {
819 Box::new(self.clone())
820 }
821}
822
823pub struct IterMut<'a, T: 'a> {
829 inner: Box<dyn IterMutTrait<'a, T, Item = &'a mut T> + 'a>,
830}
831
832trait IterMutTrait<'a, T: 'a>:
833 DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T>
834{
835}
836
837struct PrivateIterMut<'a, T: 'a, P: 'a> {
838 inner: slice::IterMut<'a, (T, P)>,
839 last: option::IntoIter<&'a mut T>,
840}
841
842#[cfg(any(feature = "full", feature = "derive"))]
843pub(crate) fn empty_punctuated_iter_mut<'a, T>() -> IterMut<'a, T> {
844 IterMut {
845 inner: Box::new(iter::empty()),
846 }
847}
848
849impl<'a, T> Iterator for IterMut<'a, T> {
850 type Item = &'a mut T;
851
852 fn next(&mut self) -> Option<Self::Item> {
853 self.inner.next()
854 }
855
856 fn size_hint(&self) -> (usize, Option<usize>) {
857 (self.len(), Some(self.len()))
858 }
859}
860
861impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
862 fn next_back(&mut self) -> Option<Self::Item> {
863 self.inner.next_back()
864 }
865}
866
867impl<'a, T> ExactSizeIterator for IterMut<'a, T> {
868 fn len(&self) -> usize {
869 self.inner.len()
870 }
871}
872
873impl<'a, T, P> Iterator for PrivateIterMut<'a, T, P> {
874 type Item = &'a mut T;
875
876 fn next(&mut self) -> Option<Self::Item> {
877 self.inner
878 .next()
879 .map(|pair| &mut pair.0)
880 .or_else(|| self.last.next())
881 }
882}
883
884impl<'a, T, P> DoubleEndedIterator for PrivateIterMut<'a, T, P> {
885 fn next_back(&mut self) -> Option<Self::Item> {
886 self.last
887 .next()
888 .or_else(|| self.inner.next_back().map(|pair| &mut pair.0))
889 }
890}
891
892impl<'a, T, P> ExactSizeIterator for PrivateIterMut<'a, T, P> {
893 fn len(&self) -> usize {
894 self.inner.len() + self.last.len()
895 }
896}
897
898impl<'a, T, I> IterMutTrait<'a, T> for I
899where
900 T: 'a,
901 I: DoubleEndedIterator<Item = &'a mut T> + ExactSizeIterator<Item = &'a mut T> + 'a,
902{
903}
904
905pub enum Pair<T, P> {
912 Punctuated(T, P),
913 End(T),
914}
915
916impl<T, P> Pair<T, P> {
917 pub fn into_value(self) -> T {
920 match self {
921 Pair::Punctuated(t, _) | Pair::End(t) => t,
922 }
923 }
924
925 pub fn value(&self) -> &T {
927 match self {
928 Pair::Punctuated(t, _) | Pair::End(t) => t,
929 }
930 }
931
932 pub fn value_mut(&mut self) -> &mut T {
934 match self {
935 Pair::Punctuated(t, _) | Pair::End(t) => t,
936 }
937 }
938
939 pub fn punct(&self) -> Option<&P> {
942 match self {
943 Pair::Punctuated(_, p) => Some(p),
944 Pair::End(_) => None,
945 }
946 }
947
948 pub fn punct_mut(&mut self) -> Option<&mut P> {
967 match self {
968 Pair::Punctuated(_, p) => Some(p),
969 Pair::End(_) => None,
970 }
971 }
972
973 pub fn new(t: T, p: Option<P>) -> Self {
976 match p {
977 Some(p) => Pair::Punctuated(t, p),
978 None => Pair::End(t),
979 }
980 }
981
982 pub fn into_tuple(self) -> (T, Option<P>) {
985 match self {
986 Pair::Punctuated(t, p) => (t, Some(p)),
987 Pair::End(t) => (t, None),
988 }
989 }
990}
991
992#[cfg(feature = "clone-impls")]
993#[cfg_attr(doc_cfg, doc(cfg(feature = "clone-impls")))]
994impl<T, P> Clone for Pair<T, P>
995where
996 T: Clone,
997 P: Clone,
998{
999 fn clone(&self) -> Self {
1000 match self {
1001 Pair::Punctuated(t, p) => Pair::Punctuated(t.clone(), p.clone()),
1002 Pair::End(t) => Pair::End(t.clone()),
1003 }
1004 }
1005}
1006
1007impl<T, P> Index<usize> for Punctuated<T, P> {
1008 type Output = T;
1009
1010 fn index(&self, index: usize) -> &Self::Output {
1011 if index == self.len() - 1 {
1012 match &self.last {
1013 Some(t) => t,
1014 None => &self.inner[index].0,
1015 }
1016 } else {
1017 &self.inner[index].0
1018 }
1019 }
1020}
1021
1022impl<T, P> IndexMut<usize> for Punctuated<T, P> {
1023 fn index_mut(&mut self, index: usize) -> &mut Self::Output {
1024 if index == self.len() - 1 {
1025 match &mut self.last {
1026 Some(t) => t,
1027 None => &mut self.inner[index].0,
1028 }
1029 } else {
1030 &mut self.inner[index].0
1031 }
1032 }
1033}
1034
1035#[cfg(feature = "printing")]
1036mod printing {
1037 use super::*;
1038 use proc_macro2::TokenStream;
1039 use quote::{ToTokens, TokenStreamExt};
1040
1041 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1042 impl<T, P> ToTokens for Punctuated<T, P>
1043 where
1044 T: ToTokens,
1045 P: ToTokens,
1046 {
1047 fn to_tokens(&self, tokens: &mut TokenStream) {
1048 tokens.append_all(self.pairs());
1049 }
1050 }
1051
1052 #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))]
1053 impl<T, P> ToTokens for Pair<T, P>
1054 where
1055 T: ToTokens,
1056 P: ToTokens,
1057 {
1058 fn to_tokens(&self, tokens: &mut TokenStream) {
1059 match self {
1060 Pair::Punctuated(a, b) => {
1061 a.to_tokens(tokens);
1062 b.to_tokens(tokens);
1063 }
1064 Pair::End(a) => a.to_tokens(tokens),
1065 }
1066 }
1067 }
1068}