@@ -28,16 +28,16 @@ pub mod windows;
28
28
/// See `posix::Path` for more info.
29
29
pub type PosixPath = posix:: Path ;
30
30
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 ;
34
34
35
35
/// Typedef for the platform-native path type
36
36
#[ cfg( unix) ]
37
37
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 ;
41
41
42
42
/// Typedef for the POSIX path component iterator.
43
43
/// See `posix::ComponentIter` for more info.
@@ -68,6 +68,8 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
68
68
/// # Failure
69
69
///
70
70
/// Raises the `null_byte` condition if the path contains a NUL.
71
+ ///
72
+ /// See individual Path impls for additional restrictions.
71
73
#[ inline]
72
74
fn from_vec ( path : & [ u8 ] ) -> Self {
73
75
if contains_nul ( path) {
@@ -87,11 +89,18 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
87
89
/// Raises the `null_byte` condition if the path contains a NUL.
88
90
#[ inline]
89
91
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
+ }
91
98
}
92
99
93
100
/// Creates a new Path from a CString.
94
101
/// The resulting Path will always be normalized.
102
+ ///
103
+ /// See individual Path impls for potential restrictions.
95
104
#[ inline]
96
105
fn from_c_str ( path : CString ) -> Self {
97
106
// CStrings can't contain NULs
@@ -186,7 +195,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
186
195
/// See `set_dirname` for details.
187
196
#[ inline]
188
197
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
+ }
190
203
}
191
204
/// Replaces the filename portion of the path with the given byte vector.
192
205
/// If the replacement name is [], this is equivalent to popping the path.
@@ -208,7 +221,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
208
221
/// See `set_filename` for details.
209
222
#[ inline]
210
223
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
+ }
212
229
}
213
230
/// Replaces the filestem with the given byte vector.
214
231
/// If there is no extension in `self` (or `self` has no filename), this is equivalent
@@ -340,7 +357,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
340
357
/// See `set_dirname` for details.
341
358
#[ inline]
342
359
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
344
363
}
345
364
/// Returns a new Path constructed by replacing the filename with the given byte vector.
346
365
/// See `set_filename` for details.
@@ -358,7 +377,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
358
377
/// See `set_filename` for details.
359
378
#[ inline]
360
379
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
362
383
}
363
384
/// Returns a new Path constructed by setting the filestem to the given byte vector.
364
385
/// See `set_filestem` for details.
@@ -376,7 +397,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
376
397
/// See `set_filestem` for details.
377
398
#[ inline]
378
399
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
380
403
}
381
404
/// Returns a new Path constructed by setting the extension to the given byte vector.
382
405
/// See `set_extension` for details.
@@ -394,20 +417,24 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
394
417
/// See `set_extension` for details.
395
418
#[ inline]
396
419
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
398
423
}
399
424
400
425
/// Returns the directory component of `self`, as a Path.
401
426
/// If `self` represents the root of the filesystem hierarchy, returns `self`.
402
427
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 ( ) ) }
404
430
}
405
431
/// Returns the file component of `self`, as a relative Path.
406
432
/// If `self` represents the root of the filesystem hierarchy, returns None.
407
433
fn file_path ( & self ) -> Option < Self > {
434
+ // self.filename() returns a NUL-free vector
408
435
match self . filename ( ) {
409
436
[ ] => None ,
410
- v => Some ( GenericPath :: from_vec ( v) )
437
+ v => Some ( unsafe { GenericPathUnsafe :: from_vec_unchecked ( v) } )
411
438
}
412
439
}
413
440
@@ -431,7 +458,11 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
431
458
/// See `push` for details.
432
459
#[ inline]
433
460
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
+ }
435
466
}
436
467
/// Pushes a Path onto `self`.
437
468
/// If the argument represents an absolute path, it replaces `self`.
@@ -466,7 +497,9 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
466
497
/// See `join` for details.
467
498
#[ inline]
468
499
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
470
503
}
471
504
/// Returns a new Path constructed by joining `self` with the given path.
472
505
/// If the given path is absolute, the new Path will represent just that.
@@ -478,6 +511,8 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
478
511
}
479
512
480
513
/// 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.
481
516
fn is_absolute ( & self ) -> bool ;
482
517
483
518
/// Returns whether `self` is equal to, or is an ancestor of, the given path.
@@ -498,19 +533,49 @@ pub trait GenericPathUnsafe {
498
533
/// The resulting Path will always be normalized.
499
534
unsafe fn from_vec_unchecked ( path : & [ u8 ] ) -> Self ;
500
535
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
+
501
543
/// Replaces the directory portion of the path with the given byte vector without
502
544
/// checking for null bytes.
503
545
/// See `set_dirname` for details.
504
546
unsafe fn set_dirname_unchecked ( & mut self , dirname : & [ u8 ] ) ;
505
547
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
+
506
556
/// Replaces the filename portion of the path with the given byte vector without
507
557
/// checking for null bytes.
508
558
/// See `set_filename` for details.
509
559
unsafe fn set_filename_unchecked ( & mut self , filename : & [ u8 ] ) ;
510
560
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.
512
570
/// See `push` for details.
513
571
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
+ }
514
579
}
515
580
516
581
#[ inline( always) ]
0 commit comments