diff --git a/Cargo.toml b/Cargo.toml index 94e369b..84d5eeb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,13 +15,13 @@ all = "deny" [dependencies] lsp-types = { version = "0", optional = true } serde = { version = "1.0", features = ["derive"], optional = true } -base64 = { version = "0.21", optional = true } -codespan-reporting = { version = "0.11", optional = true } -self-rust-tokenize = { version = "0.3", optional = true } +base64 = { version = "0.22", optional = true } +codespan-reporting = { version = "0.12", optional = true } +self-rust-tokenize = { version = "0", optional = true } [target.'cfg(target_family = "wasm")'.dependencies] wasm-bindgen = "0.2" -tsify = "0.4.5" +tsify = "0.5" [features] default = ["global-source-filesystem"] diff --git a/examples/source_map_creation.rs b/examples/source_map_creation.rs index 61d6f97..5251d16 100644 --- a/examples/source_map_creation.rs +++ b/examples/source_map_creation.rs @@ -26,7 +26,7 @@ fn main() { }; output.add_mapping(&base_span); output.push_str(chunk); - output.push(' '); + output.push_char(' '); const WORDS_PER_LINE: usize = 5; if idx % WORDS_PER_LINE + 1 == WORDS_PER_LINE { diff --git a/src/filesystem.rs b/src/filesystem.rs index 840f091..b8b5f43 100644 --- a/src/filesystem.rs +++ b/src/filesystem.rs @@ -9,47 +9,11 @@ use crate::{lines_columns_indexes::LineStarts, SourceId, SpanWithSource}; pub struct Source { pub path: PathBuf, pub content: String, + /// This is computed ahead of time for fast conversion for byte-indexes to line-column indexes + /// which is needed for source map generation and also printing code blocks in diagnostics pub(crate) line_starts: LineStarts, } -#[cfg(feature = "global-source-filesystem")] -pub mod global_store { - use super::*; - - pub struct GlobalStore; - - #[cfg(feature = "global-source-filesystem")] - static SOURCE_IDS_TO_FILES: std::sync::RwLock> = - std::sync::RwLock::new(MapFileStore { - sources: Vec::new(), - mappings: NoPathMap, - }); - - impl FileSystem for GlobalStore { - fn new_source_id_with_line_starts( - &mut self, - path: PathBuf, - content: String, - ) -> (SourceId, LineStarts) { - SOURCE_IDS_TO_FILES - .write() - .unwrap() - .new_source_id_with_line_starts(path, content) - } - - fn get_source_by_id FnOnce(&'a Source) -> T>( - &self, - source_id: SourceId, - f: F, - ) -> T { - SOURCE_IDS_TO_FILES - .read() - .unwrap() - .get_source_by_id(source_id, f) - } - } -} - #[derive(Default)] pub struct MapFileStore { sources: Vec, @@ -133,11 +97,10 @@ impl FileSystem for MapFileStore { (source_id, line_starts) } - fn get_source_by_id FnOnce(&'a Source) -> T>( - &self, - source_id: SourceId, - f: F, - ) -> T { + fn get_source_by_id(&self, source_id: SourceId, f: F) -> T + where + F: for<'a> FnOnce(&'a Source) -> T, + { f(&self.sources[source_id.0 as usize - 1]) } } diff --git a/src/lib.rs b/src/lib.rs index 23b2ca2..dda86d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,7 +36,7 @@ fn vlq_encode_integer_to_buffer(buf: &mut String, mut value: isize) { if value > 0 { clamped |= 32; } - buf.push(BASE64_ALPHABET[clamped as usize] as char); + buf.push_char(BASE64_ALPHABET[clamped as usize] as char); if value <= 0 { break; } @@ -150,7 +150,7 @@ impl SourceMapBuilder { } if let Some(false) = last_was_break { - mappings.push(','); + mappings.push_char(','); } let output_column = @@ -187,7 +187,7 @@ impl SourceMapBuilder { last_was_break = Some(false); } MappingOrBreak::Break => { - mappings.push(';'); + mappings.push_char(';'); last_was_break = Some(true); last_mapped_output_column = 0; } @@ -232,8 +232,8 @@ impl SourceMap { .enumerate() { if idx != 0 { - sources.push(','); - sources_content.push(','); + sources.push_char(','); + sources_content.push_char(','); } write!( sources, diff --git a/src/source_id.rs b/src/source_id.rs index 0b00024..956c1e6 100644 --- a/src/source_id.rs +++ b/src/source_id.rs @@ -18,6 +18,12 @@ impl SourceId { pub fn new(filesystem: &mut impl FileSystem, path: PathBuf, content: String) -> Self { filesystem.new_source_id(path, content) } + + /// Construct a `SourceId` from a custom `FileSystem` implementation + #[doc(hidden)] + pub fn new_from_u16(id: u16) -> Self { + Self(id) + } } #[cfg(feature = "self-rust-tokenize")] diff --git a/src/to_string.rs b/src/to_string.rs index 407e737..27d918b 100644 --- a/src/to_string.rs +++ b/src/to_string.rs @@ -5,13 +5,21 @@ use crate::{ /// A trait for defining behavior of adding content to a buffer. As well as register markers for source maps pub trait ToString { /// Append character - fn push(&mut self, chr: char); + fn push_u8(&mut self, chr: u8); + + /// Append character + fn push_char(&mut self, chr: char); /// Append a new line character fn push_new_line(&mut self); /// Use [ToString::push_str_contains_new_line] if `string` could contain new lines - fn push_str(&mut self, string: &str); + fn push_str(&mut self, string: &str) { + self.push_slice(string.as_bytes()) + } + + /// Use [ToString::push_str_contains_new_line] if `string` could contain new lines + fn push_slice(&mut self, slice: &[u8]); /// Used to push strings that may contain new lines fn push_str_contains_new_line(&mut self, string: &str); @@ -36,18 +44,26 @@ pub trait ToString { // TODO clarify calls impl ToString for String { - fn push(&mut self, chr: char) { + fn push_u8(&mut self, chr: u8) { + self.push(chr as char); + } + + fn push_char(&mut self, chr: char) { self.push(chr); } fn push_new_line(&mut self) { - self.push('\n'); + self.push_char('\n'); } fn push_str(&mut self, string: &str) { self.push_str(string) } + fn push_slice(&mut self, slice: &[u8]) { + self.push_str(str::from_utf8(slice).unwrap()) + } + fn push_str_contains_new_line(&mut self, string: &str) { self.push_str(string) } @@ -67,7 +83,13 @@ pub struct Writable { } impl ToString for Writable { - fn push(&mut self, chr: char) { + fn push_u8(&mut self, item: u8) { + self.length += 1; + self.since_new_line += 1; + self.writable.write_all(&[item]).unwrap(); + } + + fn push_char(&mut self, chr: char) { let mut buf = [0u8; 4]; // A char can be at most 4 bytes in UTF-8 let buf = chr.encode_utf8(&mut buf).as_bytes(); let char_size = chr.len_utf8(); @@ -78,7 +100,7 @@ impl ToString for Writable { fn push_new_line(&mut self) { self.length += 1; - self.writable.write_all(&[b'\n']).unwrap(); + self.writable.write_all(b"\n").unwrap(); } fn push_str(&mut self, string: &str) { @@ -87,6 +109,12 @@ impl ToString for Writable { self.writable.write_all(string.as_bytes()).unwrap(); } + fn push_slice(&mut self, slice: &[u8]) { + self.length += slice.len() as u32; + self.since_new_line += slice.len() as u32; + self.writable.write_all(slice).unwrap(); + } + fn push_str_contains_new_line(&mut self, slice: &str) { self.length += slice.len() as u32; self.writable.write_all(slice.as_bytes()).unwrap(); @@ -158,8 +186,16 @@ impl StringWithOptionalSourceMap { } impl ToString for StringWithOptionalSourceMap { - fn push(&mut self, chr: char) { - self.source.push(chr); + fn push_u8(&mut self, item: u8) { + self.source.push_u8(item); + if let Some(ref mut sm) = self.source_map { + sm.add_to_column(1); + } + self.since_new_line += 1; + } + + fn push_char(&mut self, chr: char) { + self.source.push_char(chr); if let Some(ref mut sm) = self.source_map { sm.add_to_column(chr.len_utf16()); } @@ -167,7 +203,7 @@ impl ToString for StringWithOptionalSourceMap { } fn push_new_line(&mut self) { - self.source.push('\n'); + self.source.push_char('\n'); if let Some(ref mut sm) = self.source_map { sm.add_new_line(); } @@ -182,6 +218,14 @@ impl ToString for StringWithOptionalSourceMap { self.since_new_line += slice.len() as u32; } + fn push_slice(&mut self, slice: &[u8]) { + self.source.push_slice(slice); + if let Some(ref mut sm) = self.source_map { + sm.add_to_column(slice.len()); + } + self.since_new_line += slice.len() as u32; + } + fn push_str_contains_new_line(&mut self, slice: &str) { self.source.push_str(slice); if let Some(ref mut sm) = self.source_map { @@ -201,7 +245,7 @@ impl ToString for StringWithOptionalSourceMap { fn should_halt(&self) -> bool { self.quit_after - .map_or(false, |quit_after| self.source.len() > quit_after) + .is_some_and(|quit_after| self.source.len() > quit_after) } fn characters_on_current_line(&self) -> u32 { @@ -230,18 +274,26 @@ impl Counter { } impl ToString for Counter { - fn push(&mut self, chr: char) { + fn push_u8(&mut self, _item: u8) { + self.acc += 1; + } + + fn push_char(&mut self, chr: char) { self.acc += chr.len_utf8(); } fn push_new_line(&mut self) { - self.push('\n'); + self.push_char('\n'); } fn push_str(&mut self, string: &str) { self.acc += string.len(); } + fn push_slice(&mut self, slice: &[u8]) { + self.acc += slice.len(); + } + fn push_str_contains_new_line(&mut self, string: &str) { self.acc += string.len(); } @@ -267,7 +319,7 @@ mod to_string_tests { fn serializer(t: &mut T) { t.push_str("Hello"); - t.push(' '); + t.push_char(' '); t.push_str("World"); }