Skip to content

Commit 08fca46

Browse files
authored
perf: mappings encoder and decoder (#114)
* perf: MappingsEncoder * perf: new mappings decoder
1 parent fef4544 commit 08fca46

File tree

10 files changed

+302
-591
lines changed

10 files changed

+302
-591
lines changed

Cargo.lock

Lines changed: 0 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ dyn-clone = "1"
3636
rustc-hash = "1"
3737
dashmap = "5"
3838
memchr = "2.6.4"
39-
arrayvec = "0.7.4"
4039

4140
codspeed-criterion-compat = { version = "2.3.3", default-features = false, optional = true }
4241
simd-json = "=0.14.0-rc.2"

src/decoder.rs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
use std::slice::Iter;
2+
3+
use crate::{Mapping, OriginalLocation};
4+
5+
const COM: u8 = 0x40; // END_SEGMENT_BIT
6+
const SEM: u8 = COM | 0x01; // NEXT_LINE
7+
const ERR: u8 = COM | 0x02; // INVALID
8+
9+
const CONTINUATION_BIT: u8 = 0x20;
10+
const DATA_MASK: u8 = 0x1f;
11+
12+
#[rustfmt::skip]
13+
const B64: [u8; 256] = [
14+
// 0 1 2 3 4 5 6 7 8 9 A B C D E F //
15+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 0
16+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 1
17+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, 62, COM, ERR, ERR, 63, // 2
18+
52, 53, 54, 55, 56, 57, 58, 59, 60, 61, ERR, SEM, ERR, ERR, ERR, ERR, // 3
19+
ERR, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 4
20+
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, ERR, ERR, ERR, ERR, ERR, // 5
21+
ERR, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 6
22+
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, ERR, ERR, ERR, ERR, ERR, // 7
23+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 8
24+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // 9
25+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // A
26+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // B
27+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // C
28+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // D
29+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // E
30+
ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, ERR, // F
31+
];
32+
33+
pub(crate) struct MappingsDecoder<'a> {
34+
mappings_iter: Iter<'a, u8>,
35+
36+
current_data: [u32; 5],
37+
current_data_pos: usize,
38+
// current_value will include a sign bit at bit 0
39+
current_value: i64,
40+
current_value_pos: usize,
41+
generated_line: u32,
42+
generated_column: i64,
43+
}
44+
45+
impl<'a> MappingsDecoder<'a> {
46+
pub fn new(mappings: &'a str) -> Self {
47+
Self {
48+
mappings_iter: mappings.as_bytes().iter(),
49+
current_data: [0u32, 0u32, 1u32, 0u32, 0u32],
50+
current_data_pos: 0,
51+
// current_value will include a sign bit at bit 0
52+
current_value: 0,
53+
current_value_pos: 0,
54+
generated_line: 1,
55+
generated_column: -1,
56+
}
57+
}
58+
}
59+
60+
impl<'a> Iterator for MappingsDecoder<'a> {
61+
type Item = Mapping;
62+
63+
fn next(&mut self) -> Option<Self::Item> {
64+
for c in &mut self.mappings_iter {
65+
let value = B64[*c as usize];
66+
if value == ERR {
67+
continue;
68+
}
69+
if (value & COM) != 0 {
70+
let mapping = match self.current_data_pos {
71+
1 => Some(Mapping {
72+
generated_line: self.generated_line,
73+
generated_column: self.current_data[0],
74+
original: None,
75+
}),
76+
4 => Some(Mapping {
77+
generated_line: self.generated_line,
78+
generated_column: self.current_data[0],
79+
original: Some(OriginalLocation {
80+
source_index: self.current_data[1],
81+
original_line: self.current_data[2],
82+
original_column: self.current_data[3],
83+
name_index: None,
84+
}),
85+
}),
86+
5 => Some(Mapping {
87+
generated_line: self.generated_line,
88+
generated_column: self.current_data[0],
89+
original: Some(OriginalLocation {
90+
source_index: self.current_data[1],
91+
original_line: self.current_data[2],
92+
original_column: self.current_data[3],
93+
name_index: Some(self.current_data[4]),
94+
}),
95+
}),
96+
_ => None,
97+
};
98+
self.generated_column = self.current_data[0] as i64;
99+
self.current_data_pos = 0;
100+
if value == SEM {
101+
self.generated_line += 1;
102+
self.current_data[0] = 0;
103+
self.generated_column = -1;
104+
}
105+
if mapping.is_some() {
106+
return mapping;
107+
}
108+
} else if (value & CONTINUATION_BIT) == 0 {
109+
// last sextet
110+
self.current_value |= (value as i64) << self.current_value_pos;
111+
let final_value = if (self.current_value & 1) != 0 {
112+
-(self.current_value >> 1)
113+
} else {
114+
self.current_value >> 1
115+
};
116+
if self.current_data_pos < 5 {
117+
self.current_data[self.current_data_pos] =
118+
(self.current_data[self.current_data_pos] as i64 + final_value)
119+
as u32;
120+
}
121+
self.current_data_pos += 1;
122+
self.current_value_pos = 0;
123+
self.current_value = 0;
124+
} else {
125+
self.current_value |=
126+
((value & DATA_MASK) as i64) << self.current_value_pos;
127+
self.current_value_pos += 5;
128+
}
129+
}
130+
131+
// end current segment
132+
let current_data_pos = self.current_data_pos;
133+
self.current_data_pos = 0;
134+
match current_data_pos {
135+
1 => {
136+
return Some(Mapping {
137+
generated_line: self.generated_line,
138+
generated_column: self.current_data[0],
139+
original: None,
140+
})
141+
}
142+
4 => {
143+
return Some(Mapping {
144+
generated_line: self.generated_line,
145+
generated_column: self.current_data[0],
146+
original: Some(OriginalLocation {
147+
source_index: self.current_data[1],
148+
original_line: self.current_data[2],
149+
original_column: self.current_data[3],
150+
name_index: None,
151+
}),
152+
})
153+
}
154+
5 => {
155+
return Some(Mapping {
156+
generated_line: self.generated_line,
157+
generated_column: self.current_data[0],
158+
original: Some(OriginalLocation {
159+
source_index: self.current_data[1],
160+
original_line: self.current_data[2],
161+
original_column: self.current_data[3],
162+
name_index: Some(self.current_data[4]),
163+
}),
164+
})
165+
}
166+
_ => (),
167+
}
168+
169+
None
170+
}
171+
}

0 commit comments

Comments
 (0)