about summary refs log tree commit diff
path: root/src/libstd/path.rs
diff options
context:
space:
mode:
authorMara Bos <m-ou.se@m-ou.se>2019-10-23 21:00:04 +0200
committerMara Bos <m-ou.se@m-ou.se>2019-10-23 21:21:25 +0200
commit18ae175d60039dfe2d2454e8e8099d3b08039862 (patch)
tree068d7ce776db3662f0172ce79e7110c8692d40a6 /src/libstd/path.rs
parent4a8c5b20c7772bc5342b83d4b0696ea216ef75a7 (diff)
downloadrust-18ae175d60039dfe2d2454e8e8099d3b08039862.tar.gz
rust-18ae175d60039dfe2d2454e8e8099d3b08039862.zip
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.
Diffstat (limited to 'src/libstd/path.rs')
-rw-r--r--src/libstd/path.rs26
1 files changed, 15 insertions, 11 deletions
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index ca81044ee85..6d6bc760649 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1363,20 +1363,24 @@ impl PathBuf {
     }
 
     fn _set_extension(&mut self, extension: &OsStr) -> bool {
-        if self.file_name().is_none() {
-            return false;
-        }
-
-        let mut stem = match self.file_stem() {
-            Some(stem) => stem.to_os_string(),
-            None => OsString::new(),
+        let file_stem = match self.file_stem() {
+            None => return false,
+            Some(f) => os_str_as_u8_slice(f),
         };
 
-        if !os_str_as_u8_slice(extension).is_empty() {
-            stem.push(".");
-            stem.push(extension);
+        // truncate until right after the file stem
+        let end_file_stem = file_stem[file_stem.len()..].as_ptr() as usize;
+        let start = os_str_as_u8_slice(&self.inner).as_ptr() as usize;
+        let v = self.as_mut_vec();
+        v.truncate(end_file_stem.wrapping_sub(start));
+
+        // add the new extension, if any
+        let new = os_str_as_u8_slice(extension);
+        if !new.is_empty() {
+            v.reserve_exact(new.len() + 1);
+            v.push(b'.');
+            v.extend_from_slice(new);
         }
-        self.set_file_name(&stem);
 
         true
     }