impl PathBuf::add_extension and Path::with_added_extension · model-checking/verify-rust-std@acbefbb (original) (raw)

`@@ -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>(&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>(&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:

`