Add more from the std

This commit is contained in:
2026-03-19 10:04:21 +01:00
parent 9b8afd2c5c
commit fc3a04a20e
49 changed files with 5497 additions and 424 deletions

View File

@@ -92,8 +92,8 @@ use crate::iter::FusedIterator;
use crate::ops::{self, Deref};
use crate::rc::Rc;
use crate::str::FromStr;
use alloc_crate::sync::Arc;
use crate::sys::path::{HAS_PREFIXES, MAIN_SEP_STR, is_sep_byte, is_verbatim_sep, parse_prefix};
use crate::sync::Arc;
use crate::sys::path::{HAS_PREFIXES, is_sep_byte, is_verbatim_sep, parse_prefix};
use crate::{cmp, fmt, fs, io, sys};
////////////////////////////////////////////////////////////////////////////////
@@ -266,22 +266,33 @@ impl<'a> Prefix<'a> {
/// ```
#[must_use]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_separator(c: char) -> bool {
#[rustc_const_unstable(feature = "const_path_separators", issue = "153106")]
pub const fn is_separator(c: char) -> bool {
c.is_ascii() && is_sep_byte(c as u8)
}
/// The primary separator of path components for the current platform.
///
/// For example, `/` on Unix and `\` on Windows.
/// All path separators recognized on the current platform, represented as [`char`]s; for example,
/// this is `&['/'][..]` on Unix and `&['\\', '/'][..]` on Windows. The [primary
/// separator](MAIN_SEPARATOR) is always element 0 of the slice.
#[unstable(feature = "const_path_separators", issue = "153106")]
pub const SEPARATORS: &[char] = crate::sys::path::SEPARATORS;
/// All path separators recognized on the current platform, represented as [`&str`]s; for example,
/// this is `&["/"][..]` on Unix and `&["\\", "/"][..]` on Windows. The [primary
/// separator](MAIN_SEPARATOR_STR) is always element 0 of the slice.
#[unstable(feature = "const_path_separators", issue = "153106")]
pub const SEPARATORS_STR: &[&str] = crate::sys::path::SEPARATORS_STR;
/// The primary separator of path components for the current platform, represented as a [`char`];
/// for example, this is `'/'` on Unix and `'\\'` on Windows.
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "path_main_separator")]
pub const MAIN_SEPARATOR: char = crate::sys::path::MAIN_SEP;
pub const MAIN_SEPARATOR: char = SEPARATORS[0];
/// The primary separator of path components for the current platform.
///
/// For example, `/` on Unix and `\` on Windows.
/// The primary separator of path components for the current platform, represented as a [`&str`];
/// for example, this is `"/"` on Unix and `"\\"` on Windows.
#[stable(feature = "main_separator_str", since = "1.68.0")]
pub const MAIN_SEPARATOR_STR: &str = crate::sys::path::MAIN_SEP_STR;
pub const MAIN_SEPARATOR_STR: &str = SEPARATORS_STR[0];
////////////////////////////////////////////////////////////////////////////////
// Misc helpers
@@ -562,7 +573,7 @@ impl<'a> Component<'a> {
pub fn as_os_str(self) -> &'a OsStr {
match self {
Component::Prefix(p) => p.as_os_str(),
Component::RootDir => OsStr::new(MAIN_SEP_STR),
Component::RootDir => OsStr::new(MAIN_SEPARATOR_STR),
Component::CurDir => OsStr::new("."),
Component::ParentDir => OsStr::new(".."),
Component::Normal(path) => path,
@@ -1379,7 +1390,7 @@ impl PathBuf {
for c in buf {
if need_sep && c != Component::RootDir {
res.push(MAIN_SEP_STR);
res.push(MAIN_SEPARATOR_STR);
}
res.push(c.as_os_str());
@@ -1402,7 +1413,7 @@ impl PathBuf {
// `path` is a pure relative path
} else if need_sep {
self.inner.push(MAIN_SEP_STR);
self.inner.push(MAIN_SEPARATOR_STR);
}
self.inner.push(path);
@@ -3240,73 +3251,101 @@ impl Path {
self
}
// /// Queries the file system to get information about a file, directory, etc.
// ///
// /// This function will traverse symbolic links to query information about the
// /// destination file.
// ///
// /// This is an alias to [`fs::metadata`].
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// ///
// /// let path = Path::new("/Minas/tirith");
// /// let metadata = path.metadata().expect("metadata call failed");
// /// println!("{:?}", metadata.file_type());
// /// ```
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[inline]
// pub fn metadata(&self) -> io::Result<fs::Metadata> {
// fs::metadata(self)
// }
/// Queries the file system to get information about a file, directory, etc.
///
/// This function will traverse symbolic links to query information about the
/// destination file.
///
/// This is an alias to [`fs::metadata`].
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
///
/// let path = Path::new("/Minas/tirith");
/// let metadata = path.metadata().expect("metadata call failed");
/// println!("{:?}", metadata.file_type());
/// ```
#[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn metadata(&self) -> io::Result<fs::Metadata> {
fs::metadata(self)
}
// /// Queries the metadata about a file without following symlinks.
// ///
// /// This is an alias to [`fs::symlink_metadata`].
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// ///
// /// let path = Path::new("/Minas/tirith");
// /// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
// /// println!("{:?}", metadata.file_type());
// /// ```
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[inline]
// pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
// fs::symlink_metadata(self)
// }
/// Queries the metadata about a file without following symlinks.
///
/// This is an alias to [`fs::symlink_metadata`].
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
///
/// let path = Path::new("/Minas/tirith");
/// let metadata = path.symlink_metadata().expect("symlink_metadata call failed");
/// println!("{:?}", metadata.file_type());
/// ```
#[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn symlink_metadata(&self) -> io::Result<fs::Metadata> {
fs::symlink_metadata(self)
}
// /// Returns the canonical, absolute form of the path with all intermediate
// /// components normalized and symbolic links resolved.
// ///
// /// This is an alias to [`fs::canonicalize`].
// ///
// /// # Errors
// ///
// /// This method will return an error in the following situations, but is not
// /// limited to just these cases:
// ///
// /// * `path` does not exist.
// /// * A non-final component in path is not a directory.
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::{Path, PathBuf};
// ///
// /// let path = Path::new("/foo/test/../test/bar.rs");
// /// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
// /// ```
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[inline]
// pub fn canonicalize(&self) -> io::Result<PathBuf> {
// fs::canonicalize(self)
// }
/// Returns the canonical, absolute form of the path with all intermediate
/// components normalized and symbolic links resolved.
///
/// This is an alias to [`fs::canonicalize`].
///
/// # Errors
///
/// This method will return an error in the following situations, but is not
/// limited to just these cases:
///
/// * `path` does not exist.
/// * A non-final component in path is not a directory.
///
/// # Examples
///
/// ```no_run
/// use std::path::{Path, PathBuf};
///
/// let path = Path::new("/foo/test/../test/bar.rs");
/// assert_eq!(path.canonicalize().unwrap(), PathBuf::from("/foo/test/bar.rs"));
/// ```
#[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn canonicalize(&self) -> io::Result<PathBuf> {
fs::canonicalize(self)
}
/// Makes the path absolute without accessing the filesystem.
///
/// This is an alias to [`path::absolute`](absolute).
///
/// # Errors
///
/// This function may return an error in the following situations:
///
/// * If the path is syntactically invalid; in particular, if it is empty.
/// * If getting the [current directory][crate::env::current_dir] fails.
///
/// # Examples
///
/// ```no_run
/// #![feature(path_absolute_method)]
/// use std::path::Path;
///
/// let path = Path::new("foo/./bar");
/// let absolute = path.absolute()?;
/// assert!(absolute.is_absolute());
/// # Ok::<(), std::io::Error>(())
/// ```
#[unstable(feature = "path_absolute_method", issue = "153328")]
#[inline]
pub fn absolute(&self) -> io::Result<PathBuf> {
absolute(self)
}
/// Normalize a path, including `..` without traversing the filesystem.
///
@@ -3369,206 +3408,206 @@ impl Path {
Ok(lexical)
}
// /// Reads a symbolic link, returning the file that the link points to.
// ///
// /// This is an alias to [`fs::read_link`].
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// ///
// /// let path = Path::new("/laputa/sky_castle.rs");
// /// let path_link = path.read_link().expect("read_link call failed");
// /// ```
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[inline]
// pub fn read_link(&self) -> io::Result<PathBuf> {
// fs::read_link(self)
// }
/// Reads a symbolic link, returning the file that the link points to.
///
/// This is an alias to [`fs::read_link`].
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
///
/// let path = Path::new("/laputa/sky_castle.rs");
/// let path_link = path.read_link().expect("read_link call failed");
/// ```
#[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn read_link(&self) -> io::Result<PathBuf> {
fs::read_link(self)
}
// /// Returns an iterator over the entries within a directory.
// ///
// /// The iterator will yield instances of <code>[io::Result]<[fs::DirEntry]></code>. New
// /// errors may be encountered after an iterator is initially constructed.
// ///
// /// This is an alias to [`fs::read_dir`].
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// ///
// /// let path = Path::new("/laputa");
// /// for entry in path.read_dir().expect("read_dir call failed") {
// /// if let Ok(entry) = entry {
// /// println!("{:?}", entry.path());
// /// }
// /// }
// /// ```
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[inline]
// pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
// fs::read_dir(self)
// }
/// Returns an iterator over the entries within a directory.
///
/// The iterator will yield instances of <code>[io::Result]<[fs::DirEntry]></code>. New
/// errors may be encountered after an iterator is initially constructed.
///
/// This is an alias to [`fs::read_dir`].
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
///
/// let path = Path::new("/laputa");
/// for entry in path.read_dir().expect("read_dir call failed") {
/// if let Ok(entry) = entry {
/// println!("{:?}", entry.path());
/// }
/// }
/// ```
#[stable(feature = "path_ext", since = "1.5.0")]
#[inline]
pub fn read_dir(&self) -> io::Result<fs::ReadDir> {
fs::read_dir(self)
}
// /// Returns `true` if the path points at an existing entity.
// ///
// /// Warning: this method may be error-prone, consider using [`try_exists()`] instead!
// /// It also has a risk of introducing time-of-check to time-of-use ([TOCTOU]) bugs.
// ///
// /// This function will traverse symbolic links to query information about the
// /// destination file.
// ///
// /// If you cannot access the metadata of the file, e.g. because of a
// /// permission error or broken symbolic links, this will return `false`.
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// /// assert!(!Path::new("does_not_exist.txt").exists());
// /// ```
// ///
// /// # See Also
// ///
// /// This is a convenience function that coerces errors to false. If you want to
// /// check errors, call [`Path::try_exists`].
// ///
// /// [`try_exists()`]: Self::try_exists
// /// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[must_use]
// #[inline]
// pub fn exists(&self) -> bool {
// fs::metadata(self).is_ok()
// }
/// Returns `true` if the path points at an existing entity.
///
/// Warning: this method may be error-prone, consider using [`try_exists()`] instead!
/// It also has a risk of introducing time-of-check to time-of-use ([TOCTOU]) bugs.
///
/// This function will traverse symbolic links to query information about the
/// destination file.
///
/// If you cannot access the metadata of the file, e.g. because of a
/// permission error or broken symbolic links, this will return `false`.
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
/// assert!(!Path::new("does_not_exist.txt").exists());
/// ```
///
/// # See Also
///
/// This is a convenience function that coerces errors to false. If you want to
/// check errors, call [`Path::try_exists`].
///
/// [`try_exists()`]: Self::try_exists
/// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou
#[stable(feature = "path_ext", since = "1.5.0")]
#[must_use]
#[inline]
pub fn exists(&self) -> bool {
fs::metadata(self).is_ok()
}
// /// Returns `Ok(true)` if the path points at an existing entity.
// ///
// /// This function will traverse symbolic links to query information about the
// /// destination file. In case of broken symbolic links this will return `Ok(false)`.
// ///
// /// [`Path::exists()`] only checks whether or not a path was both found and readable. By
// /// contrast, `try_exists` will return `Ok(true)` or `Ok(false)`, respectively, if the path
// /// was _verified_ to exist or not exist. If its existence can neither be confirmed nor
// /// denied, it will propagate an `Err(_)` instead. This can be the case if e.g. listing
// /// permission is denied on one of the parent directories.
// ///
// /// Note that while this avoids some pitfalls of the `exists()` method, it still can not
// /// prevent time-of-check to time-of-use ([TOCTOU]) bugs. You should only use it in scenarios
// /// where those bugs are not an issue.
// ///
// /// This is an alias for [`std::fs::exists`](crate::fs::exists).
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// /// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
// /// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
// /// ```
// ///
// /// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou
// /// [`exists()`]: Self::exists
// #[stable(feature = "path_try_exists", since = "1.63.0")]
// #[inline]
// pub fn try_exists(&self) -> io::Result<bool> {
// fs::exists(self)
// }
/// Returns `Ok(true)` if the path points at an existing entity.
///
/// This function will traverse symbolic links to query information about the
/// destination file. In case of broken symbolic links this will return `Ok(false)`.
///
/// [`Path::exists()`] only checks whether or not a path was both found and readable. By
/// contrast, `try_exists` will return `Ok(true)` or `Ok(false)`, respectively, if the path
/// was _verified_ to exist or not exist. If its existence can neither be confirmed nor
/// denied, it will propagate an `Err(_)` instead. This can be the case if e.g. listing
/// permission is denied on one of the parent directories.
///
/// Note that while this avoids some pitfalls of the `exists()` method, it still can not
/// prevent time-of-check to time-of-use ([TOCTOU]) bugs. You should only use it in scenarios
/// where those bugs are not an issue.
///
/// This is an alias for [`std::fs::exists`](crate::fs::exists).
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
/// assert!(!Path::new("does_not_exist.txt").try_exists().expect("Can't check existence of file does_not_exist.txt"));
/// assert!(Path::new("/root/secret_file.txt").try_exists().is_err());
/// ```
///
/// [TOCTOU]: fs#time-of-check-to-time-of-use-toctou
/// [`exists()`]: Self::exists
#[stable(feature = "path_try_exists", since = "1.63.0")]
#[inline]
pub fn try_exists(&self) -> io::Result<bool> {
fs::exists(self)
}
// /// Returns `true` if the path exists on disk and is pointing at a regular file.
// ///
// /// This function will traverse symbolic links to query information about the
// /// destination file.
// ///
// /// If you cannot access the metadata of the file, e.g. because of a
// /// permission error or broken symbolic links, this will return `false`.
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// /// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
// /// assert_eq!(Path::new("a_file.txt").is_file(), true);
// /// ```
// ///
// /// # See Also
// ///
// /// This is a convenience function that coerces errors to false. If you want to
// /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
// /// [`fs::Metadata::is_file`] if it was [`Ok`].
// ///
// /// When the goal is simply to read from (or write to) the source, the most
// /// reliable way to test the source can be read (or written to) is to open
// /// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
// /// a Unix-like system for example. See [`fs::File::open`] or
// /// [`fs::OpenOptions::open`] for more information.
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[must_use]
// pub fn is_file(&self) -> bool {
// fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
// }
/// Returns `true` if the path exists on disk and is pointing at a regular file.
///
/// This function will traverse symbolic links to query information about the
/// destination file.
///
/// If you cannot access the metadata of the file, e.g. because of a
/// permission error or broken symbolic links, this will return `false`.
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
/// assert_eq!(Path::new("./is_a_directory/").is_file(), false);
/// assert_eq!(Path::new("a_file.txt").is_file(), true);
/// ```
///
/// # See Also
///
/// This is a convenience function that coerces errors to false. If you want to
/// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
/// [`fs::Metadata::is_file`] if it was [`Ok`].
///
/// When the goal is simply to read from (or write to) the source, the most
/// reliable way to test the source can be read (or written to) is to open
/// it. Only using `is_file` can break workflows like `diff <( prog_a )` on
/// a Unix-like system for example. See [`fs::File::open`] or
/// [`fs::OpenOptions::open`] for more information.
#[stable(feature = "path_ext", since = "1.5.0")]
#[must_use]
pub fn is_file(&self) -> bool {
fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
}
// /// Returns `true` if the path exists on disk and is pointing at a directory.
// ///
// /// This function will traverse symbolic links to query information about the
// /// destination file.
// ///
// /// If you cannot access the metadata of the file, e.g. because of a
// /// permission error or broken symbolic links, this will return `false`.
// ///
// /// # Examples
// ///
// /// ```no_run
// /// use std::path::Path;
// /// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
// /// assert_eq!(Path::new("a_file.txt").is_dir(), false);
// /// ```
// ///
// /// # See Also
// ///
// /// This is a convenience function that coerces errors to false. If you want to
// /// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
// /// [`fs::Metadata::is_dir`] if it was [`Ok`].
// #[stable(feature = "path_ext", since = "1.5.0")]
// #[must_use]
// pub fn is_dir(&self) -> bool {
// fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
// }
/// Returns `true` if the path exists on disk and is pointing at a directory.
///
/// This function will traverse symbolic links to query information about the
/// destination file.
///
/// If you cannot access the metadata of the file, e.g. because of a
/// permission error or broken symbolic links, this will return `false`.
///
/// # Examples
///
/// ```no_run
/// use std::path::Path;
/// assert_eq!(Path::new("./is_a_directory/").is_dir(), true);
/// assert_eq!(Path::new("a_file.txt").is_dir(), false);
/// ```
///
/// # See Also
///
/// This is a convenience function that coerces errors to false. If you want to
/// check errors, call [`fs::metadata`] and handle its [`Result`]. Then call
/// [`fs::Metadata::is_dir`] if it was [`Ok`].
#[stable(feature = "path_ext", since = "1.5.0")]
#[must_use]
pub fn is_dir(&self) -> bool {
fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
}
// /// Returns `true` if the path exists on disk and is pointing at a symbolic link.
// ///
// /// This function will not traverse symbolic links.
// /// In case of a broken symbolic link this will also return true.
// ///
// /// If you cannot access the directory containing the file, e.g., because of a
// /// permission error, this will return false.
// ///
// /// # Examples
// ///
// /// ```rust,no_run
// /// # #[cfg(unix)] {
// /// use std::path::Path;
// /// use std::os::unix::fs::symlink;
// ///
// /// let link_path = Path::new("link");
// /// symlink("/origin_does_not_exist/", link_path).unwrap();
// /// assert_eq!(link_path.is_symlink(), true);
// /// assert_eq!(link_path.exists(), false);
// /// # }
// /// ```
// ///
// /// # See Also
// ///
// /// This is a convenience function that coerces errors to false. If you want to
// /// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call
// /// [`fs::Metadata::is_symlink`] if it was [`Ok`].
// #[must_use]
// #[stable(feature = "is_symlink", since = "1.58.0")]
// pub fn is_symlink(&self) -> bool {
// fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
// }
/// Returns `true` if the path exists on disk and is pointing at a symbolic link.
///
/// This function will not traverse symbolic links.
/// In case of a broken symbolic link this will also return true.
///
/// If you cannot access the directory containing the file, e.g., because of a
/// permission error, this will return false.
///
/// # Examples
///
/// ```rust,no_run
/// # #[cfg(unix)] {
/// use std::path::Path;
/// use std::os::unix::fs::symlink;
///
/// let link_path = Path::new("link");
/// symlink("/origin_does_not_exist/", link_path).unwrap();
/// assert_eq!(link_path.is_symlink(), true);
/// assert_eq!(link_path.exists(), false);
/// # }
/// ```
///
/// # See Also
///
/// This is a convenience function that coerces errors to false. If you want to
/// check errors, call [`fs::symlink_metadata`] and handle its [`Result`]. Then call
/// [`fs::Metadata::is_symlink`] if it was [`Ok`].
#[must_use]
#[stable(feature = "is_symlink", since = "1.58.0")]
pub fn is_symlink(&self) -> bool {
fs::symlink_metadata(self).map(|m| m.is_symlink()).unwrap_or(false)
}
/// Converts a [`Box<Path>`](Box) into a [`PathBuf`] without copying or
/// allocating.