@@ -64,6 +64,9 @@ pub trait GenericPath {
64
64
pure fn push_many( ( & [ ~str ] ) ) -> Self ;
65
65
pure fn pop( ) -> Self ;
66
66
67
+ pure fn unsafe_join( ( & Self ) ) -> Self ;
68
+ pure fn is_restricted( ) -> bool ;
69
+
67
70
pure fn normalize( ) -> Self ;
68
71
}
69
72
@@ -485,6 +488,19 @@ impl GenericPath for PosixPath {
485
488
self . push_many ( other. components )
486
489
}
487
490
491
+ pure fn unsafe_join ( other : & PosixPath ) -> PosixPath {
492
+ if other. is_absolute {
493
+ PosixPath { is_absolute : true ,
494
+ components : copy other. components }
495
+ } else {
496
+ self . push_rel ( other)
497
+ }
498
+ }
499
+
500
+ pure fn is_restricted ( ) -> bool {
501
+ false
502
+ }
503
+
488
504
pure fn push_many ( cs : & [ ~str ] ) -> PosixPath {
489
505
let mut v = copy self . components ;
490
506
for cs. each |e| {
@@ -685,6 +701,61 @@ impl GenericPath for WindowsPath {
685
701
self . push_many ( other. components )
686
702
}
687
703
704
+ pure fn unsafe_join ( other : & WindowsPath ) -> WindowsPath {
705
+ /* rhs not absolute is simple push */
706
+ if !other. is_absolute {
707
+ return self . push_many ( other. components ) ;
708
+ }
709
+
710
+ /* if rhs has a host set, then the whole thing wins */
711
+ match other. host {
712
+ Some ( copy host) => {
713
+ return WindowsPath {
714
+ host : Some ( host) ,
715
+ device : copy other. device ,
716
+ is_absolute : true ,
717
+ components : copy other. components
718
+ } ;
719
+ }
720
+ _ => { }
721
+ }
722
+
723
+ /* if rhs has a device set, then a part wins */
724
+ match other. device {
725
+ Some ( copy device) => {
726
+ return WindowsPath {
727
+ host : None ,
728
+ device : Some ( device) ,
729
+ is_absolute : true ,
730
+ components : copy other. components
731
+ } ;
732
+ }
733
+ _ => { }
734
+ }
735
+
736
+ /* fallback: host and device of lhs win, but the
737
+ whole path of the right */
738
+ WindowsPath {
739
+ host : copy self . host ,
740
+ device : copy self . device ,
741
+ is_absolute : self . is_absolute || other. is_absolute ,
742
+ components : copy other. components
743
+ }
744
+ }
745
+
746
+ pure fn is_restricted ( ) -> bool {
747
+ match self . filestem ( ) {
748
+ Some ( stem) => {
749
+ match stem. to_lower ( ) {
750
+ ~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" |
751
+ ~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true ,
752
+ _ => false
753
+ }
754
+ } ,
755
+ None => false
756
+ }
757
+ }
758
+
688
759
pure fn push_many ( cs : & [ ~str ] ) -> WindowsPath {
689
760
let mut v = copy self . components ;
690
761
for cs. each |e| {
@@ -725,7 +796,10 @@ impl GenericPath for WindowsPath {
725
796
pure fn normalize ( ) -> WindowsPath {
726
797
return WindowsPath {
727
798
host : copy self . host ,
728
- device : copy self . device ,
799
+ device : match self . device {
800
+ None => None ,
801
+ Some ( ref device) => Some ( device. to_upper ( ) )
802
+ } ,
729
803
is_absolute : self . is_absolute ,
730
804
components : normalize ( self . components )
731
805
}
@@ -764,13 +838,13 @@ pub mod windows {
764
838
765
839
pub pure fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
766
840
if (s.len() > 1 &&
767
- s[0] == '\\ ' as u8 &&
768
- s[1 ] == ' \\ ' as u8 ) {
841
+ ( s[0] == '\\ ' as u8 || s[0] == '/' as u8) &&
842
+ s[0 ] == s[1] ) {
769
843
let mut i = 2;
770
844
while i < s.len() {
771
- if s[i] == ' \\ ' as u8 {
845
+ if is_sep( s[i]) {
772
846
let pre = s.slice(2, i);
773
- let rest = s.slice(i, s.len());
847
+ let mut rest = s.slice(i, s.len());
774
848
return Some((pre, rest));
775
849
}
776
850
i += 1;
@@ -916,13 +990,21 @@ mod tests {
916
990
#[ test]
917
991
fn test_extract_unc_prefixes ( ) {
918
992
assert windows:: extract_unc_prefix ( "\\ \\ " ) . is_none ( ) ;
993
+ assert windows:: extract_unc_prefix ( "//" ) . is_none ( ) ;
919
994
assert windows:: extract_unc_prefix ( "\\ \\ hi" ) . is_none ( ) ;
995
+ assert windows:: extract_unc_prefix ( "//hi" ) . is_none ( ) ;
920
996
assert windows:: extract_unc_prefix ( "\\ \\ hi\\ " ) ==
921
997
Some ( ( ~"hi", ~"\\ ") ) ;
998
+ assert windows:: extract_unc_prefix ( "//hi\\ " ) ==
999
+ Some ( ( ~"hi", ~"\\ ") ) ;
922
1000
assert windows:: extract_unc_prefix ( "\\ \\ hi\\ there" ) ==
923
1001
Some ( ( ~"hi", ~"\\ there") ) ;
1002
+ assert windows:: extract_unc_prefix ( "//hi/there" ) ==
1003
+ Some ( ( ~"hi", ~"/there") ) ;
924
1004
assert windows:: extract_unc_prefix ( "\\ \\ hi\\ there\\ friends.txt" ) ==
925
1005
Some ( ( ~"hi", ~"\\ there\\ friends. txt ") ) ;
1006
+ assert windows:: extract_unc_prefix ( "//hi\\ there\\ friends.txt" ) ==
1007
+ Some ( ( ~"hi", ~"\\ there\\ friends. txt ") ) ;
926
1008
}
927
1009
928
1010
#[ test]
@@ -981,5 +1063,61 @@ mod tests {
981
1063
. push_many ( [ ~"lib", ~"thingy. dll "] )
982
1064
. with_filename ( "librustc.dll" ) ) ,
983
1065
"c:\\ program files (x86)\\ rust\\ lib\\ librustc.dll" ) ;
1066
+
1067
+ t ( & ( WindowsPath ( "\\ \\ computer\\ share" )
1068
+ . unsafe_join ( & WindowsPath ( "\\ a" ) ) ) ,
1069
+ "\\ \\ computer\\ a" ) ;
1070
+
1071
+ t ( & ( WindowsPath ( "//computer/share" )
1072
+ . unsafe_join ( & WindowsPath ( "\\ a" ) ) ) ,
1073
+ "\\ \\ computer\\ a" ) ;
1074
+
1075
+ t ( & ( WindowsPath ( "//computer/share" )
1076
+ . unsafe_join ( & WindowsPath ( "\\ \\ computer\\ share" ) ) ) ,
1077
+ "\\ \\ computer\\ share" ) ;
1078
+
1079
+ t ( & ( WindowsPath ( "C:/whatever" )
1080
+ . unsafe_join ( & WindowsPath ( "//computer/share/a/b" ) ) ) ,
1081
+ "\\ \\ computer\\ share\\ a\\ b" ) ;
1082
+
1083
+ t ( & ( WindowsPath ( "C:" )
1084
+ . unsafe_join ( & WindowsPath ( "D:/foo" ) ) ) ,
1085
+ "D:\\ foo" ) ;
1086
+
1087
+ t ( & ( WindowsPath ( "C:" )
1088
+ . unsafe_join ( & WindowsPath ( "B" ) ) ) ,
1089
+ "C:B" ) ;
1090
+
1091
+ t ( & ( WindowsPath ( "C:" )
1092
+ . unsafe_join ( & WindowsPath ( "/foo" ) ) ) ,
1093
+ "C:\\ foo" ) ;
1094
+
1095
+ t ( & ( WindowsPath ( "C:\\ " )
1096
+ . unsafe_join ( & WindowsPath ( "\\ bar" ) ) ) ,
1097
+ "C:\\ bar" ) ;
1098
+
1099
+ t ( & ( WindowsPath ( "" )
1100
+ . unsafe_join ( & WindowsPath ( "" ) ) ) ,
1101
+ "" ) ;
1102
+
1103
+ t ( & ( WindowsPath ( "" )
1104
+ . unsafe_join ( & WindowsPath ( "a" ) ) ) ,
1105
+ "a" ) ;
1106
+
1107
+ t ( & ( WindowsPath ( "" )
1108
+ . unsafe_join ( & WindowsPath ( "C:\\ a" ) ) ) ,
1109
+ "C:\\ a" ) ;
1110
+
1111
+ t ( & ( WindowsPath ( "c:\\ foo" )
1112
+ . normalize ( ) ) ,
1113
+ "C:\\ foo" ) ;
1114
+ }
1115
+
1116
+ #[ test]
1117
+ fn test_windows_path_restrictions ( ) {
1118
+ assert WindowsPath ( "hi" ) . is_restricted ( ) == false ;
1119
+ assert WindowsPath ( "C:\\ NUL" ) . is_restricted ( ) == true ;
1120
+ assert WindowsPath ( "C:\\ COM1.TXT" ) . is_restricted ( ) == true ;
1121
+ assert WindowsPath ( "c:\\ prn.exe" ) . is_restricted ( ) == true ;
984
1122
}
985
1123
}
0 commit comments