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;
|
mod os;
|
||||||
#[warn(non_camel_case_types)]
|
#[warn(non_camel_case_types)]
|
||||||
mod path;
|
mod path;
|
||||||
|
mod path2;
|
||||||
#[warn(non_camel_case_types)]
|
#[warn(non_camel_case_types)]
|
||||||
mod rand;
|
mod rand;
|
||||||
#[warn(non_camel_case_types)]
|
#[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 {
|
struct WindowsPath {
|
||||||
host: option<~str>;
|
host: option<~str>;
|
||||||
|
@ -31,6 +33,148 @@ trait Path {
|
||||||
fn pop_component() -> self;
|
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 {
|
impl WindowsPath : Path {
|
||||||
|
|
||||||
|
@ -82,7 +226,7 @@ impl WindowsPath : Path {
|
||||||
return WindowsPath { host: host,
|
return WindowsPath { host: host,
|
||||||
device: device,
|
device: device,
|
||||||
is_absolute: is_absolute,
|
is_absolute: is_absolute,
|
||||||
components: components }
|
components: normalize(components) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dirname() -> ~str {
|
fn dirname() -> ~str {
|
||||||
|
@ -112,7 +256,6 @@ impl WindowsPath : Path {
|
||||||
fn filename() -> option<~str> {
|
fn filename() -> option<~str> {
|
||||||
match self.components.len() {
|
match self.components.len() {
|
||||||
0 => none,
|
0 => none,
|
||||||
1 => some(copy self.components[0]),
|
|
||||||
n => some(copy self.components[n - 1])
|
n => some(copy self.components[n - 1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,11 +306,18 @@ impl WindowsPath : Path {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_filetype(t: &str) -> WindowsPath {
|
fn with_filetype(t: &str) -> WindowsPath {
|
||||||
let t = ~"." + str::from_slice(t);
|
if t.len() == 0 {
|
||||||
match self.filestem() {
|
match self.filestem() {
|
||||||
none => self.with_filename(t),
|
none => copy self,
|
||||||
some(ref s) =>
|
some(s) => self.with_filename(s)
|
||||||
self.with_filename(*s + t)
|
}
|
||||||
|
} 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 {
|
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 {
|
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.
|
// Various windows helpers, and tests for the impl.
|
||||||
mod windows {
|
mod windows {
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ export
|
||||||
// Creating a string
|
// Creating a string
|
||||||
from_bytes,
|
from_bytes,
|
||||||
from_byte,
|
from_byte,
|
||||||
|
from_slice,
|
||||||
from_char,
|
from_char,
|
||||||
from_chars,
|
from_chars,
|
||||||
append,
|
append,
|
||||||
|
|
Loading…
Reference in a new issue