Skip to content

Commit 19e333e

Browse files
committed
---
yaml --- r: 81604 b: refs/heads/snap-stage3 c: f25835c h: refs/heads/master v: v3
1 parent fd70f6e commit 19e333e

File tree

4 files changed

+2315
-29
lines changed

4 files changed

+2315
-29
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: 4c6bf4872012c010f84dc7fa2cdfe87522533f89
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 3d80a2f1f1910fd681b8fd99906da3446dc06a90
4+
refs/heads/snap-stage3: f25835c2210295bed25096807eed201e4d3b206e
55
refs/heads/try: 70152ff55722878cde684ee6462c14c65f2c4729
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libstd/path2/mod.rs

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,16 @@ pub mod windows;
2828
/// See `posix::Path` for more info.
2929
pub type PosixPath = posix::Path;
3030

31-
// /// Typedef for Windows file paths.
32-
// /// See `windows::Path` for more info.
33-
// pub type WindowsPath = windows::Path;
31+
/// Typedef for Windows file paths.
32+
/// See `windows::Path` for more info.
33+
pub type WindowsPath = windows::Path;
3434

3535
/// Typedef for the platform-native path type
3636
#[cfg(unix)]
3737
pub type Path = PosixPath;
38-
// /// Typedef for the platform-native path type
39-
//#[cfg(windows)]
40-
//pub type Path = WindowsPath;
38+
/// Typedef for the platform-native path type
39+
#[cfg(windows)]
40+
pub type Path = WindowsPath;
4141

