sqruff_lib_core/utils/functional/
segments.rs1use std::ops::Range;
2
3use crate::dialects::syntax::SyntaxSet;
4use crate::parser::segments::ErasedSegment;
5use crate::templaters::TemplatedFile;
6
7type PredicateType = Option<fn(&ErasedSegment) -> bool>;
8
9#[derive(Debug, Default, Clone)]
10pub struct Segments {
11 pub base: Vec<ErasedSegment>,
12 templated_file: Option<TemplatedFile>,
13}
14
15impl Segments {
16 pub fn into_vec(self) -> Vec<ErasedSegment> {
17 self.base
18 }
19
20 pub fn iter(&self) -> impl Iterator<Item = &ErasedSegment> {
21 self.base.iter()
22 }
23
24 pub fn recursive_crawl(&self, types: &SyntaxSet, recurse_into: bool) -> Segments {
25 let mut segments = Vec::new();
26
27 for s in &self.base {
28 segments.extend(s.recursive_crawl(types, recurse_into, &SyntaxSet::EMPTY, true));
29 }
30
31 Segments::from_vec(segments, self.templated_file.clone())
32 }
33
34 pub fn iterate_segments(&self) -> impl Iterator<Item = Segments> + '_ {
35 let mut iter = self.base.iter();
36
37 std::iter::from_fn(move || {
38 let segment = iter.next()?;
39 Segments::new(segment.clone(), self.templated_file.clone()).into()
40 })
41 }
42
43 pub fn from_vec(base: Vec<ErasedSegment>, templated_file: Option<TemplatedFile>) -> Self {
44 Self {
45 base,
46 templated_file,
47 }
48 }
49
50 pub fn reversed(&self) -> Self {
51 let mut base = self.base.clone();
52 base.reverse();
53
54 Self {
55 base,
56 templated_file: self.templated_file.clone(),
57 }
58 }
59
60 pub fn get(&self, index: usize, default: Option<ErasedSegment>) -> Option<ErasedSegment> {
61 self.base.get(index).cloned().or(default)
62 }
63
64 pub fn first(&self) -> Option<&ErasedSegment> {
65 self.base.first()
66 }
67
68 pub fn last(&self) -> Option<&ErasedSegment> {
69 self.base.last()
70 }
71
72 #[track_caller]
73 pub fn pop(&mut self) -> ErasedSegment {
74 self.base.pop().unwrap()
75 }
76
77 pub fn all(&self, predicate: PredicateType) -> bool {
78 self.base
79 .iter()
80 .all(|s| predicate.is_none_or(|pred| pred(s)))
81 }
82
83 pub fn any(&self, predicate: PredicateType) -> bool {
84 self.base
85 .iter()
86 .any(|s| predicate.is_none_or(|pred| pred(s)))
87 }
88
89 pub fn len(&self) -> usize {
90 self.base.len()
91 }
92
93 pub fn is_empty(&self) -> bool {
94 self.base.is_empty()
95 }
96
97 pub fn new(segment: ErasedSegment, templated_file: Option<TemplatedFile>) -> Self {
98 Self {
99 base: vec![segment],
100 templated_file,
101 }
102 }
103
104 pub fn children(&self, predicate: PredicateType) -> Segments {
105 let mut child_segments = Vec::with_capacity(predicate.map_or(0, |_| self.len()));
106
107 for s in &self.base {
108 for child in s.segments() {
109 if let Some(ref pred) = predicate {
110 if pred(child) {
111 child_segments.push(child.clone());
112 }
113 } else {
114 child_segments.push(child.clone());
115 }
116 }
117 }
118
119 Segments {
120 base: child_segments,
121 templated_file: self.templated_file.clone(),
122 }
123 }
124
125 pub fn find_last(&self, predicate: PredicateType) -> Segments {
126 self.base
127 .iter()
128 .rev()
129 .find_map(|s| {
130 if predicate.as_ref().is_none_or(|p| p(s)) {
131 Some(Segments {
132 base: vec![s.clone()],
133 templated_file: self.templated_file.clone(),
134 })
135 } else {
136 None
137 }
138 })
139 .unwrap_or_else(|| Segments {
140 base: vec![],
141 templated_file: self.templated_file.clone(),
142 })
143 }
144
145 pub fn find(&self, value: &ErasedSegment) -> Option<usize> {
146 self.index(value)
147 }
148
149 pub fn find_first<F: Fn(&ErasedSegment) -> bool>(&self, predicate: Option<F>) -> Segments {
150 for s in &self.base {
151 if predicate.as_ref().is_none_or(|p| p(s)) {
152 return Segments {
153 base: vec![s.clone()],
154 templated_file: self.templated_file.clone(),
155 };
156 }
157 }
158
159 Segments {
160 base: vec![],
161 templated_file: self.templated_file.clone(),
162 }
163 }
164
165 pub fn index(&self, value: &ErasedSegment) -> Option<usize> {
166 self.base.iter().position(|it| it == value)
167 }
168
169 #[track_caller]
170 pub fn select<SelectIf: Fn(&ErasedSegment) -> bool>(
171 &self,
172 select_if: Option<SelectIf>,
173 loop_while: PredicateType,
174 start_seg: Option<&ErasedSegment>,
175 stop_seg: Option<&ErasedSegment>,
176 ) -> Segments {
177 let start_index = start_seg
178 .map(|seg| self.base.iter().position(|x| x == seg).unwrap() as isize)
179 .unwrap_or(-1);
180
181 let stop_index = stop_seg
182 .map(|seg| self.base.iter().position(|x| x == seg).unwrap() as isize)
183 .unwrap_or_else(|| self.base.len() as isize);
184
185 let mut buff = Vec::new();
186
187 for seg in pyslice(&self.base, start_index + 1..stop_index) {
188 if let Some(loop_while) = &loop_while
189 && !loop_while(seg)
190 {
191 break;
192 }
193
194 if select_if.as_ref().is_none_or(|f| f(seg)) {
195 buff.push(seg.clone());
196 }
197 }
198
199 Segments {
200 base: buff,
201 templated_file: self.templated_file.clone(),
202 }
203 }
204}
205
206impl<I: std::slice::SliceIndex<[ErasedSegment]>> std::ops::Index<I> for Segments {
207 type Output = I::Output;
208
209 fn index(&self, index: I) -> &Self::Output {
210 &self.base[index]
211 }
212}
213
214impl IntoIterator for Segments {
215 type Item = ErasedSegment;
216 type IntoIter = std::vec::IntoIter<Self::Item>;
217
218 fn into_iter(self) -> Self::IntoIter {
219 self.base.into_iter()
220 }
221}
222
223fn pyslice<T>(collection: &[T], Range { start, end }: Range<isize>) -> impl Iterator<Item = &T> {
224 let slice = slyce::Slice {
225 start: start.into(),
226 end: end.into(),
227 step: None,
228 };
229 slice.apply(collection)
230}