Skip to content

Commit 70ef805

Browse files
committed
Merge branch 'perf-with-indices' into perf-with-indices-v2
2 parents 0ac2485 + 428b470 commit 70ef805

File tree

4 files changed

+256
-166
lines changed

4 files changed

+256
-166
lines changed

src/encoder.rs

Lines changed: 232 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,232 @@
1+
use crate::{vlq::encode, Mapping};
2+
3+
pub(crate) trait MappingsEncoder {
4+
fn encode(&mut self, mapping: &Mapping);
5+
fn drain(self: Box<Self>) -> String;
6+
}
7+
8+
pub fn create_encoder(columns: bool) -> Box<dyn MappingsEncoder> {
9+
if columns {
10+
Box::new(FullMappingsEncoder::new())
11+
} else {
12+
Box::new(LinesOnlyMappingsEncoder::new())
13+
}
14+
}
15+
16+
struct FullMappingsEncoder {
17+
current_line: u32,
18+
current_column: u32,
19+
current_original_line: u32,
20+
current_original_column: u32,
21+
current_source_index: u32,
22+
current_name_index: u32,
23+
active_mapping: bool,
24+
active_name: bool,
25+
initial: bool,
26+
mappings: String,
27+
}
28+
29+
impl FullMappingsEncoder {
30+
pub fn new() -> Self {
31+
Self {
32+
current_line: 1,
33+
current_column: 0,
34+
current_original_line: 1,
35+
current_original_column: 0,
36+
current_source_index: 0,
37+
current_name_index: 0,
38+
active_mapping: false,
39+
active_name: false,
40+
initial: true,
41+
mappings: Default::default(),
42+
}
43+
}
44+
}
45+
46+
impl MappingsEncoder for FullMappingsEncoder {
47+
fn encode(&mut self, mapping: &Mapping) {
48+
if self.active_mapping && self.current_line == mapping.generated_line {
49+
// A mapping is still active
50+
if mapping.original.is_some_and(|original| {
51+
original.source_index == self.current_source_index
52+
&& original.original_line == self.current_original_line
53+
&& original.original_column == self.current_original_column
54+
&& !self.active_name
55+
&& original.name_index.is_none()
56+
}) {
57+
// avoid repeating the same original mapping
58+
return;
59+
}
60+
} else {
61+
// No mapping is active
62+
if mapping.original.is_none() {
63+
// avoid writing unnecessary generated mappings
64+
return;
65+
}
66+
}
67+
68+
if self.current_line < mapping.generated_line {
69+
(0..mapping.generated_line - self.current_line)
70+
.for_each(|_| self.mappings.push(';'));
71+
self.current_line = mapping.generated_line;
72+
self.current_column = 0;
73+
self.initial = false;
74+
} else if self.initial {
75+
self.initial = false;
76+
} else {
77+
self.mappings.push(',');
78+
}
79+
80+
encode(
81+
&mut self.mappings,
82+
mapping.generated_column,
83+
self.current_column,
84+
);
85+
self.current_column = mapping.generated_column;
86+
if let Some(original) = &mapping.original {
87+
self.active_mapping = true;
88+
if original.source_index == self.current_source_index {
89+
self.mappings.push('A');
90+
} else {
91+
encode(
92+
&mut self.mappings,
93+
original.source_index,
94+
self.current_source_index,
95+
);
96+
self.current_source_index = original.source_index;
97+
}
98+
encode(
99+
&mut self.mappings,
100+
original.original_line,
101+
self.current_original_line,
102+
);
103+
self.current_original_line = original.original_line;
104+
if original.original_column == self.current_original_column {
105+
self.mappings.push('A');
106+
} else {
107+
encode(
108+
&mut self.mappings,
109+
original.original_column,
110+
self.current_original_column,
111+
);
112+
self.current_original_column = original.original_column;
113+
}
114+
if let Some(name_index) = original.name_index {
115+
encode(&mut self.mappings, name_index, self.current_name_index);
116+
self.current_name_index = name_index;
117+
self.active_name = true;
118+
} else {
119+
self.active_name = false;
120+
}
121+
} else {
122+
self.active_mapping = false;
123+
}
124+
}
125+
126+
fn drain(self: Box<Self>) -> String {
127+
self.mappings
128+
}
129+
}
130+
131+
pub(crate) struct LinesOnlyMappingsEncoder {
132+
last_written_line: u32,
133+
current_line: u32,
134+
current_source_index: u32,
135+
current_original_line: u32,
136+
mappings: String,
137+
}
138+
139+
impl LinesOnlyMappingsEncoder {
140+
pub fn new() -> Self {
141+
Self {
142+
last_written_line: 0,
143+
current_line: 1,
144+
current_source_index: 0,
145+
current_original_line: 1,
146+
mappings: Default::default(),
147+
}
148+
}
149+
}
150+
151+
impl MappingsEncoder for LinesOnlyMappingsEncoder {
152+
fn encode(&mut self, mapping: &Mapping) {
153+
if let Some(original) = &mapping.original {
154+
if self.last_written_line == mapping.generated_line {
155+
// avoid writing multiple original mappings per line
156+
return;
157+
}
158+
self.last_written_line = mapping.generated_line;
159+
if mapping.generated_line == self.current_line + 1 {
160+
self.current_line = mapping.generated_line;
161+
if original.source_index == self.current_source_index {
162+
if original.original_line == self.current_original_line + 1 {
163+
self.current_original_line = original.original_line;
164+
self.mappings.push_str(";AACA");
165+
} else {
166+
self.mappings.push_str(";AA");
167+
encode(
168+
&mut self.mappings,
169+
original.original_line,
170+
self.current_original_line,
171+
);
172+
self.current_original_line = original.original_line;
173+
self.mappings.push('A');
174+
}
175+
} else {
176+
self.mappings.push_str(";A");
177+
encode(
178+
&mut self.mappings,
179+
original.source_index,
180+
self.current_source_index,
181+
);
182+
self.current_source_index = original.source_index;
183+
encode(
184+
&mut self.mappings,
185+
original.original_line,
186+
self.current_original_line,
187+
);
188+
self.current_original_line = original.original_line;
189+
self.mappings.push('A');
190+
}
191+
} else {
192+
(0..mapping.generated_line - self.current_line)
193+
.for_each(|_| self.mappings.push(';'));
194+
self.current_line = mapping.generated_line;
195+
if original.source_index == self.current_source_index {
196+
if original.original_line == self.current_original_line + 1 {
197+
self.current_original_line = original.original_line;
198+
self.mappings.push_str("AACA");
199+
} else {
200+
self.mappings.push_str("AA");
201+
encode(
202+
&mut self.mappings,
203+
original.original_line,
204+
self.current_original_line,
205+
);
206+
self.current_original_line = original.original_line;
207+
self.mappings.push('A');
208+
}
209+
} else {
210+
self.mappings.push('A');
211+
encode(
212+
&mut self.mappings,
213+
original.source_index,
214+
self.current_source_index,
215+
);
216+
self.current_source_index = original.source_index;
217+
encode(
218+
&mut self.mappings,
219+
original.original_line,
220+
self.current_original_line,
221+
);
222+
self.current_original_line = original.original_line;
223+
self.mappings.push('A');
224+
}
225+
}
226+
}
227+
}
228+
229+
fn drain(self: Box<Self>) -> String {
230+
self.mappings
231+
}
232+
}

0 commit comments

Comments
 (0)