parcel_sourcemap/
mapping_line.rs1use crate::mapping::OriginalLocation;
2use crate::sourcemap_error::{SourceMapError, SourceMapErrorType};
3use rkyv::{Archive, Deserialize, Serialize};
4
5#[derive(Archive, Serialize, Deserialize, Debug, Clone, Copy, Default)]
6pub struct LineMapping {
7 pub generated_column: u32,
8 pub original: Option<OriginalLocation>,
9}
10
11#[derive(Archive, Serialize, Deserialize, Debug, Default, Clone)]
12pub struct MappingLine {
13 pub mappings: Vec<LineMapping>,
14 pub last_column: u32,
15 pub is_sorted: bool,
16}
17
18impl MappingLine {
19 pub fn new() -> Self {
20 Self {
21 mappings: Vec::new(),
22 last_column: 0,
23 is_sorted: true,
24 }
25 }
26
27 pub fn add_mapping(&mut self, generated_column: u32, original: Option<OriginalLocation>) {
28 if self.is_sorted && self.last_column > generated_column {
29 self.is_sorted = false;
30 }
31
32 self.mappings.push(LineMapping {
33 generated_column,
34 original,
35 });
36
37 self.last_column = generated_column;
38 }
39
40 pub fn ensure_sorted(&mut self) {
41 if !self.is_sorted {
42 self.mappings
43 .sort_by(|a, b| a.generated_column.cmp(&b.generated_column));
44 self.is_sorted = true
45 }
46 }
47
48 pub fn find_closest_mapping(&mut self, generated_column: u32) -> Option<LineMapping> {
49 if self.mappings.is_empty() {
50 return None;
51 }
52
53 self.ensure_sorted();
54 let index = match self
55 .mappings
56 .binary_search_by(|m| m.generated_column.cmp(&generated_column))
57 {
58 Ok(index) => index,
59 Err(index) => {
60 if index == 0 || index == self.mappings.len() {
61 return Some(LineMapping {
62 generated_column: 0,
63 original: self.mappings[0].original,
64 });
65 }
66
67 index - 1
68 }
69 };
70
71 Some(self.mappings[index])
72 }
73
74 pub fn offset_columns(
75 &mut self,
76 generated_column: u32,
77 generated_column_offset: i64,
78 ) -> Result<(), SourceMapError> {
79 let (start_column, overflowed) =
80 (generated_column as i64).overflowing_add(generated_column_offset);
81 if overflowed || start_column > (u32::MAX as i64) {
82 return Err(SourceMapError::new_with_reason(
83 SourceMapErrorType::UnexpectedNegativeNumber,
84 "column + column_offset cannot be negative",
85 ));
86 }
87
88 self.ensure_sorted();
89 let mut index = match self
90 .mappings
91 .binary_search_by(|m| m.generated_column.cmp(&generated_column))
92 {
93 Ok(index) => index,
94 Err(index) => index,
95 };
96
97 if generated_column_offset < 0 {
98 let u_start_column = start_column as u32;
99 let start_index = match self
100 .mappings
101 .binary_search_by(|m| m.generated_column.cmp(&u_start_column))
102 {
103 Ok(index) => index,
104 Err(index) => index,
105 };
106
107 self.mappings.drain(start_index..index);
108 index = start_index;
109 }
110
111 let abs_offset = generated_column_offset.unsigned_abs() as u32;
112 for i in index..self.mappings.len() {
113 let mapping = &mut self.mappings[i];
114 mapping.generated_column = if generated_column_offset < 0 {
115 mapping.generated_column - abs_offset
116 } else {
117 mapping.generated_column + abs_offset
118 };
119 }
120
121 Ok(())
122 }
123}