Skip to content

Commit 18ae175

Browse files
committed
Prevent unnecessary allocation in PathBuf::set_extension.
It was allocating a new OsString that was immediately dropped after using it with set_file_name. Now it directly changes the extension in the original buffer, without touching the rest of the file name or allocating a temporary string.
1 parent 4a8c5b2 commit 18ae175

File tree

1 file changed

+15
-11
lines changed

1 file changed

+15
-11
lines changed

src/libstd/path.rs

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1363,20 +1363,24 @@ impl PathBuf {
13631363
}
13641364

13651365
fn _set_extension(&mut self, extension: &OsStr) -> bool {
1366-
if self.file_name().is_none() {
1367-
return false;
1368-
}
1369-
1370-
let mut stem = match self.file_stem() {
1371-
Some(stem) => stem.to_os_string(),
1372-
None => OsString::new(),
1366+
let file_stem = match self.file_stem() {
1367+
None => return false,
1368+
Some(f) => os_str_as_u8_slice(f),
13731369
};
13741370

1375-
if !os_str_as_u8_slice(extension).is_empty() {
1376-
stem.push(".");
1377-
stem.push(extension);
1371+
// truncate until right after the file stem
1372+
let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
1373+
let start = os_str_as_u8_slice(&self.inner).as_ptr() as usize;
1374+
let v = self.as_mut_vec();
1375+
v.truncate(end_file_stem.wrapping_sub(start));
1376+
1377+
// add the new extension, if any
1378+
let new = os_str_as_u8_slice(extension);
1379+
if !new.is_empty() {
1380+
v.reserve_exact(new.len() + 1);
1381+
v.push(b'.');
1382+
v.extend_from_slice(new);
13781383
}
1379-
self.set_file_name(&stem);
13801384

13811385
true
13821386
}

0 commit comments

Comments
 (0)