Skip to content

Commit 87149e8

Browse files
committed
impl add_extension for PathBuf
Signed-off-by: tison <wander4096@gmail.com>
1 parent 4e431fa commit 87149e8

File tree

1 file changed

+70
-0
lines changed

1 file changed

+70
-0
lines changed

library/std/src/path.rs

+70
Original file line numberDiff line numberDiff line change
@@ -1498,6 +1498,76 @@ impl PathBuf {
14981498
true
14991499
}
15001500

1501+
/// Append [`self.extension`] with `extension`.
1502+
///
1503+
/// Returns `false` and does nothing if [`self.file_name`] is [`None`],
1504+
/// returns `true` and updates the extension otherwise.
1505+
///
1506+
/// If [`self.extension`] is [`None`], the extension is added; otherwise
1507+
/// it is appended.
1508+
///
1509+
/// # Caveats
1510+
///
1511+
/// The appended `extension` may contain dots and will be used in its entirety,
1512+
/// but only the part after the final dot will be reflected in
1513+
/// [`self.extension`].
1514+
///
1515+
/// See the examples below.
1516+
///
1517+
/// [`self.file_name`]: Path::file_name
1518+
/// [`self.extension`]: Path::extension
1519+
///
1520+
/// # Examples
1521+
///
1522+
/// ```
1523+
/// use std::path::{Path, PathBuf};
1524+
///
1525+
/// let mut p = PathBuf::from("/feel/the");
1526+
///
1527+
/// p.add_extension("formatted");
1528+
/// assert_eq!(Path::new("/feel/the.formatted"), p.as_path());
1529+
///
1530+
/// p.add_extension("dark.side");
1531+
/// assert_eq!(Path::new("/feel/the.formatted.dark.side"), p.as_path());
1532+
///
1533+
/// p.set_extension("cookie");
1534+
/// assert_eq!(Path::new("/feel/the.formatted.dark.cookie"), p.as_path());
1535+
///
1536+
/// p.set_extension("");
1537+
/// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());
1538+
///
1539+
/// p.add_extension("");
1540+
/// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());
1541+
/// ```
1542+
#[stable(feature = "rust1", since = "1.0.0")]
1543+
pub fn add_extension<S: AsRef<OsStr>>(&mut self, extension: S) -> bool {
1544+
self._add_extension(extension.as_ref())
1545+
}
1546+
1547+
fn _add_extension(&mut self, extension: &OsStr) -> bool {
1548+
let file_name = match self.file_name() {
1549+
None => return false,
1550+
Some(f) => f.as_encoded_bytes(),
1551+
};
1552+
1553+
let new = extension.as_encoded_bytes();
1554+
if !new.is_empty() {
1555+
// truncate until right after the file name
1556+
// this is necessary for trimming the trailing slash
1557+
let end_file_name = file_name[file_name.len()..].as_ptr().addr();
1558+
let start = self.inner.as_encoded_bytes().as_ptr().addr();
1559+
let v = self.as_mut_vec();
1560+
v.truncate(end_file_name.wrapping_sub(start));
1561+
1562+
// append the new extension
1563+
v.reserve_exact(new.len() + 1);
1564+
v.push(b'.');
1565+
v.extend_from_slice(new);
1566+
}
1567+
1568+
true
1569+
}
1570+
15011571
/// Yields a mutable reference to the underlying [`OsString`] instance.
15021572
///
15031573
/// # Examples

0 commit comments

Comments
 (0)