1
- extern mod std;
1
+ // NB: transitionary, de-mode-ing.
2
+ #[ forbid( deprecated_mode) ] ;
3
+ #[ forbid( deprecated_pattern) ] ;
2
4
3
5
struct WindowsPath {
4
6
host : option < ~str > ;
@@ -31,6 +33,148 @@ trait Path {
31
33
fn pop_component ( ) -> self ;
32
34
}
33
35
36
+ // FIXME (#3227): when default methods in traits are working, de-duplicate
37
+ // PosixPath and WindowsPath, most of their methods are common.
38
+
39
+ impl PosixPath : Path {
40
+ fn to_str ( ) -> ~str {
41
+ match self . filename ( ) {
42
+ none => self . dirname ( ) ,
43
+ some( ref f) =>
44
+ if ( self . components . len ( ) == 1 &&
45
+ !self . is_absolute ) {
46
+ copy * f
47
+ } else {
48
+ self . dirname ( ) + "/" + * f
49
+ }
50
+ }
51
+ }
52
+
53
+ static fn from_str( s: & str ) -> PosixPath {
54
+ let mut components = str:: split_nonempty ( s, |c| c == '/' ) ;
55
+ let is_absolute = ( s. len ( ) != 0 && s[ 0 ] == '/' as u8 ) ;
56
+ return PosixPath { is_absolute : is_absolute,
57
+ components : normalize ( components) }
58
+ }
59
+
60
+ fn dirname ( ) -> ~str {
61
+ let mut s = ~"";
62
+ if self . is_absolute {
63
+ s += "/" ;
64
+ }
65
+ let mut d = copy self . components ;
66
+ if d. len ( ) != 0 {
67
+ vec:: pop ( d) ;
68
+ }
69
+ s += str:: connect ( d, "/" ) ;
70
+ if s. len ( ) == 0 {
71
+ s = ~". ";
72
+ }
73
+ return s;
74
+ }
75
+
76
+ fn filename ( ) -> option < ~str > {
77
+ match self . components . len ( ) {
78
+ 0 => none,
79
+ n => some ( copy self . components [ n - 1 ] )
80
+ }
81
+ }
82
+
83
+ fn filestem ( ) -> option < ~str > {
84
+ match self . filename ( ) {
85
+ none => none,
86
+ some( ref f) => {
87
+ match str:: rfind_char ( * f, '.' ) {
88
+ some( p) => some ( f. slice ( 0 , p) ) ,
89
+ none => some ( copy * f)
90
+ }
91
+ }
92
+ }
93
+ }
94
+
95
+ fn filetype ( ) -> option < ~str > {
96
+ match self . filename ( ) {
97
+ none => none,
98
+ some( ref f) => {
99
+ match str:: rfind_char ( * f, '.' ) {
100
+ some( p) if p+1 < f. len ( ) => some ( f. slice ( p+1 , f. len ( ) ) ) ,
101
+ _ => none
102
+ }
103
+ }
104
+ }
105
+ }
106
+
107
+ fn with_dirname ( d : & str ) -> PosixPath {
108
+ let dpath = from_str :: < PosixPath > ( d) ;
109
+ match self . filename ( ) {
110
+ some( ref f) => dpath. push_components ( ~[ copy * f] ) ,
111
+ none => dpath
112
+ }
113
+ }
114
+
115
+ fn with_filename ( f : & str ) -> PosixPath {
116
+ assert ! str:: any ( f, |c| windows:: is_sep ( c as u8 ) ) ;
117
+ self . dir_path ( ) . push_components ( ~[ str:: from_slice ( f) ] )
118
+ }
119
+
120
+ fn with_filestem ( s : & str ) -> PosixPath {
121
+ match self . filetype ( ) {
122
+ none => self . with_filename ( s) ,
123
+ some( ref t) =>
124
+ self . with_filename ( str:: from_slice ( s) + "." + * t)
125
+ }
126
+ }
127
+
128
+ fn with_filetype ( t : & str ) -> PosixPath {
129
+ if t. len ( ) == 0 {
130
+ match self . filestem ( ) {
131
+ none => copy self,
132
+ some( s) => self . with_filename ( s)
133
+ }
134
+ } else {
135
+ let t = ~". " + str:: from_slice ( t) ;
136
+ match self . filestem ( ) {
137
+ none => self . with_filename ( t) ,
138
+ some( ref s) =>
139
+ self . with_filename ( * s + t)
140
+ }
141
+ }
142
+ }
143
+
144
+ fn dir_path ( ) -> PosixPath {
145
+ if self . components . len ( ) != 0 {
146
+ self . pop_component ( )
147
+ } else {
148
+ copy self
149
+ }
150
+ }
151
+
152
+ fn file_path ( ) -> PosixPath {
153
+ let cs = match self . filename ( ) {
154
+ none => ~[ ] ,
155
+ some( ref f) => ~[ copy * f]
156
+ } ;
157
+ return PosixPath { is_absolute : false ,
158
+ components : cs }
159
+ }
160
+
161
+ fn push_components ( cs : & [ ~str ] ) -> PosixPath {
162
+ return PosixPath { components : normalize ( self . components + cs) ,
163
+ ..self }
164
+ }
165
+
166
+ fn pop_component ( ) -> PosixPath {
167
+ let mut cs = copy self . components ;
168
+ if cs. len ( ) != 0 {
169
+ vec:: pop ( cs) ;
170
+ }
171
+ return PosixPath { components : cs, ..self }
172
+ }
173
+
174
+
175
+
176
+ }
177
+
34
178
35
179
impl WindowsPath : Path {
36
180
@@ -82,7 +226,7 @@ impl WindowsPath : Path {
82
226
return WindowsPath { host : host,
83
227
device : device,
84
228
is_absolute : is_absolute,
85
- components : components }
229
+ components : normalize ( components) }
86
230
}
87
231
88
232
fn dirname ( ) -> ~str {
@@ -112,7 +256,6 @@ impl WindowsPath : Path {
112
256
fn filename ( ) -> option < ~str > {
113
257
match self . components . len ( ) {
114
258
0 => none,
115
- 1 => some ( copy self . components [ 0 ] ) ,
116
259
n => some ( copy self . components [ n - 1 ] )
117
260
}
118
261
}
@@ -163,11 +306,18 @@ impl WindowsPath : Path {
163
306
}
164
307
165
308
fn with_filetype ( t : & str ) -> WindowsPath {
166
- let t = ~". " + str:: from_slice ( t) ;
167
- match self . filestem ( ) {
168
- none => self . with_filename ( t) ,
169
- some( ref s) =>
170
- self . with_filename ( * s + t)
309
+ if t. len ( ) == 0 {
310
+ match self . filestem ( ) {
311
+ none => copy self,
312
+ some( s) => self . with_filename ( s)
313
+ }
314
+ } else {
315
+ let t = ~". " + str:: from_slice ( t) ;
316
+ match self . filestem ( ) {
317
+ none => self . with_filename ( t) ,
318
+ some( ref s) =>
319
+ self . with_filename ( * s + t)
320
+ }
171
321
}
172
322
}
173
323
@@ -191,7 +341,8 @@ impl WindowsPath : Path {
191
341
}
192
342
193
343
fn push_components ( cs : & [ ~str ] ) -> WindowsPath {
194
- return WindowsPath { components : self . components + cs, ..self }
344
+ return WindowsPath { components : normalize ( self . components + cs) ,
345
+ ..self }
195
346
}
196
347
197
348
fn pop_component ( ) -> WindowsPath {
@@ -203,6 +354,85 @@ impl WindowsPath : Path {
203
354
}
204
355
}
205
356
357
+
358
+ fn normalize( components : & [ ~str ] ) -> ~[ ~str ] {
359
+ let mut cs = ~[ ] ;
360
+ for components. each |c| {
361
+ if c == ~". " { again; }
362
+ if c == ~".." && cs.len() != 0 {
363
+ vec::pop(cs);
364
+ again;
365
+ }
366
+ vec::push(cs, copy c);
367
+ }
368
+ cs
369
+ }
370
+
371
+ mod posix {
372
+
373
+ #[test]
374
+ fn test_posix_paths() {
375
+ fn mk(s: &str) -> PosixPath { from_str::<PosixPath>(s) }
376
+ fn t(wp: &PosixPath, s: &str) {
377
+ let ss = wp.to_str();
378
+ let sss = str::from_slice(s);
379
+ if (ss != sss) {
380
+ debug!(" got %s", ss) ;
381
+ debug ! ( "expected %s" , sss) ;
382
+ assert ss == sss;
383
+ }
384
+ }
385
+
386
+ t ( & ( mk ( "hi" ) ) , "hi" ) ;
387
+ t ( & ( mk ( "hi/there" ) ) , "hi/there" ) ;
388
+ t ( & ( mk ( "hi/there.txt" ) ) , "hi/there.txt" ) ;
389
+
390
+ t ( & ( mk ( "hi/there.txt" ) ) , "hi/there.txt" ) ;
391
+ t ( & ( mk ( "hi/there.txt" )
392
+ . with_filetype ( "" ) ) , "hi/there" ) ;
393
+
394
+ t ( & ( mk ( "/a/b/c/there.txt" )
395
+ . with_dirname ( "hi" ) ) , "hi/there.txt" ) ;
396
+
397
+ t ( & ( mk ( "hi/there.txt" )
398
+ . with_dirname ( "." ) ) , "there.txt" ) ;
399
+
400
+ t ( & ( mk ( "a/b/../c/././/../foo.txt/" ) ) ,
401
+ "a/foo.txt" ) ;
402
+
403
+ t ( & ( mk ( "a/b/c" )
404
+ . push_components ( [ ~".."])), " a/b");
405
+
406
+ t(&(mk(" there. txt ")
407
+ . with_filetype ( "o" ) ) , "there.o" ) ;
408
+
409
+ t( & ( mk ( "hi/there.txt" )
410
+ . with_filetype ( "o" ) ) , "hi/there.o" ) ;
411
+
412
+ t ( & ( mk ( "hi/there.txt" )
413
+ . with_filetype ( "o" )
414
+ . with_dirname ( "/usr/lib" ) ) ,
415
+ "/usr/lib/there.o" ) ;
416
+
417
+ t ( & ( mk ( "hi/there.txt" )
418
+ . with_filetype ( "o" )
419
+ . with_dirname ( "/usr/lib/" ) ) ,
420
+ "/usr/lib/there.o" ) ;
421
+
422
+ t ( & ( mk ( "hi/there.txt" )
423
+ . with_filetype ( "o" )
424
+ . with_dirname ( "/usr//lib//" ) ) ,
425
+ "/usr/lib/there.o" ) ;
426
+
427
+ t ( & ( mk ( "/usr/bin/rust" )
428
+ . push_components ( [ ~"lib", ~"thingy. so "] )
429
+ . with_filestem ( "librustc" ) ) ,
430
+ "/usr/bin/rust/lib/librustc.so" ) ;
431
+
432
+ }
433
+
434
+ }
435
+
206
436
// Various windows helpers, and tests for the impl.
207
437
mod windows {
208
438
0 commit comments