1use crate::*;
7use core::ops::Range;
8
9pub type ByteSpan = Range<usize>;
11
12#[derive(Default, Debug, Clone, PartialEq, Eq)]
23pub struct Span<'a> {
24 pub file: &'a str,
25 pub bytes: ByteSpan,
26 pub expanded_from: Option<&'a Span<'a>>,
27 pub included_from: Option<&'a Span<'a>>,
28}
29
30#[derive(Debug, PartialEq)]
33pub enum SpanRelation {
34 Earlier,
35 Later,
36 Same,
37}
38
39impl<'a> Span<'a> {
40 fn include_indeces(&self) -> Vec<usize> {
41 match &self.included_from {
42 None => {
43 vec![self.bytes.start]
44 }
45 Some(inner_span) => {
46 let mut nested_byte_indeces = inner_span.include_indeces();
47 nested_byte_indeces.push(self.bytes.start);
48 nested_byte_indeces
49 }
50 }
51 }
52 fn indeces_to_compare(&self) -> Vec<Vec<usize>> {
53 let mut indeces = vec![self.include_indeces()];
54 match self.expanded_from {
55 Some(expanded_span) => {
56 indeces.extend(expanded_span.indeces_to_compare())
57 }
58 None => (),
59 };
60 indeces
61 }
62 pub fn compare(&self, other: &Self) -> SpanRelation {
88 let mut idx = 0;
89 let self_include_byte_indeces = self.indeces_to_compare();
90 let other_include_byte_indeces = other.indeces_to_compare();
91 loop {
92 match (
93 self_include_byte_indeces.get(idx),
94 other_include_byte_indeces.get(idx),
95 ) {
96 (Some(self_idxs), Some(other_idxs)) => {
97 let mut nested_idx = 0;
98 'match_define: loop {
99 match (
100 self_idxs.get(nested_idx),
101 other_idxs.get(nested_idx),
102 ) {
103 (Some(self_idx), Some(other_idx)) => {
104 if self_idx < other_idx {
105 return SpanRelation::Earlier;
106 } else if self_idx > other_idx {
107 return SpanRelation::Later;
108 } else {
109 nested_idx += 1;
110 }
111 }
112 (None, None) => {
113 break 'match_define;
114 }
115 _ => {
116 panic!(
117 "Internal error comparing spans {:?} and {:?}",
118 self, other
119 )
120 }
121 }
122 }
123 idx += 1;
124 }
125 (None, None) => {
126 break SpanRelation::Same;
127 }
128 _ => {
129 panic!(
130 "Internal error comparing spans {:?} and {:?}",
131 self, other
132 )
133 }
134 }
135 }
136 }
137
138 pub const fn expansion_depth(&self) -> usize {
140 let mut curr_span: &Span = self;
141 let mut depth = 0;
142 loop {
143 if let Some(expanded_from_span) = curr_span.expanded_from {
144 curr_span = expanded_from_span;
145 depth += 1;
146 } else {
147 break;
148 }
149 }
150 depth
151 }
152
153 pub const fn inclusion_depth(&self) -> usize {
155 let mut curr_span: &Span = self;
156 let mut depth = 0;
157 loop {
158 if let Some(included_from_span) = curr_span.included_from {
159 curr_span = included_from_span;
160 depth += 1;
161 } else {
162 break;
163 }
164 }
165 depth
166 }
167}
168
169#[test]
170fn basic_span_comparison() {
171 let span1 = Span {
172 file: "",
173 bytes: (0..2),
174 expanded_from: None,
175 included_from: None,
176 };
177 let span2 = Span {
178 file: "",
179 bytes: (2..4),
180 expanded_from: None,
181 included_from: None,
182 };
183 assert_eq!(span1.compare(&span2), SpanRelation::Earlier)
184}
185
186#[test]
187fn include_span_comparison() {
188 let span1 = Span {
189 file: "",
190 bytes: (2..4),
191 expanded_from: None,
192 included_from: None,
193 };
194 let included_span = Span {
195 file: "",
196 bytes: (0..2),
197 expanded_from: None,
198 included_from: None,
199 };
200 let span2 = Span {
202 file: "",
203 bytes: (4..6),
204 expanded_from: None,
205 included_from: Some(&included_span),
206 };
207 assert_eq!(span1.compare(&span2), SpanRelation::Later)
208}
209
210#[test]
211fn define_span_comparison() {
212 let span1 = Span {
213 file: "",
214 bytes: (2..4),
215 expanded_from: None,
216 included_from: None,
217 };
218 let definition_span = Span {
219 file: "",
220 bytes: (0..2),
221 expanded_from: None,
222 included_from: None,
223 };
224 let span2 = Span {
226 file: "",
227 bytes: (4..6),
228 expanded_from: Some(&definition_span),
229 included_from: None,
230 };
231 assert_eq!(span1.compare(&span2), SpanRelation::Earlier)
232}
233
234#[test]
235fn mixed_define_span_comparison() {
236 let definition_span1 = Span {
237 file: "",
238 bytes: (102..104),
239 expanded_from: None,
240 included_from: None,
241 };
242 let span1 = Span {
243 file: "",
244 bytes: (0..2),
245 expanded_from: Some(&definition_span1),
246 included_from: None,
247 };
248 let definition_span2 = Span {
249 file: "",
250 bytes: (100..102),
251 expanded_from: None,
252 included_from: None,
253 };
254 let span2 = Span {
256 file: "",
257 bytes: (2..4),
258 expanded_from: Some(&definition_span2),
259 included_from: None,
260 };
261 assert_eq!(span1.compare(&span2), SpanRelation::Earlier)
262}
263
264#[test]
265fn same_definition_span_comparison() {
266 let definition_span1 = Span {
267 file: "",
268 bytes: (2..4),
269 expanded_from: None,
270 included_from: None,
271 };
272 let span1 = Span {
273 file: "",
274 bytes: (100..104),
275 expanded_from: Some(&definition_span1),
276 included_from: None,
277 };
278 let definition_span2 = Span {
279 file: "",
280 bytes: (0..2),
281 expanded_from: None,
282 included_from: None,
283 };
284 let span2 = Span {
285 file: "",
286 bytes: (100..104),
287 expanded_from: Some(&definition_span2),
288 included_from: None,
289 };
290 assert_eq!(span1.compare(&span2), SpanRelation::Later)
291}
292
293#[test]
294fn define_include_span_comparison() {
295 let definition_span1 = Span {
297 file: "",
298 bytes: (2..4),
299 expanded_from: None,
300 included_from: None,
301 };
302 let inclusion_span1 = Span {
303 file: "",
304 bytes: (50..52),
305 expanded_from: None,
306 included_from: None,
307 };
308 let span1 = Span {
309 file: "",
310 bytes: (100..104),
311 expanded_from: Some(&definition_span1),
312 included_from: Some(&inclusion_span1),
313 };
314 let definition_span2 = Span {
315 file: "",
316 bytes: (0..2),
317 expanded_from: None,
318 included_from: None,
319 };
320 let inclusion_span2 = Span {
321 file: "",
322 bytes: (52..54),
323 expanded_from: None,
324 included_from: None,
325 };
326 let span2 = Span {
327 file: "",
328 bytes: (100..104),
329 expanded_from: Some(&definition_span2),
330 included_from: Some(&inclusion_span2),
331 };
332 assert_eq!(span1.compare(&span2), SpanRelation::Earlier)
333}
334
335#[test]
336fn same_define_include_span_comparison() {
337 let definition_span1 = Span {
339 file: "",
340 bytes: (2..4),
341 expanded_from: None,
342 included_from: None,
343 };
344 let inclusion_span1 = Span {
345 file: "",
346 bytes: (50..52),
347 expanded_from: None,
348 included_from: None,
349 };
350 let span1 = Span {
351 file: "",
352 bytes: (100..104),
353 expanded_from: Some(&definition_span1),
354 included_from: Some(&inclusion_span1),
355 };
356 let definition_span2 = Span {
357 file: "",
358 bytes: (0..2),
359 expanded_from: None,
360 included_from: None,
361 };
362 let inclusion_span2 = Span {
363 file: "",
364 bytes: (50..52),
365 expanded_from: None,
366 included_from: None,
367 };
368 let span2 = Span {
369 file: "",
370 bytes: (100..104),
371 expanded_from: Some(&definition_span2),
372 included_from: Some(&inclusion_span2),
373 };
374 assert_eq!(span1.compare(&span2), SpanRelation::Later)
375}
376
377#[cfg(feature = "lossless")]
383#[derive(Default, Clone, Debug)]
384pub struct Metadata<'a> {
385 pub span: Span<'a>,
386 pub non_trivia: Vec<NonTriviaToken<'a>>,
387}
388
389#[cfg(not(feature = "lossless"))]
395#[derive(Default, Clone, Debug)]
396pub struct Metadata<'a> {
397 pub span: Span<'a>,
398}
399
400impl<'a> Metadata<'a> {
401 #[cfg(feature = "lossless")]
404 pub fn new(span: Span<'a>, non_trivia: Vec<NonTriviaToken<'a>>) -> Self {
405 Self { span, non_trivia }
406 }
407
408 #[cfg(not(feature = "lossless"))]
411 #[allow(unused_variables)]
412 pub fn new(span: Span<'a>, non_trivia: Vec<NonTriviaToken<'a>>) -> Self {
413 Self { span }
414 }
415}
416
417impl<'a> PartialEq for Metadata<'a> {
418 fn eq(&self, _: &Self) -> bool {
419 true
422 }
423}
424
425impl<'a, 'b> IntoIterator for &'b Metadata<'a> {
427 type Item = Node<'a, 'b>;
428 type IntoIter = std::iter::Empty<Node<'a, 'b>>;
429 fn into_iter(self) -> Self::IntoIter {
430 std::iter::empty()
431 }
432}
433
434impl<'a, 'b> IntoIterator for &'b mut Metadata<'a> {
435 type Item = Node<'a, 'b>;
436 type IntoIter = std::iter::Empty<Node<'a, 'b>>;
437 fn into_iter(self) -> Self::IntoIter {
438 std::iter::empty()
439 }
440}
441
442#[derive(Clone, Debug, PartialEq)]
444pub enum NonTriviaToken<'a> {
445 OnelineComment(&'a str, Span<'a>),
446 BlockComment(&'a str, Span<'a>),
447 Newline,
448}