4242
/// Typedef for the POSIX path component iterator.
4343
/// See `posix::ComponentIter` for more info.
@@ -68,6 +68,8 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
6868
/// # Failure
6969
///
7070
/// Raises the `null_byte` condition if the path contains a NUL.
71+
///
72+
/// See individual Path impls for additional restrictions.
7173
#[inline]
7274
fn from_vec(path: &[u8]) -> Self {
7375
if contains_nul(path) {
@@ -87,11 +89,18 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
8789
/// Raises the `null_byte` condition if the path contains a NUL.
8890
#[inline]
8991
fn from_str(path: &str) -> Self {
90-
GenericPath::from_vec(path.as_bytes())
92+
let v = path.as_bytes();
93+
if contains_nul(v) {
94+
GenericPath::from_vec(path.as_bytes()) // let from_vec handle the condition
95+
} else {
96+
unsafe { GenericPathUnsafe::from_str_unchecked(path) }
97+
}
9198
}
9299

93100
/// Creates a new Path from a CString.
94101
/// The resulting Path will always be normalized.
102+
///
103+
/// See individual Path impls for potential restrictions.
95104
#[inline]
96105
fn from_c_str(path: CString) -> Self {
97106
// CStrings can't contain NULs
@@ -186,7 +195,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
186195
/// See `set_dirname` for details.
187196
#[inline]
188197
fn set_dirname_str(&mut self, dirname: &str) {
189-
self.set_dirname(dirname.as_bytes())
198+
if contains_nul(dirname.as_bytes()) {
199+
self.set_dirname(dirname.as_bytes()) // triggers null_byte condition
200+
} else {
201+
unsafe { self.set_dirname_str_unchecked(dirname) }
202+
}
190203
}
191204
/// Replaces the filename portion of the path with the given byte vector.
192205
/// If the replacement name is [], this is equivalent to popping the path.
@@ -208,7 +221,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
208221
/// See `set_filename` for details.
209222
#[inline]
210223
fn set_filename_str(&mut self, filename: &str) {
211-
self.set_filename(filename.as_bytes())
224+
if contains_nul(filename.as_bytes()) {
225+
self.set_filename(filename.as_bytes()) // triggers null_byte condition
226+
} else {
227+
unsafe { self.set_filename_str_unchecked(filename) }
228+
}
212229
}
213230
/// Replaces the filestem with the given byte vector.
214231
/// If there is no extension in `self` (or `self` has no filename), this is equivalent
@@ -340,7 +357,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
340357
/// See `set_dirname` for details.
341358
#[inline]
342359
fn with_dirname_str(&self, dirname: &str) -> Self {
343-
self.with_dirname(dirname.as_bytes())
360+
let mut p = self.clone();
361+
p.set_dirname_str(dirname);
362+
p
344363
}
345364
/// Returns a new Path constructed by replacing the filename with the given byte vector.
346365
/// See `set_filename` for details.
@@ -358,7 +377,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
358377
/// See `set_filename` for details.
359378
#[inline]
360379
fn with_filename_str(&self, filename: &str) -> Self {
361-
self.with_filename(filename.as_bytes())
380+
let mut p = self.clone();
381+
p.set_filename_str(filename);
382+
p
362383
}
363384
/// Returns a new Path constructed by setting the filestem to the given byte vector.
364385
/// See `set_filestem` for details.
@@ -376,7 +397,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
376397
/// See `set_filestem` for details.
377398
#[inline]
378399
fn with_filestem_str(&self, filestem: &str) -> Self {
379-
self.with_filestem(filestem.as_bytes())
400+
let mut p = self.clone();
401+
p.set_filestem_str(filestem);
402+
p
380403
}
381404
/// Returns a new Path constructed by setting the extension to the given byte vector.
382405
/// See `set_extension` for details.
@@ -394,20 +417,24 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
394417
/// See `set_extension` for details.
395418
#[inline]
396419
fn with_extension_str(&self, extension: &str) -> Self {
397-
self.with_extension(extension.as_bytes())
420+
let mut p = self.clone();
421+
p.set_extension_str(extension);
422+
p
398423
}
399424

400425
/// Returns the directory component of `self`, as a Path.
401426
/// If `self` represents the root of the filesystem hierarchy, returns `self`.
402427
fn dir_path(&self) -> Self {
403-
GenericPath::from_vec(self.dirname())
428+
// self.dirname() returns a NUL-free vector
429+
unsafe { GenericPathUnsafe::from_vec_unchecked(self.dirname()) }
404430
}
405431
/// Returns the file component of `self`, as a relative Path.
406432
/// If `self` represents the root of the filesystem hierarchy, returns None.
407433
fn file_path(&self) -> Option<Self> {
434+
// self.filename() returns a NUL-free vector
408435
match self.filename() {
409436
[] => None,
410-
v => Some(GenericPath::from_vec(v))
437+
v => Some(unsafe { GenericPathUnsafe::from_vec_unchecked(v) })
411438
}
412439
}
413440

@@ -431,7 +458,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
431458
/// See `push` for details.
432459
#[inline]
433460
fn push_str(&mut self, path: &str) {
434-
self.push(path.as_bytes())
461+
if contains_nul(path.as_bytes()) {
462+
self.push(path.as_bytes()) // triggers null_byte condition
463+
} else {
464+
unsafe { self.push_str_unchecked(path) }
465+
}
435466
}
436467
/// Pushes a Path onto `self`.
437468
/// If the argument represents an absolute path, it replaces `self`.
@@ -466,7 +497,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
466497
/// See `join` for details.
467498
#[inline]
468499
fn join_str(&self, path: &str) -> Self {
469-
self.join(path.as_bytes())
500+
let mut p = self.clone();
501+
p.push_str(path);
502+
p
470503
}
471504
/// Returns a new Path constructed by joining `self` with the given path.
472505
/// If the given path is absolute, the new Path will represent just that.
@@ -478,6 +511,8 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
478511
}
479512

480513
/// Returns whether `self` represents an absolute path.
514+
/// An absolute path is defined as one that, when joined to another path, will
515+
/// yield back the same absolute path.
481516
fn is_absolute(&self) -> bool;
482517

483518
/// Returns whether `self` is equal to, or is an ancestor of, the given path.
@@ -498,19 +533,49 @@ pub trait GenericPathUnsafe {
498533
/// The resulting Path will always be normalized.
499534
unsafe fn from_vec_unchecked(path: &[u8]) -> Self;
500535

536+
/// Creates a new Path from a str without checking for null bytes.
537+
/// The resulting Path will always be normalized.
538+
#[inline]
539+
unsafe fn from_str_unchecked(path: &str) -> Self {
540+
GenericPathUnsafe::from_vec_unchecked(path.as_bytes())
541+
}
542+
501543
/// Replaces the directory portion of the path with the given byte vector without
502544
/// checking for null bytes.
503545
/// See `set_dirname` for details.
504546
unsafe fn set_dirname_unchecked(&mut self, dirname: &[u8]);
505547

548+
/// Replaces the directory portion of the path with the given str without
549+
/// checking for null bytes.
550+
/// See `set_dirname_str` for details.
551+
#[inline]
552+
unsafe fn set_dirname_str_unchecked(&mut self, dirname: &str) {
553+
self.set_dirname_unchecked(dirname.as_bytes())
554+
}
555+
506556
/// Replaces the filename portion of the path with the given byte vector without
507557
/// checking for null bytes.
508558
/// See `set_filename` for details.
509559
unsafe fn set_filename_unchecked(&mut self, filename: &[u8]);
510560

511-
/// Pushes a path onto `self` without checking for null bytes.
561+
/// Replaces the filename portion of the path with the given str without
562+
/// checking for null bytes.
563+
/// See `set_filename_str` for details.
564+
#[inline]
565+
unsafe fn set_filename_str_unchecked(&mut self, filename: &str) {
566+
self.set_filename_unchecked(filename.as_bytes())
567+
}
568+
569+
/// Pushes a byte vector onto `self` without checking for null bytes.
512570
/// See `push` for details.
513571
unsafe fn push_unchecked(&mut self, path: &[u8]);
572+
573+
/// Pushes a str onto `self` without checking for null bytes.
574+
/// See `push_str` for details.
575+
#[inline]
576+
unsafe fn push_str_unchecked(&mut self, path: &str) {
577+
self.push_unchecked(path.as_bytes())
578+
}
514579
}
515580

516581
#[inline(always)]

branches/snap-stage3/src/libstd/path2/posix.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub fn is_sep(u: &u8) -> bool {
4545
}
4646

4747
impl Eq for Path {
48+
#[inline]
4849
fn eq(&self, other: &Path) -> bool {
4950
self.repr == other.repr
5051
}
@@ -134,7 +135,7 @@ impl GenericPathUnsafe for Path {
134135
self.repr = Path::normalize(v);
135136
}
136137
Some(idx) => {
137-
let mut v = vec::with_capacity(self.repr.len() - idx + filename.len());
138+
let mut v = vec::with_capacity(idx + 1 + filename.len());
138139
v.push_all(self.repr.slice_to(idx+1));
139140
v.push_all(filename);
140141
self.repr = Path::normalize(v);
@@ -313,7 +314,7 @@ impl Path {
313314
let val = {
314315
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == sep;
315316
let v_ = if is_abs { v.as_slice().slice_from(1) } else { v.as_slice() };
316-
let comps = normalize_helper(v_, is_abs, is_sep);
317+
let comps = normalize_helper(v_, is_abs);
317318
match comps {
318319
None => None,
319320
Some(comps) => {
@@ -363,15 +364,14 @@ impl Path {
363364
}
364365

365366
// None result means the byte vector didn't need normalizing
366-
// FIXME (#8169): Pull this into parent module once visibility works
367-
fn normalize_helper<'a>(v: &'a [u8], is_abs: bool, f: &'a fn(&u8) -> bool) -> Option<~[&'a [u8]]> {
367+
fn normalize_helper<'a>(v: &'a [u8], is_abs: bool) -> Option<~[&'a [u8]]> {
368368
if is_abs && v.as_slice().is_empty() {
369369
return None;
370370
}
371371
let mut comps: ~[&'a [u8]] = ~[];
372372
let mut n_up = 0u;
373373
let mut changed = false;
374-
for comp in v.split_iter(f) {
374+
for comp in v.split_iter(is_sep) {
375375
if comp.is_empty() { changed = true }
376376
else if comp == bytes!(".") { changed = true }
377377
else if comp == bytes!("..") {

0 commit comments

Comments
 (0)