diff --git a/src/helpers.rs b/src/helpers.rs index daffad3..56ceb37 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -1,7 +1,8 @@ use arrayvec::ArrayVec; +use core::fmt; use std::{ borrow::{BorrowMut, Cow}, - cell::{OnceCell, RefCell}, + cell::RefCell, rc::Rc, }; @@ -13,7 +14,7 @@ use crate::{ source::{Mapping, OriginalLocation}, vlq::decode, with_indices::WithIndices, - MapOptions, SourceMap, + Error, MapOptions, SourceMap, }; // Adding this type because sourceContentLine not happy @@ -115,87 +116,89 @@ pub struct GeneratedInfo { pub generated_column: u32, } -pub fn decode_mappings<'b, 'a: 'b>( - source_map: &'a SourceMap, -) -> impl Iterator + 'b { +pub fn decode_mappings( + source_map: &SourceMap, +) -> impl Iterator + '_ { SegmentIter::new(source_map.mappings()) } pub struct SegmentIter<'a> { - mapping_str: &'a str, + mapping_str: &'a [u8], generated_line: usize, generated_column: u32, source_index: u32, original_line: u32, original_column: u32, name_index: u32, - line: &'a str, nums: ArrayVec, - segment_cursor: usize, + tracing_index: usize, + current_index: usize, } impl<'a> SegmentIter<'a> { pub fn new(mapping_str: &'a str) -> Self { SegmentIter { - line: "", - mapping_str, + mapping_str: mapping_str.as_bytes(), source_index: 0, original_line: 1, original_column: 0, name_index: 0, - generated_line: 0, - segment_cursor: 0, + generated_line: 1, generated_column: 0, nums: ArrayVec::new(), + tracing_index: 0, + current_index: 0, } } - fn next_segment(&mut self) -> Option<&'a str> { - if self.line.is_empty() { - loop { - match self.next_line() { - Some(line) => { - self.generated_line += 1; - if line.is_empty() { - continue; - } - self.line = line; - self.generated_column = 0; - self.segment_cursor = 0; - break; + fn next_segment(&mut self) -> Option<&'a [u8]> { + let mapping_str_len = self.mapping_str.len(); + if self.current_index == mapping_str_len { + return None; + } + + loop { + match self.mapping_str[self.current_index] { + b',' => { + if self.tracing_index != self.current_index { + let segment = + &self.mapping_str[self.tracing_index..self.current_index]; + self.tracing_index = self.current_index; + return Some(segment); + } + self.current_index += 1; + self.tracing_index = self.current_index; + } + b';' => { + if self.tracing_index != self.current_index { + let segment = + &self.mapping_str[self.tracing_index..self.current_index]; + self.tracing_index = self.current_index; + return Some(segment); } - None => return None, + self.generated_line += 1; + self.generated_column = 0; + self.current_index += 1; + self.tracing_index = self.current_index; } + _ => match memchr::memchr2( + b',', + b';', + &self.mapping_str[self.current_index..], + ) { + Some(index) => self.current_index += index, + None => self.current_index = mapping_str_len, + }, } - } - - if let Some(i) = - memchr::memchr(b',', self.line[self.segment_cursor..].as_bytes()) - { - let cursor = self.segment_cursor; - self.segment_cursor = self.segment_cursor + i + 1; - Some(&self.line[cursor..cursor + i]) - } else { - let line = self.line; - self.line = ""; - Some(&line[self.segment_cursor..]) - } - } - fn next_line(&mut self) -> Option<&'a str> { - if self.mapping_str.is_empty() { - return None; - } - match memchr::memchr(b';', self.mapping_str.as_bytes()) { - Some(i) => { - let temp_str = self.mapping_str; - self.mapping_str = &self.mapping_str[i + 1..]; - Some(&temp_str[..i]) - } - None => { - let tem_str = self.mapping_str; - self.mapping_str = ""; - Some(tem_str) + if self.current_index == mapping_str_len { + if self.tracing_index != self.current_index { + let segment = + &self.mapping_str[self.tracing_index..self.current_index]; + return Some(segment); + } else { + return None; + } } } } @@ -208,29 +211,41 @@ impl<'a> Iterator for SegmentIter<'a> { match self.next_segment() { Some(segment) => { self.nums.clear(); - decode(segment, &mut self.nums).unwrap(); - self.generated_column = - (i64::from(self.generated_column) + self.nums[0]) as u32; + let mut vlq = decode(segment); + self.generated_column = (i64::from(self.generated_column) + + vlq + .next() + .unwrap_or_else(|| Err(Error::VlqNoValues)) + .unwrap()) as u32; let mut src = None; let mut name = None; - if self.nums.len() > 1 { - if self.nums.len() != 4 && self.nums.len() != 5 { - panic!("got {} segments, expected 4 or 5", self.nums.len()); - } + if let Some(source_index) = vlq.next() { + // if self.nums.len() != 4 && self.nums.len() != 5 { + // panic!("got {} segments, expected 4 or 5", self.nums.len()); + // } self.source_index = - (i64::from(self.source_index) + self.nums[1]) as u32; + (i64::from(self.source_index) + source_index.unwrap()) as u32; src = Some(self.source_index); - self.original_line = - (i64::from(self.original_line) + self.nums[2]) as u32; - self.original_column = - (i64::from(self.original_column) + self.nums[3]) as u32; - - if self.nums.len() > 4 { - self.name_index = - (i64::from(self.name_index) + self.nums[4]) as u32; - name = Some(self.name_index); + self.original_line = (i64::from(self.original_line) + + vlq + .next() + .unwrap_or_else(|| Err(Error::VlqNoValues)) + .unwrap()) as u32; + self.original_column = (i64::from(self.original_column) + + vlq + .next() + .unwrap_or_else(|| Err(Error::VlqNoValues)) + .unwrap()) as u32; + + match vlq.next() { + Some(name_index) => { + self.name_index = + (i64::from(self.name_index) + name_index.unwrap()) as u32; + name = Some(self.name_index) + } + None => (), } } @@ -531,7 +546,7 @@ fn stream_chunks_of_source_map_full<'a>( let mut current_mapping = mappings_iter.next(); for (current_generated_index, c) in source.char_indices() { - if let Some(mapping) = current_mapping.take() { + if let Some(mapping) = ¤t_mapping { if mapping.generated_line == current_generated_line && mapping.generated_column == current_generated_column { @@ -553,8 +568,6 @@ fn stream_chunks_of_source_map_full<'a>( tracking_mapping_original = mapping.original; current_mapping = mappings_iter.next(); - } else { - current_mapping = Some(mapping); } } @@ -732,29 +745,7 @@ fn stream_chunks_of_source_map_lines_full<'a>( #[derive(Debug)] struct SourceMapLineData<'a> { pub mappings_data: Vec, - pub chunks: Vec>, -} - -#[derive(Debug)] -struct SourceMapLineChunk<'a> { - content: Cow<'a, str>, - cached: OnceCell>>, -} - -impl<'a> SourceMapLineChunk<'a> { - pub fn new(content: Cow<'a, str>) -> Self { - Self { - content, - cached: OnceCell::new(), - } - } - - pub fn substring(&self, start_index: usize, end_index: usize) -> &str { - let cached = self - .cached - .get_or_init(|| WithIndices::new(self.content.clone())); - cached.substring(start_index, end_index) - } + pub chunks: Vec>>, } type InnerSourceIndexValueMapping<'a> = @@ -1203,7 +1194,7 @@ pub fn stream_chunks_of_combined_source_map<'a>( .unwrap_or(-1), ); // SAFETY: final_source is false - let chunk = SourceMapLineChunk::new(chunk.unwrap()); + let chunk = WithIndices::new(chunk.unwrap()); data.chunks.push(chunk); }, &mut |i, source, source_content| { diff --git a/src/vlq.rs b/src/vlq.rs index 5d01283..7373a9b 100644 --- a/src/vlq.rs +++ b/src/vlq.rs @@ -24,46 +24,64 @@ const B64: [i8; 256] = [ -1, -1, -1, -1, -1, -1, ]; -/// Parses a VLQ segment into a pre-allocated `Vec` instead of returning a new allocation. -pub fn decode(segment: &str, rv: &mut ArrayVec) -> Result<()> { - let mut cur = 0; - let mut shift = 0; +pub struct VlqIter<'a> { + segment: std::slice::Iter<'a, u8>, + cur: i64, + shift: u32, +} + +impl<'a> Iterator for VlqIter<'a> { + type Item = Result; - for c in segment.bytes() { - let enc = i64::from(B64[c as usize]); - let val = enc & 0b11111; - let cont = enc >> 5; - cur += val.checked_shl(shift).ok_or(Error::VlqOverflow)?; - shift += 5; + fn next(&mut self) -> Option { + loop { + let c = self.segment.next(); + match c { + Some(c) => { + let enc = i64::from(B64[*c as usize]); + let val = enc & 0b11111; + let cont = enc >> 5; + self.cur += + match val.checked_shl(self.shift).ok_or(Error::VlqOverflow) { + Ok(v) => v, + Err(e) => return Some(Err(e)), + }; + self.shift += 5; - if cont == 0 { - let sign = cur & 1; - cur >>= 1; - if sign != 0 { - cur = -cur; + if cont == 0 { + let sign = self.cur & 1; + self.cur >>= 1; + if sign != 0 { + self.cur = -self.cur; + } + let result = self.cur; + self.cur = 0; + self.shift = 0; + return Some(Ok(result)); + } + } + None => { + if self.cur != 0 || self.shift != 0 { + return Some(Err(Error::VlqLeftover)); + } else { + return None; + } + } } - rv.push(cur); - cur = 0; - shift = 0; } } +} - if cur != 0 || shift != 0 { - Err(Error::VlqLeftover) - } else if rv.is_empty() { - Err(Error::VlqNoValues) - } else { - Ok(()) +pub fn decode<'a>(segment: &'a [u8]) -> VlqIter<'a> { + VlqIter { + segment: segment.iter(), + cur: 0, + shift: 0, } } -#[inline(always)] -pub fn encode(out: &mut Vec, a: u32, b: u32) { - let mut num = if a >= b { - (a - b) << 1 - } else { - ((b - a) << 1) + 1 - }; +fn encode_vlq(out: &mut String, num: i64) { + let mut num = if num < 0 { ((-num) << 1) + 1 } else { num << 1 }; loop { let mut digit = num & 0b11111; @@ -71,9 +89,13 @@ pub fn encode(out: &mut Vec, a: u32, b: u32) { if num > 0 { digit |= 1 << 5; } - out.push(B64_CHARS[digit as usize]); + out.push(B64_CHARS[digit as usize] as char); if num == 0 { break; } } } + +pub fn encode(out: &mut String, a: u32, b: u32) { + encode_vlq(out, i64::from(a) - i64::from(b)) +}