Skip to content

Commit 10e2b0c

Browse files
committed
Make ChangedContent possibly borrow its contents to avoid unnecessary allocations
1 parent fbf0e86 commit 10e2b0c

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

crates/node/src/lib.rs

+13-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::borrow::Cow;
12
use std::ops::Deref;
23
use std::sync::{atomic::AtomicBool, Mutex};
34

@@ -37,11 +38,11 @@ pub struct GlobEntry {
3738
pub pattern: String,
3839
}
3940

40-
impl From<ChangedContent> for tailwindcss_oxide::ChangedContent {
41+
impl<'a> From<ChangedContent> for tailwindcss_oxide::ChangedContent<'a> {
4142
fn from(changed_content: ChangedContent) -> Self {
4243
Self {
43-
file: changed_content.file.map(Into::into),
44-
content: changed_content.content,
44+
file: changed_content.file.map(Into::into).map(Cow::Owned),
45+
content: changed_content.content.map(Cow::Owned),
4546
}
4647
}
4748
}
@@ -109,9 +110,13 @@ impl Scanner {
109110

110111
#[napi]
111112
pub fn scan_files(&mut self, input: Vec<ChangedContent>) -> Vec<String> {
112-
self
113-
.scanner
114-
.scan_content(input.into_iter().map(Into::into).collect())
113+
self.scanner.scan_content(
114+
input
115+
.into_iter()
116+
.map(Into::into)
117+
.collect::<Vec<_>>()
118+
.as_slice(),
119+
)
115120
}
116121

117122
#[napi]
@@ -224,8 +229,8 @@ pub fn tw_on_before_parse(handle: &mut OnBeforeParse) -> Result<()> {
224229

225230
let mut scanner = tailwindcss_oxide::Scanner::new(None);
226231

227-
let candidates = scanner.scan_content(vec![tailwindcss_oxide::ChangedContent {
228-
content: Some(source_code.to_string()),
232+
let candidates = scanner.scan_content(&[tailwindcss_oxide::ChangedContent {
233+
content: Some(source_code),
229234
file: None,
230235
}]);
231236

crates/oxide/src/lib.rs

+16-15
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use glob_match::glob_match;
1010
use paths::Path;
1111
use rayon::prelude::*;
1212
use scanner::allowed_paths::read_dir;
13+
use std::borrow::Cow;
1314
use std::fs;
1415
use std::path::PathBuf;
1516
use std::sync;
@@ -40,9 +41,9 @@ fn init_tracing() {
4041
}
4142

4243
#[derive(Debug, Clone)]
43-
pub struct ChangedContent {
44-
pub file: Option<PathBuf>,
45-
pub content: Option<String>,
44+
pub struct ChangedContent<'a> {
45+
pub file: Option<Cow<'a, PathBuf>>,
46+
pub content: Option<Cow<'a, str>>,
4647
}
4748

4849
#[derive(Debug, Clone)]
@@ -111,7 +112,7 @@ impl Scanner {
111112
}
112113

113114
#[tracing::instrument(skip_all)]
114-
pub fn scan_content(&mut self, changed_content: Vec<ChangedContent>) -> Vec<String> {
115+
pub fn scan_content<'a>(&mut self, changed_content: &[ChangedContent<'a>]) -> Vec<String> {
115116
self.prepare();
116117
let candidates = parse_all_blobs(read_all_files(changed_content));
117118

@@ -128,13 +129,13 @@ impl Scanner {
128129
}
129130

130131
#[tracing::instrument(skip_all)]
131-
pub fn get_candidates_with_positions(
132+
pub fn get_candidates_with_positions<'a>(
132133
&mut self,
133-
changed_content: ChangedContent,
134+
changed_content: ChangedContent<'a>,
134135
) -> Vec<(String, usize)> {
135136
self.prepare();
136137

137-
let content = read_changed_content(changed_content).unwrap_or_default();
138+
let content = read_changed_content(&changed_content).unwrap_or_default();
138139
let extractor = Extractor::with_positions(&content[..], Default::default());
139140

140141
let candidates: Vec<(String, usize)> = extractor
@@ -198,14 +199,14 @@ impl Scanner {
198199

199200
if should_scan_file {
200201
changed_content.push(ChangedContent {
201-
file: Some(path.clone()),
202+
file: Some(Cow::Borrowed(path)),
202203
content: None,
203204
});
204205
}
205206
}
206207

207208
if !changed_content.is_empty() {
208-
let candidates = parse_all_blobs(read_all_files(changed_content));
209+
let candidates = parse_all_blobs(read_all_files(changed_content.as_slice()));
209210
self.candidates.par_extend(candidates);
210211
}
211212
}
@@ -426,16 +427,16 @@ impl Scanner {
426427
}
427428
}
428429

429-
fn read_changed_content(c: ChangedContent) -> Option<Vec<u8>> {
430-
if let Some(content) = c.content {
431-
return Some(content.into_bytes());
430+
fn read_changed_content<'a>(c: &ChangedContent<'a>) -> Option<Vec<u8>> {
431+
if let Some(content) = &c.content {
432+
return Some(content.as_bytes().to_vec());
432433
}
433434

434-
let Some(file) = c.file else {
435+
let Some(file) = &c.file else {
435436
return Default::default();
436437
};
437438

438-
let Ok(content) = std::fs::read(&file).map_err(|e| {
439+
let Ok(content) = std::fs::read(file.as_ref()).map_err(|e| {
439440
event!(tracing::Level::ERROR, "Failed to read file: {:?}", e);
440441
e
441442
}) else {
@@ -460,7 +461,7 @@ fn read_changed_content(c: ChangedContent) -> Option<Vec<u8>> {
460461
}
461462

462463
#[tracing::instrument(skip_all)]
463-
fn read_all_files(changed_content: Vec<ChangedContent>) -> Vec<Vec<u8>> {
464+
fn read_all_files<'a>(changed_content: &[ChangedContent<'a>]) -> Vec<Vec<u8>> {
464465
event!(
465466
tracing::Level::INFO,
466467
"Reading {:?} file(s)",

0 commit comments

Comments
 (0)