2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-09-19 18:52:32 -05:00
|
|
|
/*!
|
|
|
|
|
|
|
|
Cross-platform file path handling
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2012-08-27 18:26:35 -05:00
|
|
|
use cmp::Eq;
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
2013-01-08 21:37:25 -06:00
|
|
|
use option::{None, Option, Some};
|
2012-12-23 16:41:37 -06:00
|
|
|
use str;
|
2013-01-08 21:37:25 -06:00
|
|
|
use to_str::ToStr;
|
2012-08-27 18:26:35 -05:00
|
|
|
|
2013-03-20 10:35:02 -05:00
|
|
|
#[deriving(Eq)]
|
2012-09-27 17:44:09 -05:00
|
|
|
pub struct WindowsPath {
|
2012-09-07 16:50:47 -05:00
|
|
|
host: Option<~str>,
|
|
|
|
device: Option<~str>,
|
|
|
|
is_absolute: bool,
|
|
|
|
components: ~[~str],
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2012-11-17 22:23:44 -06:00
|
|
|
pub pure fn WindowsPath(s: &str) -> WindowsPath {
|
2012-12-13 17:55:05 -06:00
|
|
|
GenericPath::from_str(s)
|
2012-11-17 22:23:44 -06:00
|
|
|
}
|
|
|
|
|
2013-03-20 10:35:02 -05:00
|
|
|
#[deriving(Eq)]
|
2012-09-27 17:44:09 -05:00
|
|
|
pub struct PosixPath {
|
2012-09-07 16:50:47 -05:00
|
|
|
is_absolute: bool,
|
|
|
|
components: ~[~str],
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2012-11-17 22:23:44 -06:00
|
|
|
pub pure fn PosixPath(s: &str) -> PosixPath {
|
2012-12-13 17:55:05 -06:00
|
|
|
GenericPath::from_str(s)
|
2012-11-17 22:23:44 -06:00
|
|
|
}
|
|
|
|
|
2012-09-27 17:44:09 -05:00
|
|
|
pub trait GenericPath {
|
2013-03-21 21:07:54 -05:00
|
|
|
pure fn from_str(&str) -> Self;
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn dirname(&self) -> ~str;
|
|
|
|
pure fn filename(&self) -> Option<~str>;
|
|
|
|
pure fn filestem(&self) -> Option<~str>;
|
|
|
|
pure fn filetype(&self) -> Option<~str>;
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_dirname(&self, (&str)) -> Self;
|
|
|
|
pure fn with_filename(&self, (&str)) -> Self;
|
|
|
|
pure fn with_filestem(&self, (&str)) -> Self;
|
|
|
|
pure fn with_filetype(&self, (&str)) -> Self;
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn dir_path(&self) -> Self;
|
|
|
|
pure fn file_path(&self) -> Self;
|
2012-11-29 20:37:33 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn push(&self, (&str)) -> Self;
|
|
|
|
pure fn push_rel(&self, (&Self)) -> Self;
|
|
|
|
pure fn push_many(&self, (&[~str])) -> Self;
|
|
|
|
pure fn pop(&self) -> Self;
|
2012-08-29 15:59:02 -05:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn unsafe_join(&self, (&Self)) -> Self;
|
|
|
|
pure fn is_restricted(&self) -> bool;
|
2013-02-18 16:48:18 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn normalize(&self) -> Self;
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2012-08-29 15:25:31 -05:00
|
|
|
#[cfg(windows)]
|
2012-09-27 17:44:09 -05:00
|
|
|
pub type Path = WindowsPath;
|
2012-08-29 15:25:31 -05:00
|
|
|
|
|
|
|
#[cfg(windows)]
|
2012-09-27 17:44:09 -05:00
|
|
|
pub pure fn Path(s: &str) -> Path {
|
2012-11-17 22:23:44 -06:00
|
|
|
WindowsPath(s)
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2012-08-29 15:25:31 -05:00
|
|
|
#[cfg(unix)]
|
2012-09-27 17:44:09 -05:00
|
|
|
pub type Path = PosixPath;
|
2012-08-29 15:25:31 -05:00
|
|
|
|
|
|
|
#[cfg(unix)]
|
2012-09-27 17:44:09 -05:00
|
|
|
pub pure fn Path(s: &str) -> Path {
|
2012-11-17 22:23:44 -06:00
|
|
|
PosixPath(s)
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2012-11-09 19:50:23 -06:00
|
|
|
#[cfg(target_os = "linux")]
|
2012-11-29 18:21:49 -06:00
|
|
|
#[cfg(target_os = "android")]
|
2012-11-09 19:50:23 -06:00
|
|
|
mod stat {
|
|
|
|
#[cfg(target_arch = "x86")]
|
2012-11-29 18:21:49 -06:00
|
|
|
#[cfg(target_arch = "arm")]
|
2013-01-29 08:28:08 -06:00
|
|
|
#[cfg(target_arch = "mips")]
|
2012-11-09 19:50:23 -06:00
|
|
|
pub mod arch {
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
|
|
|
|
2012-11-09 19:50:23 -06:00
|
|
|
pub fn default_stat() -> libc::stat {
|
|
|
|
libc::stat {
|
|
|
|
st_dev: 0,
|
|
|
|
__pad1: 0,
|
|
|
|
st_ino: 0,
|
|
|
|
st_mode: 0,
|
|
|
|
st_nlink: 0,
|
|
|
|
st_uid: 0,
|
|
|
|
st_gid: 0,
|
|
|
|
st_rdev: 0,
|
|
|
|
__pad2: 0,
|
|
|
|
st_size: 0,
|
|
|
|
st_blksize: 0,
|
|
|
|
st_blocks: 0,
|
|
|
|
st_atime: 0,
|
|
|
|
st_atime_nsec: 0,
|
|
|
|
st_mtime: 0,
|
|
|
|
st_mtime_nsec: 0,
|
|
|
|
st_ctime: 0,
|
|
|
|
st_ctime_nsec: 0,
|
|
|
|
__unused4: 0,
|
|
|
|
__unused5: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
pub mod arch {
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
|
|
|
|
2012-11-09 19:50:23 -06:00
|
|
|
pub fn default_stat() -> libc::stat {
|
|
|
|
libc::stat {
|
|
|
|
st_dev: 0,
|
|
|
|
st_ino: 0,
|
|
|
|
st_nlink: 0,
|
|
|
|
st_mode: 0,
|
|
|
|
st_uid: 0,
|
|
|
|
st_gid: 0,
|
|
|
|
__pad0: 0,
|
|
|
|
st_rdev: 0,
|
|
|
|
st_size: 0,
|
|
|
|
st_blksize: 0,
|
|
|
|
st_blocks: 0,
|
|
|
|
st_atime: 0,
|
|
|
|
st_atime_nsec: 0,
|
|
|
|
st_mtime: 0,
|
|
|
|
st_mtime_nsec: 0,
|
|
|
|
st_ctime: 0,
|
|
|
|
st_ctime_nsec: 0,
|
|
|
|
__unused: [0, 0, 0],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "freebsd")]
|
|
|
|
mod stat {
|
|
|
|
#[cfg(target_arch = "x86_64")]
|
|
|
|
pub mod arch {
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
|
|
|
|
2012-11-09 19:50:23 -06:00
|
|
|
pub fn default_stat() -> libc::stat {
|
|
|
|
libc::stat {
|
|
|
|
st_dev: 0,
|
|
|
|
st_ino: 0,
|
|
|
|
st_mode: 0,
|
|
|
|
st_nlink: 0,
|
|
|
|
st_uid: 0,
|
|
|
|
st_gid: 0,
|
|
|
|
st_rdev: 0,
|
|
|
|
st_atime: 0,
|
|
|
|
st_atime_nsec: 0,
|
|
|
|
st_mtime: 0,
|
|
|
|
st_mtime_nsec: 0,
|
|
|
|
st_ctime: 0,
|
|
|
|
st_ctime_nsec: 0,
|
|
|
|
st_size: 0,
|
|
|
|
st_blocks: 0,
|
|
|
|
st_blksize: 0,
|
|
|
|
st_flags: 0,
|
|
|
|
st_gen: 0,
|
|
|
|
st_lspare: 0,
|
|
|
|
st_birthtime: 0,
|
|
|
|
st_birthtime_nsec: 0,
|
|
|
|
__unused: [0, 0],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "macos")]
|
|
|
|
mod stat {
|
|
|
|
pub mod arch {
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
|
|
|
|
2012-11-09 19:50:23 -06:00
|
|
|
pub fn default_stat() -> libc::stat {
|
|
|
|
libc::stat {
|
|
|
|
st_dev: 0,
|
|
|
|
st_mode: 0,
|
|
|
|
st_nlink: 0,
|
|
|
|
st_ino: 0,
|
|
|
|
st_uid: 0,
|
|
|
|
st_gid: 0,
|
|
|
|
st_rdev: 0,
|
|
|
|
st_atime: 0,
|
|
|
|
st_atime_nsec: 0,
|
|
|
|
st_mtime: 0,
|
|
|
|
st_mtime_nsec: 0,
|
|
|
|
st_ctime: 0,
|
|
|
|
st_ctime_nsec: 0,
|
|
|
|
st_birthtime: 0,
|
|
|
|
st_birthtime_nsec: 0,
|
|
|
|
st_size: 0,
|
|
|
|
st_blocks: 0,
|
|
|
|
st_blksize: 0,
|
|
|
|
st_flags: 0,
|
|
|
|
st_gen: 0,
|
|
|
|
st_lspare: 0,
|
|
|
|
st_qspare: [0, 0],
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-21 17:35:47 -06:00
|
|
|
#[cfg(target_os = "win32")]
|
2012-11-09 19:50:23 -06:00
|
|
|
mod stat {
|
|
|
|
pub mod arch {
|
2013-01-04 17:38:56 -06:00
|
|
|
use libc;
|
2012-11-09 19:50:23 -06:00
|
|
|
pub fn default_stat() -> libc::stat {
|
|
|
|
libc::stat {
|
|
|
|
st_dev: 0,
|
|
|
|
st_ino: 0,
|
|
|
|
st_mode: 0,
|
|
|
|
st_nlink: 0,
|
|
|
|
st_uid: 0,
|
|
|
|
st_gid: 0,
|
|
|
|
st_rdev: 0,
|
|
|
|
st_size: 0,
|
|
|
|
st_atime: 0,
|
|
|
|
st_mtime: 0,
|
|
|
|
st_ctime: 0,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-02-26 19:47:41 -06:00
|
|
|
pub impl Path {
|
2012-11-09 19:50:23 -06:00
|
|
|
fn stat(&self) -> Option<libc::stat> {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
do str::as_c_str(self.to_str()) |buf| {
|
|
|
|
let mut st = stat::arch::default_stat();
|
2013-02-14 18:00:04 -06:00
|
|
|
let r = libc::stat(buf, &mut st);
|
2012-11-09 19:50:23 -06:00
|
|
|
|
2013-02-15 02:51:28 -06:00
|
|
|
if r == 0 { Some(st) } else { None }
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-11-09 19:50:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-21 17:35:47 -06:00
|
|
|
#[cfg(unix)]
|
2012-11-09 19:50:23 -06:00
|
|
|
fn lstat(&self) -> Option<libc::stat> {
|
2013-01-10 23:23:07 -06:00
|
|
|
unsafe {
|
|
|
|
do str::as_c_str(self.to_str()) |buf| {
|
|
|
|
let mut st = stat::arch::default_stat();
|
2013-02-14 18:00:04 -06:00
|
|
|
let r = libc::lstat(buf, &mut st);
|
2012-11-09 19:50:23 -06:00
|
|
|
|
2013-02-15 02:51:28 -06:00
|
|
|
if r == 0 { Some(st) } else { None }
|
2013-01-10 23:23:07 -06:00
|
|
|
}
|
2012-11-09 19:50:23 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn exists(&self) -> bool {
|
|
|
|
match self.stat() {
|
|
|
|
None => false,
|
|
|
|
Some(_) => true,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_size(&self) -> Option<i64> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => Some(st.st_size as i64),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_mode(&self) -> Option<uint> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => Some(st.st_mode as uint),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "freebsd")]
|
|
|
|
#[cfg(target_os = "linux")]
|
|
|
|
#[cfg(target_os = "macos")]
|
2013-02-26 19:47:41 -06:00
|
|
|
pub impl Path {
|
2012-11-09 19:50:23 -06:00
|
|
|
fn get_atime(&self) -> Option<(i64, int)> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => {
|
|
|
|
Some((st.st_atime as i64,
|
|
|
|
st.st_atime_nsec as int))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_mtime(&self) -> Option<(i64, int)> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => {
|
|
|
|
Some((st.st_mtime as i64,
|
|
|
|
st.st_mtime_nsec as int))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_ctime(&self) -> Option<(i64, int)> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => {
|
|
|
|
Some((st.st_ctime as i64,
|
|
|
|
st.st_ctime_nsec as int))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "freebsd")]
|
|
|
|
#[cfg(target_os = "macos")]
|
2013-02-26 19:47:41 -06:00
|
|
|
pub impl Path {
|
2012-11-09 19:50:23 -06:00
|
|
|
fn get_birthtime(&self) -> Option<(i64, int)> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => {
|
|
|
|
Some((st.st_birthtime as i64,
|
|
|
|
st.st_birthtime_nsec as int))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(target_os = "win32")]
|
2013-02-26 19:47:41 -06:00
|
|
|
pub impl Path {
|
2012-11-09 19:50:23 -06:00
|
|
|
fn get_atime(&self) -> Option<(i64, int)> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => {
|
|
|
|
Some((st.st_atime as i64, 0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_mtime(&self) -> Option<(i64, int)> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => {
|
|
|
|
Some((st.st_mtime as i64, 0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_ctime(&self) -> Option<(i64, int)> {
|
|
|
|
match self.stat() {
|
|
|
|
None => None,
|
|
|
|
Some(ref st) => {
|
|
|
|
Some((st.st_ctime as i64, 0))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl ToStr for PosixPath {
|
2013-02-03 22:47:26 -06:00
|
|
|
pure fn to_str(&self) -> ~str {
|
2012-08-29 15:25:31 -05:00
|
|
|
let mut s = ~"";
|
|
|
|
if self.is_absolute {
|
|
|
|
s += "/";
|
2012-06-24 22:18:18 -05:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
s + str::connect(self.components, "/")
|
2012-06-24 22:18:18 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2012-08-29 15:25:31 -05:00
|
|
|
// FIXME (#3227): when default methods in traits are working, de-duplicate
|
|
|
|
// PosixPath and WindowsPath, most of their methods are common.
|
2013-02-14 13:47:00 -06:00
|
|
|
impl GenericPath for PosixPath {
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-21 21:07:54 -05:00
|
|
|
pure fn from_str(s: &str) -> PosixPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
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,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: components }
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn dirname(&self) -> ~str {
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2012-08-29 15:25:31 -05:00
|
|
|
let s = self.dir_path().to_str();
|
|
|
|
if s.len() == 0 {
|
|
|
|
~"."
|
|
|
|
} else {
|
2013-02-15 02:51:28 -06:00
|
|
|
s
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn filename(&self) -> Option<~str> {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.components.len() {
|
|
|
|
0 => None,
|
|
|
|
n => Some(copy self.components[n - 1])
|
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn filestem(&self) -> Option<~str> {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filename() {
|
|
|
|
None => None,
|
|
|
|
Some(ref f) => {
|
|
|
|
match str::rfind_char(*f, '.') {
|
2013-03-21 06:36:21 -05:00
|
|
|
Some(p) => Some(f.slice(0, p).to_owned()),
|
2012-08-29 15:25:31 -05:00
|
|
|
None => Some(copy *f)
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn filetype(&self) -> Option<~str> {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filename() {
|
|
|
|
None => None,
|
|
|
|
Some(ref f) => {
|
|
|
|
match str::rfind_char(*f, '.') {
|
2013-03-21 06:36:21 -05:00
|
|
|
Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()),
|
2012-08-29 15:25:31 -05:00
|
|
|
_ => None
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_dirname(&self, d: &str) -> PosixPath {
|
2012-11-17 22:23:44 -06:00
|
|
|
let dpath = PosixPath(d);
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filename() {
|
|
|
|
Some(ref f) => dpath.push(*f),
|
2013-02-15 02:51:28 -06:00
|
|
|
None => dpath
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_filename(&self, f: &str) -> PosixPath {
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(! str::any(f, |c| windows::is_sep(c as u8)));
|
2012-08-29 15:25:31 -05:00
|
|
|
self.dir_path().push(f)
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_filestem(&self, s: &str) -> PosixPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filetype() {
|
|
|
|
None => self.with_filename(s),
|
2012-09-18 13:19:52 -05:00
|
|
|
Some(ref t) => self.with_filename(str::from_slice(s) + *t)
|
2012-05-08 19:33:48 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_filetype(&self, t: &str) -> PosixPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
if t.len() == 0 {
|
|
|
|
match self.filestem() {
|
2013-03-04 21:36:15 -06:00
|
|
|
None => copy *self,
|
2012-09-28 15:00:07 -05:00
|
|
|
Some(ref s) => self.with_filename(*s)
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
} else {
|
2012-08-29 15:25:31 -05:00
|
|
|
let t = ~"." + str::from_slice(t);
|
|
|
|
match self.filestem() {
|
|
|
|
None => self.with_filename(t),
|
2012-09-18 13:19:52 -05:00
|
|
|
Some(ref s) => self.with_filename(*s + t)
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn dir_path(&self) -> PosixPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
if self.components.len() != 0 {
|
|
|
|
self.pop()
|
2012-03-02 19:20:00 -06:00
|
|
|
} else {
|
2013-03-04 21:36:15 -06:00
|
|
|
copy *self
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn file_path(&self) -> PosixPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
let cs = match self.filename() {
|
|
|
|
None => ~[],
|
|
|
|
Some(ref f) => ~[copy *f]
|
|
|
|
};
|
|
|
|
return PosixPath { is_absolute: false,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: cs }
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn push_rel(&self, other: &PosixPath) -> PosixPath {
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(!other.is_absolute);
|
2012-08-29 15:25:31 -05:00
|
|
|
self.push_many(other.components)
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn unsafe_join(&self, other: &PosixPath) -> PosixPath {
|
2013-02-18 16:48:18 -06:00
|
|
|
if other.is_absolute {
|
|
|
|
PosixPath { is_absolute: true,
|
|
|
|
components: copy other.components }
|
|
|
|
} else {
|
|
|
|
self.push_rel(other)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn is_restricted(&self) -> bool {
|
2013-02-18 19:54:05 -06:00
|
|
|
false
|
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn push_many(&self, cs: &[~str]) -> PosixPath {
|
2012-09-13 21:34:18 -05:00
|
|
|
let mut v = copy self.components;
|
|
|
|
for cs.each |e| {
|
2012-09-19 18:55:01 -05:00
|
|
|
let mut ss = str::split_nonempty(
|
|
|
|
*e,
|
|
|
|
|c| windows::is_sep(c as u8));
|
2013-02-15 02:51:28 -06:00
|
|
|
unsafe { v.push_all_move(ss); }
|
2012-09-13 21:34:18 -05:00
|
|
|
}
|
2012-09-19 00:35:28 -05:00
|
|
|
PosixPath { is_absolute: self.is_absolute,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: v }
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn push(&self, s: &str) -> PosixPath {
|
2012-09-13 21:34:18 -05:00
|
|
|
let mut v = copy self.components;
|
|
|
|
let mut ss = str::split_nonempty(s, |c| windows::is_sep(c as u8));
|
2013-02-15 02:51:28 -06:00
|
|
|
unsafe { v.push_all_move(ss); }
|
2013-03-04 21:36:15 -06:00
|
|
|
PosixPath { components: v, ..copy *self }
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn pop(&self) -> PosixPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
let mut cs = copy self.components;
|
|
|
|
if cs.len() != 0 {
|
2012-09-28 00:20:47 -05:00
|
|
|
unsafe { cs.pop(); }
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-09-19 00:35:28 -05:00
|
|
|
return PosixPath {
|
|
|
|
is_absolute: self.is_absolute,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: cs
|
2012-09-19 00:35:28 -05:00
|
|
|
}
|
|
|
|
//..self }
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2012-08-29 15:59:02 -05:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn normalize(&self) -> PosixPath {
|
2012-08-29 15:59:02 -05:00
|
|
|
return PosixPath {
|
2012-09-19 00:35:28 -05:00
|
|
|
is_absolute: self.is_absolute,
|
|
|
|
components: normalize(self.components)
|
|
|
|
// ..self
|
2012-08-29 15:59:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl ToStr for WindowsPath {
|
2013-02-03 22:47:26 -06:00
|
|
|
pure fn to_str(&self) -> ~str {
|
2012-08-29 15:25:31 -05:00
|
|
|
let mut s = ~"";
|
|
|
|
match self.host {
|
2012-09-28 15:00:07 -05:00
|
|
|
Some(ref h) => { s += "\\\\"; s += *h; }
|
2012-08-29 15:25:31 -05:00
|
|
|
None => { }
|
|
|
|
}
|
|
|
|
match self.device {
|
2012-09-28 15:00:07 -05:00
|
|
|
Some(ref d) => { s += *d; s += ":"; }
|
2012-08-29 15:25:31 -05:00
|
|
|
None => { }
|
|
|
|
}
|
|
|
|
if self.is_absolute {
|
|
|
|
s += "\\";
|
|
|
|
}
|
|
|
|
s + str::connect(self.components, "\\")
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2013-02-14 13:47:00 -06:00
|
|
|
impl GenericPath for WindowsPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2013-03-21 21:07:54 -05:00
|
|
|
pure fn from_str(s: &str) -> WindowsPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
let host;
|
|
|
|
let device;
|
|
|
|
let rest;
|
|
|
|
|
|
|
|
match windows::extract_drive_prefix(s) {
|
|
|
|
Some((ref d, ref r)) => {
|
|
|
|
host = None;
|
|
|
|
device = Some(copy *d);
|
|
|
|
rest = copy *r;
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
match windows::extract_unc_prefix(s) {
|
|
|
|
Some((ref h, ref r)) => {
|
|
|
|
host = Some(copy *h);
|
|
|
|
device = None;
|
|
|
|
rest = copy *r;
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
host = None;
|
|
|
|
device = None;
|
|
|
|
rest = str::from_slice(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut components =
|
|
|
|
str::split_nonempty(rest, |c| windows::is_sep(c as u8));
|
|
|
|
let is_absolute = (rest.len() != 0 && windows::is_sep(rest[0]));
|
2013-02-15 02:51:28 -06:00
|
|
|
return WindowsPath { host: host,
|
|
|
|
device: device,
|
2012-08-29 15:25:31 -05:00
|
|
|
is_absolute: is_absolute,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: components }
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn dirname(&self) -> ~str {
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2012-08-29 15:25:31 -05:00
|
|
|
let s = self.dir_path().to_str();
|
|
|
|
if s.len() == 0 {
|
|
|
|
~"."
|
|
|
|
} else {
|
2013-02-15 02:51:28 -06:00
|
|
|
s
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn filename(&self) -> Option<~str> {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.components.len() {
|
|
|
|
0 => None,
|
|
|
|
n => Some(copy self.components[n - 1])
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn filestem(&self) -> Option<~str> {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filename() {
|
|
|
|
None => None,
|
|
|
|
Some(ref f) => {
|
|
|
|
match str::rfind_char(*f, '.') {
|
2013-03-21 06:36:21 -05:00
|
|
|
Some(p) => Some(f.slice(0, p).to_owned()),
|
2012-08-29 15:25:31 -05:00
|
|
|
None => Some(copy *f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn filetype(&self) -> Option<~str> {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filename() {
|
|
|
|
None => None,
|
|
|
|
Some(ref f) => {
|
|
|
|
match str::rfind_char(*f, '.') {
|
2013-03-21 06:36:21 -05:00
|
|
|
Some(p) if p < f.len() => Some(f.slice(p, f.len()).to_owned()),
|
2012-08-29 15:25:31 -05:00
|
|
|
_ => None
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_dirname(&self, d: &str) -> WindowsPath {
|
2012-11-17 22:23:44 -06:00
|
|
|
let dpath = WindowsPath(d);
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filename() {
|
|
|
|
Some(ref f) => dpath.push(*f),
|
2013-02-15 02:51:28 -06:00
|
|
|
None => dpath
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_filename(&self, f: &str) -> WindowsPath {
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(! str::any(f, |c| windows::is_sep(c as u8)));
|
2012-08-29 15:25:31 -05:00
|
|
|
self.dir_path().push(f)
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_filestem(&self, s: &str) -> WindowsPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
match self.filetype() {
|
|
|
|
None => self.with_filename(s),
|
2012-09-18 13:19:52 -05:00
|
|
|
Some(ref t) => self.with_filename(str::from_slice(s) + *t)
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn with_filetype(&self, t: &str) -> WindowsPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
if t.len() == 0 {
|
|
|
|
match self.filestem() {
|
2013-03-04 21:36:15 -06:00
|
|
|
None => copy *self,
|
2012-09-28 15:00:07 -05:00
|
|
|
Some(ref s) => self.with_filename(*s)
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
let t = ~"." + str::from_slice(t);
|
|
|
|
match self.filestem() {
|
|
|
|
None => self.with_filename(t),
|
|
|
|
Some(ref s) =>
|
|
|
|
self.with_filename(*s + t)
|
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn dir_path(&self) -> WindowsPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
if self.components.len() != 0 {
|
|
|
|
self.pop()
|
|
|
|
} else {
|
2013-03-04 21:36:15 -06:00
|
|
|
copy *self
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn file_path(&self) -> WindowsPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
let cs = match self.filename() {
|
|
|
|
None => ~[],
|
|
|
|
Some(ref f) => ~[copy *f]
|
|
|
|
};
|
|
|
|
return WindowsPath { host: None,
|
|
|
|
device: None,
|
|
|
|
is_absolute: false,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: cs }
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn push_rel(&self, other: &WindowsPath) -> WindowsPath {
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(!other.is_absolute);
|
2012-08-29 15:25:31 -05:00
|
|
|
self.push_many(other.components)
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn unsafe_join(&self, other: &WindowsPath) -> WindowsPath {
|
2013-02-18 19:34:48 -06:00
|
|
|
/* rhs not absolute is simple push */
|
2013-02-18 16:48:18 -06:00
|
|
|
if !other.is_absolute {
|
2013-02-18 19:34:48 -06:00
|
|
|
return self.push_many(other.components);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if rhs has a host set, then the whole thing wins */
|
|
|
|
match other.host {
|
|
|
|
Some(copy host) => {
|
|
|
|
return WindowsPath {
|
|
|
|
host: Some(host),
|
|
|
|
device: copy other.device,
|
|
|
|
is_absolute: true,
|
|
|
|
components: copy other.components
|
|
|
|
};
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* if rhs has a device set, then a part wins */
|
|
|
|
match other.device {
|
|
|
|
Some(copy device) => {
|
|
|
|
return WindowsPath {
|
|
|
|
host: None,
|
|
|
|
device: Some(device),
|
|
|
|
is_absolute: true,
|
|
|
|
components: copy other.components
|
|
|
|
};
|
2013-02-18 16:48:18 -06:00
|
|
|
}
|
2013-02-18 19:34:48 -06:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* fallback: host and device of lhs win, but the
|
|
|
|
whole path of the right */
|
|
|
|
WindowsPath {
|
|
|
|
host: copy self.host,
|
|
|
|
device: copy self.device,
|
|
|
|
is_absolute: self.is_absolute || other.is_absolute,
|
|
|
|
components: copy other.components
|
2013-02-18 16:48:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn is_restricted(&self) -> bool {
|
2013-02-18 19:54:05 -06:00
|
|
|
match self.filestem() {
|
|
|
|
Some(stem) => {
|
|
|
|
match stem.to_lower() {
|
|
|
|
~"con" | ~"aux" | ~"com1" | ~"com2" | ~"com3" | ~"com4" |
|
|
|
|
~"lpt1" | ~"lpt2" | ~"lpt3" | ~"prn" | ~"nul" => true,
|
|
|
|
_ => false
|
|
|
|
}
|
|
|
|
},
|
|
|
|
None => false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn push_many(&self, cs: &[~str]) -> WindowsPath {
|
2012-09-13 21:34:18 -05:00
|
|
|
let mut v = copy self.components;
|
|
|
|
for cs.each |e| {
|
2012-09-19 18:55:01 -05:00
|
|
|
let mut ss = str::split_nonempty(
|
|
|
|
*e,
|
|
|
|
|c| windows::is_sep(c as u8));
|
2013-02-15 02:51:28 -06:00
|
|
|
unsafe { v.push_all_move(ss); }
|
2012-09-13 21:34:18 -05:00
|
|
|
}
|
2012-09-19 00:35:28 -05:00
|
|
|
// tedious, but as-is, we can't use ..self
|
|
|
|
return WindowsPath {
|
|
|
|
host: copy self.host,
|
|
|
|
device: copy self.device,
|
|
|
|
is_absolute: self.is_absolute,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: v
|
2012-09-19 00:35:28 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn push(&self, s: &str) -> WindowsPath {
|
2012-09-13 21:34:18 -05:00
|
|
|
let mut v = copy self.components;
|
|
|
|
let mut ss = str::split_nonempty(s, |c| windows::is_sep(c as u8));
|
2013-02-15 02:51:28 -06:00
|
|
|
unsafe { v.push_all_move(ss); }
|
2013-03-04 21:36:15 -06:00
|
|
|
return WindowsPath { components: v, ..copy *self }
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn pop(&self) -> WindowsPath {
|
2012-08-29 15:25:31 -05:00
|
|
|
let mut cs = copy self.components;
|
|
|
|
if cs.len() != 0 {
|
2012-09-28 00:20:47 -05:00
|
|
|
unsafe { cs.pop(); }
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-09-19 00:35:28 -05:00
|
|
|
return WindowsPath {
|
|
|
|
host: copy self.host,
|
|
|
|
device: copy self.device,
|
|
|
|
is_absolute: self.is_absolute,
|
2013-02-15 02:51:28 -06:00
|
|
|
components: cs
|
2012-09-19 00:35:28 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2012-08-29 15:59:02 -05:00
|
|
|
|
2013-03-04 21:36:15 -06:00
|
|
|
pure fn normalize(&self) -> WindowsPath {
|
2012-08-29 15:59:02 -05:00
|
|
|
return WindowsPath {
|
2012-09-19 00:35:28 -05:00
|
|
|
host: copy self.host,
|
2013-02-18 19:34:48 -06:00
|
|
|
device: match self.device {
|
|
|
|
None => None,
|
|
|
|
Some(ref device) => Some(device.to_upper())
|
|
|
|
},
|
2012-09-19 00:35:28 -05:00
|
|
|
is_absolute: self.is_absolute,
|
|
|
|
components: normalize(self.components)
|
2012-08-29 15:59:02 -05:00
|
|
|
}
|
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2012-09-27 17:44:09 -05:00
|
|
|
pub pure fn normalize(components: &[~str]) -> ~[~str] {
|
2012-08-29 15:25:31 -05:00
|
|
|
let mut cs = ~[];
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2012-08-29 15:25:31 -05:00
|
|
|
for components.each |c| {
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2012-09-19 18:55:01 -05:00
|
|
|
if *c == ~"." && components.len() > 1 { loop; }
|
|
|
|
if *c == ~"" { loop; }
|
|
|
|
if *c == ~".." && cs.len() != 0 {
|
2012-09-28 00:20:47 -05:00
|
|
|
cs.pop();
|
2012-09-07 17:32:04 -05:00
|
|
|
loop;
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-09-26 19:33:34 -05:00
|
|
|
cs.push(copy *c);
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
2013-02-15 02:51:28 -06:00
|
|
|
cs
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
// Various windows helpers, and tests for the impl.
|
2012-12-27 19:53:04 -06:00
|
|
|
pub mod windows {
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
2013-01-08 21:37:25 -06:00
|
|
|
use option::{None, Option, Some};
|
2012-12-23 16:41:37 -06:00
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
#[inline(always)]
|
|
|
|
pub pure fn is_sep(u: u8) -> bool {
|
|
|
|
u == '/' as u8 || u == '\\' as u8
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
pub pure fn extract_unc_prefix(s: &str) -> Option<(~str,~str)> {
|
|
|
|
if (s.len() > 1 &&
|
2013-02-18 19:34:48 -06:00
|
|
|
(s[0] == '\\' as u8 || s[0] == '/' as u8) &&
|
|
|
|
s[0] == s[1]) {
|
2012-11-17 22:09:51 -06:00
|
|
|
let mut i = 2;
|
|
|
|
while i < s.len() {
|
2013-02-18 19:34:48 -06:00
|
|
|
if is_sep(s[i]) {
|
2013-03-21 06:36:21 -05:00
|
|
|
let pre = s.slice(2, i).to_owned();
|
|
|
|
let mut rest = s.slice(i, s.len()).to_owned();
|
2013-02-15 02:51:28 -06:00
|
|
|
return Some((pre, rest));
|
2012-11-17 22:09:51 -06:00
|
|
|
}
|
|
|
|
i += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
None
|
|
|
|
}
|
2012-08-29 15:59:02 -05:00
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
pub pure fn extract_drive_prefix(s: &str) -> Option<(~str,~str)> {
|
|
|
|
unsafe {
|
|
|
|
if (s.len() > 1 &&
|
|
|
|
libc::isalpha(s[0] as libc::c_int) != 0 &&
|
|
|
|
s[1] == ':' as u8) {
|
|
|
|
let rest = if s.len() == 2 {
|
|
|
|
~""
|
|
|
|
} else {
|
2013-03-21 06:36:21 -05:00
|
|
|
s.slice(2, s.len()).to_owned()
|
2012-11-17 22:09:51 -06:00
|
|
|
};
|
2013-03-21 06:36:21 -05:00
|
|
|
return Some((s.slice(0,1).to_owned(), rest));
|
2012-11-17 22:09:51 -06:00
|
|
|
}
|
|
|
|
None
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
2012-08-29 15:59:02 -05:00
|
|
|
}
|
2012-11-17 22:09:51 -06:00
|
|
|
}
|
|
|
|
|
2012-11-09 19:50:23 -06:00
|
|
|
#[cfg(test)]
|
2012-11-17 22:09:51 -06:00
|
|
|
mod tests {
|
2013-01-08 21:37:25 -06:00
|
|
|
use option::{None, Some};
|
|
|
|
use path::{PosixPath, WindowsPath, windows};
|
2012-12-27 19:53:04 -06:00
|
|
|
use str;
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
#[test]
|
|
|
|
fn test_double_slash_collapsing() {
|
|
|
|
let path = PosixPath("tmp/");
|
|
|
|
let path = path.push("/hmm");
|
|
|
|
let path = path.normalize();
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(~"tmp/hmm" == path.to_str());
|
2012-11-17 22:09:51 -06:00
|
|
|
|
|
|
|
let path = WindowsPath("tmp/");
|
|
|
|
let path = path.push("/hmm");
|
|
|
|
let path = path.normalize();
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(~"tmp\\hmm" == path.to_str());
|
2012-11-17 22:09:51 -06:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2012-09-18 13:19:52 -05:00
|
|
|
#[test]
|
|
|
|
fn test_filetype_foo_bar() {
|
2012-11-17 22:09:51 -06:00
|
|
|
let wp = PosixPath("foo.bar");
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(wp.filetype() == Some(~".bar"));
|
2012-11-17 22:09:51 -06:00
|
|
|
|
|
|
|
let wp = WindowsPath("foo.bar");
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(wp.filetype() == Some(~".bar"));
|
2012-09-18 13:19:52 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_filetype_foo() {
|
2012-11-17 22:09:51 -06:00
|
|
|
let wp = PosixPath("foo");
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(wp.filetype() == None);
|
2012-11-17 22:09:51 -06:00
|
|
|
|
|
|
|
let wp = WindowsPath("foo");
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(wp.filetype() == None);
|
2012-09-18 13:19:52 -05:00
|
|
|
}
|
|
|
|
|
2012-08-29 15:59:02 -05:00
|
|
|
#[test]
|
|
|
|
fn test_posix_paths() {
|
2012-11-17 22:09:51 -06:00
|
|
|
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);
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(ss == sss);
|
2012-11-17 22:09:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t(&(PosixPath("hi")), "hi");
|
|
|
|
t(&(PosixPath("/lib")), "/lib");
|
|
|
|
t(&(PosixPath("hi/there")), "hi/there");
|
|
|
|
t(&(PosixPath("hi/there.txt")), "hi/there.txt");
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("hi/there.txt")), "hi/there.txt");
|
|
|
|
t(&(PosixPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("")), "hi/there");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("/a/b/c/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_dirname("hi")), "hi/there.txt");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("hi/there.txt")
|
2012-08-29 15:59:02 -05:00
|
|
|
.with_dirname(".")), "./there.txt");
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("a/b/c")
|
2012-08-29 15:59:02 -05:00
|
|
|
.push("..")), "a/b/c/..");
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")), "there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")), "hi/there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")
|
|
|
|
.with_dirname("/usr/lib")),
|
|
|
|
"/usr/lib/there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")
|
|
|
|
.with_dirname("/usr/lib/")),
|
|
|
|
"/usr/lib/there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")
|
|
|
|
.with_dirname("/usr//lib//")),
|
|
|
|
"/usr/lib/there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("/usr/bin/rust")
|
2012-08-29 15:25:31 -05:00
|
|
|
.push_many([~"lib", ~"thingy.so"])
|
|
|
|
.with_filestem("librustc")),
|
|
|
|
"/usr/bin/rust/lib/librustc.so");
|
|
|
|
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
2012-08-29 15:59:02 -05:00
|
|
|
#[test]
|
|
|
|
fn test_normalize() {
|
2012-11-17 22:09:51 -06:00
|
|
|
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);
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(ss == sss);
|
2012-11-17 22:09:51 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
t(&(PosixPath("hi/there.txt")
|
2012-08-29 15:59:02 -05:00
|
|
|
.with_dirname(".").normalize()), "there.txt");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("a/b/../c/././/../foo.txt/").normalize()),
|
2012-08-29 15:59:02 -05:00
|
|
|
"a/foo.txt");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(PosixPath("a/b/c")
|
2012-08-29 15:59:02 -05:00
|
|
|
.push("..").normalize()), "a/b");
|
|
|
|
}
|
2012-03-02 19:20:00 -06:00
|
|
|
|
|
|
|
#[test]
|
2012-08-29 15:25:31 -05:00
|
|
|
fn test_extract_unc_prefixes() {
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(windows::extract_unc_prefix("\\\\").is_none());
|
|
|
|
fail_unless!(windows::extract_unc_prefix("//").is_none());
|
|
|
|
fail_unless!(windows::extract_unc_prefix("\\\\hi").is_none());
|
|
|
|
fail_unless!(windows::extract_unc_prefix("//hi").is_none());
|
|
|
|
fail_unless!(windows::extract_unc_prefix("\\\\hi\\") ==
|
|
|
|
Some((~"hi", ~"\\")));
|
|
|
|
fail_unless!(windows::extract_unc_prefix("//hi\\") ==
|
|
|
|
Some((~"hi", ~"\\")));
|
|
|
|
fail_unless!(windows::extract_unc_prefix("\\\\hi\\there") ==
|
|
|
|
Some((~"hi", ~"\\there")));
|
|
|
|
fail_unless!(windows::extract_unc_prefix("//hi/there") ==
|
|
|
|
Some((~"hi", ~"/there")));
|
|
|
|
fail_unless!(windows::extract_unc_prefix(
|
|
|
|
"\\\\hi\\there\\friends.txt") ==
|
|
|
|
Some((~"hi", ~"\\there\\friends.txt")));
|
|
|
|
fail_unless!(windows::extract_unc_prefix(
|
|
|
|
"//hi\\there\\friends.txt") ==
|
|
|
|
Some((~"hi", ~"\\there\\friends.txt")));
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-08-29 15:25:31 -05:00
|
|
|
fn test_extract_drive_prefixes() {
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(windows::extract_drive_prefix("c").is_none());
|
|
|
|
fail_unless!(windows::extract_drive_prefix("c:") ==
|
|
|
|
Some((~"c", ~"")));
|
|
|
|
fail_unless!(windows::extract_drive_prefix("d:") ==
|
|
|
|
Some((~"d", ~"")));
|
|
|
|
fail_unless!(windows::extract_drive_prefix("z:") ==
|
|
|
|
Some((~"z", ~"")));
|
|
|
|
fail_unless!(windows::extract_drive_prefix("c:\\hi") ==
|
|
|
|
Some((~"c", ~"\\hi")));
|
|
|
|
fail_unless!(windows::extract_drive_prefix("d:hi") ==
|
|
|
|
Some((~"d", ~"hi")));
|
|
|
|
fail_unless!(windows::extract_drive_prefix("c:hi\\there.txt") ==
|
|
|
|
Some((~"c", ~"hi\\there.txt")));
|
|
|
|
fail_unless!(windows::extract_drive_prefix("c:\\hi\\there.txt") ==
|
|
|
|
Some((~"c", ~"\\hi\\there.txt")));
|
2012-03-02 19:20:00 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2012-08-29 15:25:31 -05:00
|
|
|
fn test_windows_paths() {
|
|
|
|
fn t(wp: &WindowsPath, s: &str) {
|
|
|
|
let ss = wp.to_str();
|
|
|
|
let sss = str::from_slice(s);
|
|
|
|
if (ss != sss) {
|
|
|
|
debug!("got %s", ss);
|
|
|
|
debug!("expected %s", sss);
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(ss == sss);
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(WindowsPath("hi")), "hi");
|
|
|
|
t(&(WindowsPath("hi/there")), "hi\\there");
|
|
|
|
t(&(WindowsPath("hi/there.txt")), "hi\\there.txt");
|
2012-08-29 15:25:31 -05:00
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(WindowsPath("there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")), "there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(WindowsPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")), "hi\\there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(WindowsPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")
|
|
|
|
.with_dirname("c:\\program files A")),
|
|
|
|
"c:\\program files A\\there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(WindowsPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")
|
|
|
|
.with_dirname("c:\\program files B\\")),
|
|
|
|
"c:\\program files B\\there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(WindowsPath("hi/there.txt")
|
2012-08-29 15:25:31 -05:00
|
|
|
.with_filetype("o")
|
|
|
|
.with_dirname("c:\\program files C\\/")),
|
|
|
|
"c:\\program files C\\there.o");
|
|
|
|
|
2012-11-17 22:09:51 -06:00
|
|
|
t(&(WindowsPath("c:\\program files (x86)\\rust")
|
2012-08-29 15:25:31 -05:00
|
|
|
.push_many([~"lib", ~"thingy.dll"])
|
|
|
|
.with_filename("librustc.dll")),
|
|
|
|
"c:\\program files (x86)\\rust\\lib\\librustc.dll");
|
2013-02-18 19:34:48 -06:00
|
|
|
|
|
|
|
t(&(WindowsPath("\\\\computer\\share")
|
|
|
|
.unsafe_join(&WindowsPath("\\a"))),
|
|
|
|
"\\\\computer\\a");
|
|
|
|
|
|
|
|
t(&(WindowsPath("//computer/share")
|
|
|
|
.unsafe_join(&WindowsPath("\\a"))),
|
|
|
|
"\\\\computer\\a");
|
|
|
|
|
|
|
|
t(&(WindowsPath("//computer/share")
|
|
|
|
.unsafe_join(&WindowsPath("\\\\computer\\share"))),
|
|
|
|
"\\\\computer\\share");
|
|
|
|
|
|
|
|
t(&(WindowsPath("C:/whatever")
|
|
|
|
.unsafe_join(&WindowsPath("//computer/share/a/b"))),
|
|
|
|
"\\\\computer\\share\\a\\b");
|
|
|
|
|
|
|
|
t(&(WindowsPath("C:")
|
|
|
|
.unsafe_join(&WindowsPath("D:/foo"))),
|
|
|
|
"D:\\foo");
|
|
|
|
|
|
|
|
t(&(WindowsPath("C:")
|
|
|
|
.unsafe_join(&WindowsPath("B"))),
|
|
|
|
"C:B");
|
|
|
|
|
|
|
|
t(&(WindowsPath("C:")
|
|
|
|
.unsafe_join(&WindowsPath("/foo"))),
|
|
|
|
"C:\\foo");
|
|
|
|
|
|
|
|
t(&(WindowsPath("C:\\")
|
|
|
|
.unsafe_join(&WindowsPath("\\bar"))),
|
|
|
|
"C:\\bar");
|
|
|
|
|
|
|
|
t(&(WindowsPath("")
|
|
|
|
.unsafe_join(&WindowsPath(""))),
|
|
|
|
"");
|
|
|
|
|
|
|
|
t(&(WindowsPath("")
|
|
|
|
.unsafe_join(&WindowsPath("a"))),
|
|
|
|
"a");
|
|
|
|
|
|
|
|
t(&(WindowsPath("")
|
|
|
|
.unsafe_join(&WindowsPath("C:\\a"))),
|
|
|
|
"C:\\a");
|
|
|
|
|
|
|
|
t(&(WindowsPath("c:\\foo")
|
|
|
|
.normalize()),
|
|
|
|
"C:\\foo");
|
2012-09-18 13:19:52 -05:00
|
|
|
}
|
2013-02-18 19:54:05 -06:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_windows_path_restrictions() {
|
2013-03-06 15:58:02 -06:00
|
|
|
fail_unless!(WindowsPath("hi").is_restricted() == false);
|
|
|
|
fail_unless!(WindowsPath("C:\\NUL").is_restricted() == true);
|
|
|
|
fail_unless!(WindowsPath("C:\\COM1.TXT").is_restricted() == true);
|
|
|
|
fail_unless!(WindowsPath("c:\\prn.exe").is_restricted() == true);
|
2013-02-18 19:54:05 -06:00
|
|
|
}
|
2012-08-29 15:25:31 -05:00
|
|
|
}
|