summaryrefslogtreecommitdiffstats
path: root/library/std/src/path.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/std/src/path.rs')
-rw-r--r--library/std/src/path.rs40
1 files changed, 29 insertions, 11 deletions
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 28cd3c4e4..5842c096f 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1158,12 +1158,12 @@ impl FusedIterator for Ancestors<'_> {}
/// Which method works best depends on what kind of situation you're in.
#[cfg_attr(not(test), rustc_diagnostic_item = "PathBuf")]
#[stable(feature = "rust1", since = "1.0.0")]
-// FIXME:
// `PathBuf::as_mut_vec` current implementation relies
// on `PathBuf` being layout-compatible with `Vec<u8>`.
-// When attribute privacy is implemented, `PathBuf` should be annotated as `#[repr(transparent)]`.
-// Anyway, `PathBuf` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
+// However, `PathBuf` layout is considered an implementation detail and must not be relied upon. We
+// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
+// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
+#[cfg_attr(not(doc), repr(transparent))]
pub struct PathBuf {
inner: OsString,
}
@@ -1983,12 +1983,12 @@ impl AsRef<OsStr> for PathBuf {
/// ```
#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
#[stable(feature = "rust1", since = "1.0.0")]
-// FIXME:
// `Path::new` current implementation relies
// on `Path` being layout-compatible with `OsStr`.
-// When attribute privacy is implemented, `Path` should be annotated as `#[repr(transparent)]`.
-// Anyway, `Path` representation and layout are considered implementation detail, are
-// not documented and must not be relied upon.
+// However, `Path` layout is considered an implementation detail and must not be relied upon. We
+// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
+// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
+#[cfg_attr(not(doc), repr(transparent))]
pub struct Path {
inner: OsStr,
}
@@ -2608,9 +2608,27 @@ impl Path {
}
fn _with_extension(&self, extension: &OsStr) -> PathBuf {
- let mut buf = self.to_path_buf();
- buf.set_extension(extension);
- buf
+ let self_len = self.as_os_str().len();
+ let self_bytes = self.as_os_str().as_os_str_bytes();
+
+ let (new_capacity, slice_to_copy) = match self.extension() {
+ None => {
+ // Enough capacity for the extension and the dot
+ let capacity = self_len + extension.len() + 1;
+ let whole_path = self_bytes.iter();
+ (capacity, whole_path)
+ }
+ Some(previous_extension) => {
+ let capacity = self_len + extension.len() - previous_extension.len();
+ let path_till_dot = self_bytes[..self_len - previous_extension.len()].iter();
+ (capacity, path_till_dot)
+ }
+ };
+
+ let mut new_path = PathBuf::with_capacity(new_capacity);
+ new_path.as_mut_vec().extend(slice_to_copy);
+ new_path.set_extension(extension);
+ new_path
}
/// Produces an iterator over the [`Component`]s of the path.