path2: Implement WindowsPath
This commit is contained in:
parent
3d80a2f1f1
commit
f25835c221
@ -28,16 +28,16 @@ pub mod windows;
|
||||
/// See `posix::Path` for more info.
|
||||
pub type PosixPath = posix::Path;
|
||||
|
||||
// /// Typedef for Windows file paths.
|
||||
// /// See `windows::Path` for more info.
|
||||
// pub type WindowsPath = windows::Path;
|
||||
/// Typedef for Windows file paths.
|
||||
/// See `windows::Path` for more info.
|
||||
pub type WindowsPath = windows::Path;
|
||||
|
||||
/// Typedef for the platform-native path type
|
||||
#[cfg(unix)]
|
||||
pub type Path = PosixPath;
|
||||
// /// Typedef for the platform-native path type
|
||||
//#[cfg(windows)]
|
||||
//pub type Path = WindowsPath;
|
||||
/// Typedef for the platform-native path type
|
||||
#[cfg(windows)]
|
||||
pub type Path = WindowsPath;
|
||||
|
||||
/// Typedef for the POSIX path component iterator.
|
||||
/// See `posix::ComponentIter` for more info.
|
||||
@ -68,6 +68,8 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// # Failure
|
||||
///
|
||||
/// Raises the `null_byte` condition if the path contains a NUL.
|
||||
///
|
||||
/// See individual Path impls for additional restrictions.
|
||||
#[inline]
|
||||
fn from_vec(path: &[u8]) -> Self {
|
||||
if contains_nul(path) {
|
||||
@ -87,11 +89,18 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// Raises the `null_byte` condition if the path contains a NUL.
|
||||
#[inline]
|
||||
fn from_str(path: &str) -> Self {
|
||||
GenericPath::from_vec(path.as_bytes())
|
||||
let v = path.as_bytes();
|
||||
if contains_nul(v) {
|
||||
GenericPath::from_vec(path.as_bytes()) // let from_vec handle the condition
|
||||
} else {
|
||||
unsafe { GenericPathUnsafe::from_str_unchecked(path) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new Path from a CString.
|
||||
/// The resulting Path will always be normalized.
|
||||
///
|
||||
/// See individual Path impls for potential restrictions.
|
||||
#[inline]
|
||||
fn from_c_str(path: CString) -> Self {
|
||||
// CStrings can't contain NULs
|
||||
@ -186,7 +195,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `set_dirname` for details.
|
||||
#[inline]
|
||||
fn set_dirname_str(&mut self, dirname: &str) {
|
||||
self.set_dirname(dirname.as_bytes())
|
||||
if contains_nul(dirname.as_bytes()) {
|
||||
self.set_dirname(dirname.as_bytes()) // triggers null_byte condition
|
||||
} else {
|
||||
unsafe { self.set_dirname_str_unchecked(dirname) }
|
||||
}
|
||||
}
|
||||
/// Replaces the filename portion of the path with the given byte vector.
|
||||
/// If the replacement name is [], this is equivalent to popping the path.
|
||||
@ -208,7 +221,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `set_filename` for details.
|
||||
#[inline]
|
||||
fn set_filename_str(&mut self, filename: &str) {
|
||||
self.set_filename(filename.as_bytes())
|
||||
if contains_nul(filename.as_bytes()) {
|
||||
self.set_filename(filename.as_bytes()) // triggers null_byte condition
|
||||
} else {
|
||||
unsafe { self.set_filename_str_unchecked(filename) }
|
||||
}
|
||||
}
|
||||
/// Replaces the filestem with the given byte vector.
|
||||
/// If there is no extension in `self` (or `self` has no filename), this is equivalent
|
||||
@ -340,7 +357,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `set_dirname` for details.
|
||||
#[inline]
|
||||
fn with_dirname_str(&self, dirname: &str) -> Self {
|
||||
self.with_dirname(dirname.as_bytes())
|
||||
let mut p = self.clone();
|
||||
p.set_dirname_str(dirname);
|
||||
p
|
||||
}
|
||||
/// Returns a new Path constructed by replacing the filename with the given byte vector.
|
||||
/// See `set_filename` for details.
|
||||
@ -358,7 +377,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `set_filename` for details.
|
||||
#[inline]
|
||||
fn with_filename_str(&self, filename: &str) -> Self {
|
||||
self.with_filename(filename.as_bytes())
|
||||
let mut p = self.clone();
|
||||
p.set_filename_str(filename);
|
||||
p
|
||||
}
|
||||
/// Returns a new Path constructed by setting the filestem to the given byte vector.
|
||||
/// See `set_filestem` for details.
|
||||
@ -376,7 +397,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `set_filestem` for details.
|
||||
#[inline]
|
||||
fn with_filestem_str(&self, filestem: &str) -> Self {
|
||||
self.with_filestem(filestem.as_bytes())
|
||||
let mut p = self.clone();
|
||||
p.set_filestem_str(filestem);
|
||||
p
|
||||
}
|
||||
/// Returns a new Path constructed by setting the extension to the given byte vector.
|
||||
/// See `set_extension` for details.
|
||||
@ -394,20 +417,24 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `set_extension` for details.
|
||||
#[inline]
|
||||
fn with_extension_str(&self, extension: &str) -> Self {
|
||||
self.with_extension(extension.as_bytes())
|
||||
let mut p = self.clone();
|
||||
p.set_extension_str(extension);
|
||||
p
|
||||
}
|
||||
|
||||
/// Returns the directory component of `self`, as a Path.
|
||||
/// If `self` represents the root of the filesystem hierarchy, returns `self`.
|
||||
fn dir_path(&self) -> Self {
|
||||
GenericPath::from_vec(self.dirname())
|
||||
// self.dirname() returns a NUL-free vector
|
||||
unsafe { GenericPathUnsafe::from_vec_unchecked(self.dirname()) }
|
||||
}
|
||||
/// Returns the file component of `self`, as a relative Path.
|
||||
/// If `self` represents the root of the filesystem hierarchy, returns None.
|
||||
fn file_path(&self) -> Option<Self> {
|
||||
// self.filename() returns a NUL-free vector
|
||||
match self.filename() {
|
||||
[] => None,
|
||||
v => Some(GenericPath::from_vec(v))
|
||||
v => Some(unsafe { GenericPathUnsafe::from_vec_unchecked(v) })
|
||||
}
|
||||
}
|
||||
|
||||
@ -431,7 +458,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `push` for details.
|
||||
#[inline]
|
||||
fn push_str(&mut self, path: &str) {
|
||||
self.push(path.as_bytes())
|
||||
if contains_nul(path.as_bytes()) {
|
||||
self.push(path.as_bytes()) // triggers null_byte condition
|
||||
} else {
|
||||
unsafe { self.push_str_unchecked(path) }
|
||||
}
|
||||
}
|
||||
/// Pushes a Path onto `self`.
|
||||
/// If the argument represents an absolute path, it replaces `self`.
|
||||
@ -466,7 +497,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
/// See `join` for details.
|
||||
#[inline]
|
||||
fn join_str(&self, path: &str) -> Self {
|
||||
self.join(path.as_bytes())
|
||||
let mut p = self.clone();
|
||||
p.push_str(path);
|
||||
p
|
||||
}
|
||||
/// Returns a new Path constructed by joining `self` with the given path.
|
||||
/// If the given path is absolute, the new Path will represent just that.
|
||||
@ -478,6 +511,8 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
|
||||
}
|
||||
|
||||
/// Returns whether `self` represents an absolute path.
|
||||
/// An absolute path is defined as one that, when joined to another path, will
|
||||
/// yield back the same absolute path.
|
||||
fn is_absolute(&self) -> bool;
|
||||
|
||||
/// Returns whether `self` is equal to, or is an ancestor of, the given path.
|
||||
@ -498,19 +533,49 @@ pub trait GenericPathUnsafe {
|
||||
/// The resulting Path will always be normalized.
|
||||
unsafe fn from_vec_unchecked(path: &[u8]) -> Self;
|
||||
|
||||
/// Creates a new Path from a str without checking for null bytes.
|
||||
/// The resulting Path will always be normalized.
|
||||
#[inline]
|
||||
unsafe fn from_str_unchecked(path: &str) -> Self {
|
||||
GenericPathUnsafe::from_vec_unchecked(path.as_bytes())
|
||||
}
|
||||
|
||||
/// Replaces the directory portion of the path with the given byte vector without
|
||||
/// checking for null bytes.
|
||||
/// See `set_dirname` for details.
|
||||
unsafe fn set_dirname_unchecked(&mut self, dirname: &[u8]);
|
||||
|
||||
/// Replaces the directory portion of the path with the given str without
|
||||
/// checking for null bytes.
|
||||
/// See `set_dirname_str` for details.
|
||||
#[inline]
|
||||
unsafe fn set_dirname_str_unchecked(&mut self, dirname: &str) {
|
||||
self.set_dirname_unchecked(dirname.as_bytes())
|
||||
}
|
||||
|
||||
/// Replaces the filename portion of the path with the given byte vector without
|
||||
/// checking for null bytes.
|
||||
/// See `set_filename` for details.
|
||||
unsafe fn set_filename_unchecked(&mut self, filename: &[u8]);
|
||||
|
||||
/// Pushes a path onto `self` without checking for null bytes.
|
||||
/// Replaces the filename portion of the path with the given str without
|
||||
/// checking for null bytes.
|
||||
/// See `set_filename_str` for details.
|
||||
#[inline]
|
||||
unsafe fn set_filename_str_unchecked(&mut self, filename: &str) {
|
||||
self.set_filename_unchecked(filename.as_bytes())
|
||||
}
|
||||
|
||||
/// Pushes a byte vector onto `self` without checking for null bytes.
|
||||
/// See `push` for details.
|
||||
unsafe fn push_unchecked(&mut self, path: &[u8]);
|
||||
|
||||
/// Pushes a str onto `self` without checking for null bytes.
|
||||
/// See `push_str` for details.
|
||||
#[inline]
|
||||
unsafe fn push_str_unchecked(&mut self, path: &str) {
|
||||
self.push_unchecked(path.as_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
@ -45,6 +45,7 @@ pub fn is_sep(u: &u8) -> bool {
|
||||
}
|
||||
|
||||
impl Eq for Path {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Path) -> bool {
|
||||
self.repr == other.repr
|
||||
}
|
||||
@ -134,7 +135,7 @@ impl GenericPathUnsafe for Path {
|
||||
self.repr = Path::normalize(v);
|
||||
}
|
||||
Some(idx) => {
|
||||
let mut v = vec::with_capacity(self.repr.len() - idx + filename.len());
|
||||
let mut v = vec::with_capacity(idx + 1 + filename.len());
|
||||
v.push_all(self.repr.slice_to(idx+1));
|
||||
v.push_all(filename);
|
||||
self.repr = Path::normalize(v);
|
||||
@ -313,7 +314,7 @@ impl Path {
|
||||
let val = {
|
||||
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == sep;
|
||||
let v_ = if is_abs { v.as_slice().slice_from(1) } else { v.as_slice() };
|
||||
let comps = normalize_helper(v_, is_abs, is_sep);
|
||||
let comps = normalize_helper(v_, is_abs);
|
||||
match comps {
|
||||
None => None,
|
||||
Some(comps) => {
|
||||
@ -363,15 +364,14 @@ impl Path {
|
||||
}
|
||||
|
||||
// None result means the byte vector didn't need normalizing
|
||||
// FIXME (#8169): Pull this into parent module once visibility works
|
||||
fn normalize_helper<'a>(v: &'a [u8], is_abs: bool, f: &'a fn(&u8) -> bool) -> Option<~[&'a [u8]]> {
|
||||
fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<~[&'a [u8]]> {
|
||||
if is_abs && v.as_slice().is_empty() {
|
||||
return None;
|
||||
}
|
||||
let mut comps: ~[&'a [u8]] = ~[];
|
||||
let mut n_up = 0u;
|
||||
let mut changed = false;
|
||||
for comp in v.split_iter(f) {
|
||||
for comp in v.split_iter(is_sep) {
|
||||
if comp.is_empty() { changed = true }
|
||||
else if comp == bytes!(".") { changed = true }
|
||||
else if comp == bytes!("..") {
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user