@@ -1519,6 +1519,77 @@ impl PathBuf {
1519
1519
true
1520
1520
}
1521
1521
1522
+ /// Append [`self.extension`] with `extension`.
1523
+ ///
1524
+ /// Returns `false` and does nothing if [`self.file_name`] is [`None`],
1525
+ /// returns `true` and updates the extension otherwise.
1526
+ ///
1527
+ /// If [`self.extension`] is [`None`], the extension is added; otherwise
1528
+ /// it is appended.
1529
+ ///
1530
+ /// # Caveats
1531
+ ///
1532
+ /// The appended `extension` may contain dots and will be used in its entirety,
1533
+ /// but only the part after the final dot will be reflected in
1534
+ /// [`self.extension`].
1535
+ ///
1536
+ /// See the examples below.
1537
+ ///
1538
+ /// [`self.file_name`]: Path::file_name
1539
+ /// [`self.extension`]: Path::extension
1540
+ ///
1541
+ /// # Examples
1542
+ ///
1543
+ /// ```
1544
+ /// #![feature(path_add_extension)]
1545
+ ///
1546
+ /// use std::path::{Path, PathBuf};
1547
+ ///
1548
+ /// let mut p = PathBuf::from("/feel/the");
1549
+ ///
1550
+ /// p.add_extension("formatted");
1551
+ /// assert_eq!(Path::new("/feel/the.formatted"), p.as_path());
1552
+ ///
1553
+ /// p.add_extension("dark.side");
1554
+ /// assert_eq!(Path::new("/feel/the.formatted.dark.side"), p.as_path());
1555
+ ///
1556
+ /// p.set_extension("cookie");
1557
+ /// assert_eq!(Path::new("/feel/the.formatted.dark.cookie"), p.as_path());
1558
+ ///
1559
+ /// p.set_extension("");
1560
+ /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());
1561
+ ///
1562
+ /// p.add_extension("");
1563
+ /// assert_eq!(Path::new("/feel/the.formatted.dark"), p.as_path());
1564
+ /// ```
1565
+ #[ unstable( feature = "path_add_extension" , issue = "127292" ) ]
1566
+ pub fn add_extension < S : AsRef < OsStr > > ( & mut self , extension : S ) -> bool {
1567
+ self . _add_extension ( extension. as_ref ( ) )
1568
+ }
1569
+
1570
+ fn _add_extension ( & mut self , extension : & OsStr ) -> bool {
1571
+ let file_name = match self . file_name ( ) {
1572
+ None => return false ,
1573
+ Some ( f) => f. as_encoded_bytes ( ) ,
1574
+ } ;
1575
+
1576
+ let new = extension;
1577
+ if !new. is_empty ( ) {
1578
+ // truncate until right after the file name
1579
+ // this is necessary for trimming the trailing slash
1580
+ let end_file_name = file_name[ file_name. len ( ) ..] . as_ptr ( ) . addr ( ) ;
1581
+ let start = self . inner . as_encoded_bytes ( ) . as_ptr ( ) . addr ( ) ;
1582
+ self . inner . truncate ( end_file_name. wrapping_sub ( start) ) ;
1583
+
1584
+ // append the new extension
1585
+ self . inner . reserve_exact ( new. len ( ) + 1 ) ;
1586
+ self . inner . push ( OsStr :: new ( "." ) ) ;
1587
+ self . inner . push ( new) ;
1588
+ }
1589
+
1590
+ true
1591
+ }
1592
+
1522
1593
/// Yields a mutable reference to the underlying [`OsString`] instance.
1523
1594
///
1524
1595
/// # Examples
@@ -2656,6 +2727,32 @@ impl Path {
2656
2727
new_path
2657
2728
}
2658
2729
2730
+ /// Creates an owned [`PathBuf`] like `self` but with an extra extension.
2731
+ ///
2732
+ /// See [`PathBuf::add_extension`] for more details.
2733
+ ///
2734
+ /// # Examples
2735
+ ///
2736
+ /// ```
2737
+ /// #![feature(path_add_extension)]
2738
+ ///
2739
+ /// use std::path::{Path, PathBuf};
2740
+ ///
2741
+ /// let path = Path::new("foo.rs");
2742
+ /// assert_eq!(path.with_added_extension("txt"), PathBuf::from("foo.rs.txt"));
2743
+ ///
2744
+ /// let path = Path::new("foo.tar.gz");
2745
+ /// assert_eq!(path.with_added_extension(""), PathBuf::from("foo.tar.gz"));
2746
+ /// assert_eq!(path.with_added_extension("xz"), PathBuf::from("foo.tar.gz.xz"));
2747
+ /// assert_eq!(path.with_added_extension("").with_added_extension("txt"), PathBuf::from("foo.tar.gz.txt"));
2748
+ /// ```
2749
+ #[ unstable( feature = "path_add_extension" , issue = "127292" ) ]
2750
+ pub fn with_added_extension < S : AsRef < OsStr > > ( & self , extension : S ) -> PathBuf {
2751
+ let mut new_path = self . to_path_buf ( ) ;
2752
+ new_path. add_extension ( extension) ;
2753
+ new_path
2754
+ }
2755
+
2659
2756
/// Produces an iterator over the [`Component`]s of the path.
2660
2757
///
2661
2758
/// When parsing the path, there is a small amount of normalization:
0 commit comments