Skip to content

Commit aacdc78

Browse files
committed
perf: next_segment
1 parent 89e14f6 commit aacdc78

File tree

2 files changed

+78
-42
lines changed

2 files changed

+78
-42
lines changed

src/helpers.rs

+31-18
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use arrayvec::ArrayVec;
2+
use core::fmt;
23
use std::{
34
borrow::{BorrowMut, Cow},
45
cell::RefCell,
@@ -13,7 +14,7 @@ use crate::{
1314
source::{Mapping, OriginalLocation},
1415
vlq::decode,
1516
with_indices::WithIndices,
16-
MapOptions, SourceMap,
17+
Error, MapOptions, SourceMap,
1718
};
1819

1920
// Adding this type because sourceContentLine not happy
@@ -210,29 +211,41 @@ impl<'a> Iterator for SegmentIter<'a> {
210211
match self.next_segment() {
211212
Some(segment) => {
212213
self.nums.clear();
213-
decode(segment, &mut self.nums).unwrap();
214-
self.generated_column =
215-
(i64::from(self.generated_column) + self.nums[0]) as u32;
214+
let mut vlq = decode(segment);
215+
self.generated_column = (i64::from(self.generated_column)
216+
+ vlq
217+
.next()
218+
.unwrap_or_else(|| Err(Error::VlqNoValues))
219+
.unwrap()) as u32;
216220

217221
let mut src = None;
218222
let mut name = None;
219223

220-
if self.nums.len() > 1 {
221-
if self.nums.len() != 4 && self.nums.len() != 5 {
222-
panic!("got {} segments, expected 4 or 5", self.nums.len());
223-
}
224+
if let Some(source_index) = vlq.next() {
225+
// if self.nums.len() != 4 && self.nums.len() != 5 {
226+
// panic!("got {} segments, expected 4 or 5", self.nums.len());
227+
// }
224228
self.source_index =
225-
(i64::from(self.source_index) + self.nums[1]) as u32;
229+
(i64::from(self.source_index) + source_index.unwrap()) as u32;
226230
src = Some(self.source_index);
227-
self.original_line =
228-
(i64::from(self.original_line) + self.nums[2]) as u32;
229-
self.original_column =
230-
(i64::from(self.original_column) + self.nums[3]) as u32;
231-
232-
if self.nums.len() > 4 {
233-
self.name_index =
234-
(i64::from(self.name_index) + self.nums[4]) as u32;
235-
name = Some(self.name_index);
231+
self.original_line = (i64::from(self.original_line)
232+
+ vlq
233+
.next()
234+
.unwrap_or_else(|| Err(Error::VlqNoValues))
235+
.unwrap()) as u32;
236+
self.original_column = (i64::from(self.original_column)
237+
+ vlq
238+
.next()
239+
.unwrap_or_else(|| Err(Error::VlqNoValues))
240+
.unwrap()) as u32;
241+
242+
match vlq.next() {
243+
Some(name_index) => {
244+
self.name_index =
245+
(i64::from(self.name_index) + name_index.unwrap()) as u32;
246+
name = Some(self.name_index)
247+
}
248+
None => (),
236249
}
237250
}
238251

src/vlq.rs

+47-24
Original file line numberDiff line numberDiff line change
@@ -24,36 +24,59 @@ const B64: [i8; 256] = [
2424
-1, -1, -1, -1, -1, -1,
2525
];
2626

27-
/// Parses a VLQ segment into a pre-allocated `Vec` instead of returning a new allocation.
28-
pub fn decode(segment: &[u8], rv: &mut ArrayVec<i64, 5>) -> Result<()> {
29-
let mut cur = 0;
30-
let mut shift = 0;
27+
pub struct VlqIter<'a> {
28+
segment: std::slice::Iter<'a, u8>,
29+
cur: i64,
30+
shift: u32,
31+
}
32+
33+
impl<'a> Iterator for VlqIter<'a> {
34+
type Item = Result<i64>;
3135

32-
for c in segment {
33-
let enc = i64::from(B64[*c as usize]);
34-
let val = enc & 0b11111;
35-
let cont = enc >> 5;
36-
cur += val.checked_shl(shift).ok_or(Error::VlqOverflow)?;
37-
shift += 5;
36+
fn next(&mut self) -> Option<Self::Item> {
37+
loop {
38+
let c = self.segment.next();
39+
match c {
40+
Some(c) => {
41+
let enc = i64::from(B64[*c as usize]);
42+
let val = enc & 0b11111;
43+
let cont = enc >> 5;
44+
self.cur +=
45+
match val.checked_shl(self.shift).ok_or(Error::VlqOverflow) {
46+
Ok(v) => v,
47+
Err(e) => return Some(Err(e)),
48+
};
49+
self.shift += 5;
3850

39-
if cont == 0 {
40-
let sign = cur & 1;
41-
cur >>= 1;
42-
if sign != 0 {
43-
cur = -cur;
51+
if cont == 0 {
52+
let sign = self.cur & 1;
53+
self.cur >>= 1;
54+
if sign != 0 {
55+
self.cur = -self.cur;
56+
}
57+
let result = self.cur;
58+
self.cur = 0;
59+
self.shift = 0;
60+
return Some(Ok(result));
61+
}
62+
}
63+
None => {
64+
if self.cur != 0 || self.shift != 0 {
65+
return Some(Err(Error::VlqLeftover));
66+
} else {
67+
return None;
68+
}
69+
}
4470
}
45-
rv.push(cur);
46-
cur = 0;
47-
shift = 0;
4871
}
4972
}
73+
}
5074

51-
if cur != 0 || shift != 0 {
52-
Err(Error::VlqLeftover)
53-
} else if rv.is_empty() {
54-
Err(Error::VlqNoValues)
55-
} else {
56-
Ok(())
75+
pub fn decode<'a>(segment: &'a [u8]) -> VlqIter<'a> {
76+
VlqIter {
77+
segment: segment.iter(),
78+
cur: 0,
79+
shift: 0,
5780
}
5881
}
5982

0 commit comments

Comments
 (0)