1use crate::priv_prelude::*;
2
3#[derive(Clone, Debug, Serialize)]
4pub struct Punctuated<T, P> {
5 pub value_separator_pairs: Vec<(T, P)>,
6 pub final_value_opt: Option<Box<T>>,
7}
8
9impl<T, P> Punctuated<T, P> {
10 pub fn empty() -> Self {
11 Self {
12 value_separator_pairs: vec![],
13 final_value_opt: None,
14 }
15 }
16
17 pub fn single(value: T) -> Self {
18 Self {
19 value_separator_pairs: vec![],
20 final_value_opt: Some(Box::new(value)),
21 }
22 }
23
24 pub fn iter(&self) -> impl Iterator<Item = &T> {
25 self.value_separator_pairs
26 .iter()
27 .map(|(t, _)| t)
28 .chain(self.final_value_opt.iter().map(|t| &**t))
29 }
30
31 pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
32 self.value_separator_pairs
33 .iter_mut()
34 .map(|(t, _)| t)
35 .chain(self.final_value_opt.iter_mut().map(|t| &mut **t))
36 }
37
38 pub fn has_trailing_punctuation(&self) -> bool {
41 !self.value_separator_pairs.is_empty() && self.final_value_opt.is_none()
42 }
43
44 pub fn is_empty(&self) -> bool {
48 self.value_separator_pairs.is_empty() && self.final_value_opt.is_none()
49 }
50}
51
52impl<T, P> IntoIterator for Punctuated<T, P> {
53 type Item = T;
54 type IntoIter = PunctuatedIter<T, P>;
55 fn into_iter(self) -> PunctuatedIter<T, P> {
56 PunctuatedIter {
57 value_separator_pairs: self.value_separator_pairs.into_iter(),
58 final_value_opt: self.final_value_opt,
59 }
60 }
61}
62
63pub struct PunctuatedIter<T, P> {
64 value_separator_pairs: std::vec::IntoIter<(T, P)>,
65 final_value_opt: Option<Box<T>>,
66}
67
68impl<T, P> Iterator for PunctuatedIter<T, P> {
69 type Item = T;
70
71 fn next(&mut self) -> Option<T> {
72 match self.value_separator_pairs.next() {
73 Some((value, _separator)) => Some(value),
74 None => self.final_value_opt.take().map(|final_value| *final_value),
75 }
76 }
77}
78
79impl<'a, T, P> IntoIterator for &'a Punctuated<T, P> {
80 type Item = &'a T;
81 type IntoIter = PunctuatedRefIter<'a, T, P>;
82 fn into_iter(self) -> PunctuatedRefIter<'a, T, P> {
83 PunctuatedRefIter {
84 punctuated: self,
85 index: 0,
86 }
87 }
88}
89
90pub struct PunctuatedRefIter<'a, T, P> {
91 punctuated: &'a Punctuated<T, P>,
92 index: usize,
93}
94
95impl<'a, T, P> Iterator for PunctuatedRefIter<'a, T, P> {
96 type Item = &'a T;
97
98 fn next(&mut self) -> Option<&'a T> {
99 if self.index > self.punctuated.value_separator_pairs.len() {
100 return None;
101 }
102 match self.punctuated.value_separator_pairs.get(self.index) {
103 None => match &self.punctuated.final_value_opt {
104 Some(value) => {
105 self.index += 1;
106 Some(value)
107 }
108 None => None,
109 },
110 Some((value, _separator)) => {
111 self.index += 1;
112 Some(value)
113 }
114 }
115 }
116}