sway_ast/
punctuated.rs

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    /// Returns true if the [Punctuated] ends with the punctuation token.
39    /// E.g., `fn fun(x: u64, y: u64,)`.
40    pub fn has_trailing_punctuation(&self) -> bool {
41        !self.value_separator_pairs.is_empty() && self.final_value_opt.is_none()
42    }
43
44    /// Returns true if the [Punctuated] has neither value separator pairs,
45    /// nor the final value.
46    /// E.g., `fn fun()`.
47    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}