Allow mutation only for Paths with form Any

This commit is contained in:
Ian Manske 2024-06-01 16:47:38 -04:00
parent e968b9f77e
commit 308349a7a4
2 changed files with 23 additions and 23 deletions

View File

@ -117,15 +117,15 @@ impl PathJoin for Canonical {
type Output = Absolute;
}
/// A marker trait for [`PathForm`]s that support mutation.
/// A marker trait for [`PathForm`]s that support setting the file name or extension.
///
/// This includes the [`Any`], [`Relative`], and [`Absolute`] path forms.
/// [`Canonical`] paths do not support mutation,
/// since unguarded mutation can cause them to no longer be canonical.
pub trait PathMut: PathForm {}
impl PathMut for Any {}
impl PathMut for Relative {}
impl PathMut for Absolute {}
/// [`Canonical`] paths do not support this, since appending file names and extensions that contain
/// path separators can cause the path to no longer be canonical.
pub trait PathSet: PathForm {}
impl PathSet for Any {}
impl PathSet for Relative {}
impl PathSet for Absolute {}
/// A marker trait for [`PathForm`]s that support pushing [`MaybeRelative`] paths.
///
@ -134,6 +134,6 @@ impl PathMut for Absolute {}
/// which is why they do not support pushing.
/// In the future, a `push_rel` and/or a `try_push` method could be added as an alternative.
/// Similarly, [`Canonical`] paths may become uncanonical if a non-canonical path is pushed onto it.
pub trait PathPush: PathMut {}
pub trait PathPush: PathSet {}
impl PathPush for Any {}
impl PathPush for Absolute {}

View File

@ -1,6 +1,6 @@
use crate::form::{
Absolute, Any, Canonical, IsAbsolute, MaybeAbsolute, MaybeRelative, PathCast, PathForm,
PathJoin, PathMut, PathPush, Relative,
PathJoin, PathPush, PathSet, Relative,
};
use std::{
borrow::{Borrow, Cow},
@ -198,6 +198,11 @@ impl Path {
Self::new_unchecked(path)
}
#[inline]
pub fn as_mut_os_str(&mut self) -> &mut OsStr {
self.inner.as_mut_os_str()
}
#[inline]
pub fn is_absolute(&self) -> bool {
self.inner.is_absolute()
@ -230,12 +235,7 @@ impl<Form: PathJoin> Path<Form> {
}
}
impl<Form: PathMut> Path<Form> {
#[inline]
pub fn as_mut_os_str(&mut self) -> &mut OsStr {
self.inner.as_mut_os_str()
}
impl<Form: PathSet> Path<Form> {
#[inline]
pub fn with_file_name(&self, file_name: impl AsRef<OsStr>) -> PathBuf<Form> {
PathBuf::new_unchecked(self.inner.with_file_name(file_name))
@ -486,6 +486,11 @@ impl PathBuf {
Self::new_unchecked(std::path::PathBuf::with_capacity(capacity))
}
#[inline]
pub fn as_mut_os_string(&mut self) -> &mut OsString {
self.inner.as_mut_os_string()
}
#[inline]
pub fn clear(&mut self) {
self.inner.clear()
@ -517,12 +522,7 @@ impl<Form: PathPush> PathBuf<Form> {
}
}
impl<Form: PathMut> PathBuf<Form> {
#[inline]
pub fn as_mut_os_string(&mut self) -> &mut OsString {
self.inner.as_mut_os_string()
}
impl<Form: PathSet> PathBuf<Form> {
#[inline]
pub fn set_file_name(&mut self, file_name: impl AsRef<OsStr>) {
self.inner.set_file_name(file_name)
@ -587,12 +587,12 @@ impl<Form: PathForm> Deref for PathBuf<Form> {
}
}
impl<Form: PathMut> DerefMut for PathBuf<Form> {
impl DerefMut for PathBuf {
#[inline]
fn deref_mut(&mut self) -> &mut Self::Target {
// Safety: `Path<Form>` is a repr(transparent) wrapper around `std::path::Path`.
let path: &mut std::path::Path = &mut self.inner;
let ptr = std::ptr::from_mut(path) as *mut Path<Form>;
let ptr = std::ptr::from_mut(path) as *mut Path;
unsafe { &mut *ptr }
}
}