fallow_extract/
source_map.rs1use oxc_span::Span;
4
5#[derive(Debug, Clone)]
6struct FragmentMap {
7 generated_start: u32,
8 original_start: u32,
9 len: u32,
10}
11
12#[derive(Debug, Clone, Default)]
14pub struct ExtractionResult {
15 pub body: String,
17 fragments: Vec<FragmentMap>,
18}
19
20impl ExtractionResult {
21 #[must_use]
23 pub fn contiguous(body: &str, original_start: usize) -> Self {
24 let mut result = Self::default();
25 result.push_mapped(body, original_start);
26 result
27 }
28
29 pub fn push_mapped(&mut self, text: &str, original_start: usize) {
31 if text.is_empty() {
32 return;
33 }
34 let generated_start = self.body.len();
35 self.body.push_str(text);
36 self.fragments.push(FragmentMap {
37 generated_start: generated_start as u32,
38 original_start: original_start as u32,
39 len: text.len() as u32,
40 });
41 }
42
43 #[must_use]
45 pub fn original_offset(&self, offset: u32) -> Option<u32> {
46 self.original_offset_start_biased(offset)
47 }
48
49 fn original_offset_start_biased(&self, offset: u32) -> Option<u32> {
50 let idx = self
51 .fragments
52 .partition_point(|fragment| fragment.generated_start <= offset)
53 .checked_sub(1)?;
54 let fragment = &self.fragments[idx];
55 let delta = offset.checked_sub(fragment.generated_start)?;
56 if delta <= fragment.len {
57 Some(fragment.original_start + delta)
58 } else {
59 None
60 }
61 }
62
63 fn original_offset_end_biased(&self, offset: u32) -> Option<u32> {
64 let idx = self
65 .fragments
66 .partition_point(|fragment| fragment.generated_start < offset)
67 .checked_sub(1)?;
68 let fragment = &self.fragments[idx];
69 let delta = offset.checked_sub(fragment.generated_start)?;
70 if delta <= fragment.len {
71 Some(fragment.original_start + delta)
72 } else {
73 None
74 }
75 }
76
77 #[must_use]
79 pub fn remap_span(&self, span: Span) -> Span {
80 if span.start == 0 && span.end == 0 {
81 return span;
82 }
83 let Some(start) = self.original_offset(span.start) else {
84 return span;
85 };
86 let Some(end) = self.original_offset_end_biased(span.end) else {
87 return span;
88 };
89 Span::new(start, end)
90 }
91}