Add PosixPath to path2. Add path2 to core build. Add dot/dotdot-normalizing.
This commit is contained in:
parent
a14485b7fd
commit
08441fca76
3 changed files with 241 additions and 9 deletions
|
@ -252,6 +252,7 @@ mod libc;
|
|||
mod os;
|
||||
#[warn(non_camel_case_types)]
|
||||
mod path;
|
||||
mod path2;
|
||||
#[warn(non_camel_case_types)]
|
||||
mod rand;
|
||||
#[warn(non_camel_case_types)]
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
extern mod std;
|
||||
// NB: transitionary, de-mode-ing.
|
||||
#[forbid(deprecated_mode)];
|
||||
#[forbid(deprecated_pattern)];
|
||||
|
||||
struct WindowsPath {
|
||||
host: option<~str>;
|
||||
|
@ -31,6 +33,148 @@ trait Path {
|
|||
fn pop_component() -> self;
|
||||
}
|
||||
|
||||
// FIXME (#3227): when default methods in traits are working, de-duplicate
|
||||
// PosixPath and WindowsPath, most of their methods are common.
|
||||
|
||||
impl PosixPath : Path {
|
||||
fn to_str() -> ~str {
|
||||
match self.filename() {
|
||||
none => self.dirname(),
|
||||
some(ref f) =>
|
||||
if (self.components.len() == 1 &&
|
||||
!self.is_absolute) {
|
||||
copy *f
|
||||
} else {
|
||||
self.dirname() + "/" + *f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static fn from_str(s: &str) -> PosixPath {
|
||||
let mut components = str::split_nonempty(s, |c| c == '/');
|
||||
let is_absolute = (s.len() != 0 && s[0] == '/' as u8);
|
||||
return PosixPath { is_absolute: is_absolute,
|
||||
components: normalize(components) }
|
||||
}
|
||||
|
||||
fn dirname() -> ~str {
|
||||
let mut s = ~"";
|
||||
if self.is_absolute {
|
||||
s += "/";
|
||||
}
|
||||
let mut d = copy self.components;
|
||||
if d.len() != 0 {
|
||||
vec::pop(d);
|
||||
}
|
||||
s += str::connect(d, "/");
|
||||
if s.len() == 0 {
|
||||
s = ~".";
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
fn filename() -> option<~str> {
|
||||
match self.components.len() {
|
||||
0 => none,
|
||||
n => some(copy self.components[n - 1])
|
||||
}
|
||||
}
|
||||
|
||||
fn filestem() -> option<~str> {
|
||||
match self.filename() {
|
||||
none => none,
|
||||
some(ref f) => {
|
||||
match str::rfind_char(*f, '.') {
|
||||
some(p) => some(f.slice(0, p)),
|
||||
none => some(copy *f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn filetype() -> option<~str> {
|
||||
match self.filename() {
|
||||
none => none,
|
||||
some(ref f) => {
|
||||
match str::rfind_char(*f, '.') {
|
||||
some(p) if p+1 < f.len() => some(f.slice(p+1, f.len())),
|
||||
_ => none
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn with_dirname(d: &str) -> PosixPath {
|
||||
let dpath = from_str::<PosixPath>(d);
|
||||
match self.filename() {
|
||||
some(ref f) => dpath.push_components(~[copy *f]),
|
||||
none => dpath
|
||||
}
|
||||
}
|
||||
|
||||
fn with_filename(f: &str) -> PosixPath {
|
||||
assert ! str::any(f, |c| windows::is_sep(c as u8));
|
||||
self.dir_path().push_components(~[str::from_slice(f)])
|
||||
}
|
||||
|
||||
fn with_filestem(s: &str) -> PosixPath {
|
||||
match self.filetype() {
|
||||
none => self.with_filename(s),
|
||||
some(ref t) =>
|
||||
self.with_filename(str::from_slice(s) + "." + *t)
|
||||
}
|
||||
}
|
||||
|
||||
fn with_filetype(t: &str) -> PosixPath {
|
||||
if t.len() == 0 {
|
||||
match self.filestem() {
|
||||
none => copy self,
|
||||
some(s) => self.with_filename(s)
|
||||
}
|
||||
} else {
|
||||
let t = ~"." + str::from_slice(t);
|
||||
match self.filestem() {
|
||||
none => self.with_filename(t),
|
||||
some(ref s) =>
|
||||
self.with_filename(*s + t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn dir_path() -> PosixPath {
|
||||
if self.components.len() != 0 {
|
||||
self.pop_component()
|
||||
} else {
|
||||
copy self
|
||||
}
|
||||
}
|
||||
|
||||
fn file_path() -> PosixPath {
|
||||
let cs = match self.filename() {
|
||||
none => ~[],
|
||||
some(ref f) => ~[copy *f]
|
||||
};
|
||||
return PosixPath { is_absolute: false,
|
||||
components: cs }
|
||||
}
|
||||
|
||||
fn push_components(cs: &[~str]) -> PosixPath {
|
||||
return PosixPath { components: normalize(self.components + cs),
|
||||
..self }
|
||||
}
|
||||
|
||||
fn pop_component() -> PosixPath {
|
||||
let mut cs = copy self.components;
|
||||
if cs.len() != 0 {
|
||||
vec::pop(cs);
|
||||
}
|
||||
return PosixPath { components: cs, ..self }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
impl WindowsPath : Path {
|
||||
|
||||
|
@ -82,7 +226,7 @@ impl WindowsPath : Path {
|
|||
return WindowsPath { host: host,
|
||||
device: device,
|
||||
is_absolute: is_absolute,
|
||||
components: components }
|
||||
components: normalize(components) }
|
||||
}
|
||||
|
||||
fn dirname() -> ~str {
|
||||
|
@ -112,7 +256,6 @@ impl WindowsPath : Path {
|
|||
fn filename() -> option<~str> {
|
||||
match self.components.len() {
|
||||
0 => none,
|
||||
1 => some(copy self.components[0]),
|
||||
n => some(copy self.components[n - 1])
|
||||
}
|
||||
}
|
||||
|
@ -163,11 +306,18 @@ impl WindowsPath : Path {
|
|||
}
|
||||
|
||||
fn with_filetype(t: &str) -> WindowsPath {
|
||||
let t = ~"." + str::from_slice(t);
|
||||
match self.filestem() {
|
||||
none => self.with_filename(t),
|
||||
some(ref s) =>
|
||||
self.with_filename(*s + t)
|
||||
if t.len() == 0 {
|
||||
match self.filestem() {
|
||||
none => copy self,
|
||||
some(s) => self.with_filename(s)
|
||||
}
|
||||
} else {
|
||||
let t = ~"." + str::from_slice(t);
|
||||
match self.filestem() {
|
||||
none => self.with_filename(t),
|
||||
some(ref s) =>
|
||||
self.with_filename(*s + t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +341,8 @@ impl WindowsPath : Path {
|
|||
}
|
||||
|
||||
fn push_components(cs: &[~str]) -> WindowsPath {
|
||||
return WindowsPath { components: self.components + cs, ..self }
|
||||
return WindowsPath { components: normalize(self.components + cs),
|
||||
..self }
|
||||
}
|
||||
|
||||
fn pop_component() -> WindowsPath {
|
||||
|
@ -203,6 +354,85 @@ impl WindowsPath : Path {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
fn normalize(components: &[~str]) -> ~[~str] {
|
||||
let mut cs = ~[];
|
||||
for components.each |c| {
|
||||
if c == ~"." { again; }
|
||||
if c == ~".." && cs.len() != 0 {
|
||||
vec::pop(cs);
|
||||
again;
|
||||
}
|
||||
vec::push(cs, copy c);
|
||||
}
|
||||
cs
|
||||
}
|
||||
|
||||
mod posix {
|
||||
|
||||
#[test]
|
||||
fn test_posix_paths() {
|
||||
fn mk(s: &str) -> PosixPath { from_str::<PosixPath>(s) }
|
||||
fn t(wp: &PosixPath, s: &str) {
|
||||
let ss = wp.to_str();
|
||||
let sss = str::from_slice(s);
|
||||
if (ss != sss) {
|
||||
debug!("got %s", ss);
|
||||
debug!("expected %s", sss);
|
||||
assert ss == sss;
|
||||
}
|
||||
}
|
||||
|
||||
t(&(mk("hi")), "hi");
|
||||
t(&(mk("hi/there")), "hi/there");
|
||||
t(&(mk("hi/there.txt")), "hi/there.txt");
|
||||
|
||||
t(&(mk("hi/there.txt")), "hi/there.txt");
|
||||
t(&(mk("hi/there.txt")
|
||||
.with_filetype("")), "hi/there");
|
||||
|
||||
t(&(mk("/a/b/c/there.txt")
|
||||
.with_dirname("hi")), "hi/there.txt");
|
||||
|
||||
t(&(mk("hi/there.txt")
|
||||
.with_dirname(".")), "there.txt");
|
||||
|
||||
t(&(mk("a/b/../c/././/../foo.txt/")),
|
||||
"a/foo.txt");
|
||||
|
||||
t(&(mk("a/b/c")
|
||||
.push_components([~".."])), "a/b");
|
||||
|
||||
t(&(mk("there.txt")
|
||||
.with_filetype("o")), "there.o");
|
||||
|
||||
t(&(mk("hi/there.txt")
|
||||
.with_filetype("o")), "hi/there.o");
|
||||
|
||||
t(&(mk("hi/there.txt")
|
||||
.with_filetype("o")
|
||||
.with_dirname("/usr/lib")),
|
||||
"/usr/lib/there.o");
|
||||
|
||||
t(&(mk("hi/there.txt")
|
||||
.with_filetype("o")
|
||||
.with_dirname("/usr/lib/")),
|
||||
"/usr/lib/there.o");
|
||||
|
||||
t(&(mk("hi/there.txt")
|
||||
.with_filetype("o")
|
||||
.with_dirname("/usr//lib//")),
|
||||
"/usr/lib/there.o");
|
||||
|
||||
t(&(mk("/usr/bin/rust")
|
||||
.push_components([~"lib", ~"thingy.so"])
|
||||
.with_filestem("librustc")),
|
||||
"/usr/bin/rust/lib/librustc.so");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Various windows helpers, and tests for the impl.
|
||||
mod windows {
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ export
|
|||
// Creating a string
|
||||
from_bytes,
|
||||
from_byte,
|
||||
from_slice,
|
||||
from_char,
|
||||
from_chars,
|
||||
append,
|
||||
|
|
Loading…
Reference in a new issue