|
@@ -119,7 +119,7 @@ assert!(css_url.serialize() == "http://servo.github.io/rust-url/main.css".to_str
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
-#![feature(core, std_misc, collections, old_path)]
|
|
|
|
|
|
|
+#![feature(core, std_misc, collections, old_path, path, os)]
|
|
|
|
|
|
|
|
extern crate "rustc-serialize" as rustc_serialize;
|
|
extern crate "rustc-serialize" as rustc_serialize;
|
|
|
|
|
|
|
@@ -129,6 +129,7 @@ extern crate matches;
|
|
|
use std::fmt::{self, Formatter};
|
|
use std::fmt::{self, Formatter};
|
|
|
use std::hash;
|
|
use std::hash;
|
|
|
use std::old_path as path;
|
|
use std::old_path as path;
|
|
|
|
|
+use std::path as new_path;
|
|
|
|
|
|
|
|
pub use host::{Host, Ipv6Address};
|
|
pub use host::{Host, Ipv6Address};
|
|
|
pub use parser::{ErrorHandler, ParseResult, ParseError};
|
|
pub use parser::{ErrorHandler, ParseResult, ParseError};
|
|
@@ -479,7 +480,7 @@ impl Url {
|
|
|
///
|
|
///
|
|
|
/// This returns `Err` if the given path is not absolute
|
|
/// This returns `Err` if the given path is not absolute
|
|
|
/// or, with a Windows path, if the prefix is not a disk prefix (e.g. `C:`).
|
|
/// or, with a Windows path, if the prefix is not a disk prefix (e.g. `C:`).
|
|
|
- pub fn from_file_path<T: ToUrlPath>(path: &T) -> Result<Url, ()> {
|
|
|
|
|
|
|
+ pub fn from_file_path<T: ToUrlPath + ?Sized>(path: &T) -> Result<Url, ()> {
|
|
|
let path = try!(path.to_url_path());
|
|
let path = try!(path.to_url_path());
|
|
|
Ok(Url::from_path_common(path))
|
|
Ok(Url::from_path_common(path))
|
|
|
}
|
|
}
|
|
@@ -501,7 +502,7 @@ impl Url {
|
|
|
/// as the base URL is `file:///var/index.html`, which might not be what was intended.
|
|
/// as the base URL is `file:///var/index.html`, which might not be what was intended.
|
|
|
///
|
|
///
|
|
|
/// (Note that `Path::new` removes any trailing slash.)
|
|
/// (Note that `Path::new` removes any trailing slash.)
|
|
|
- pub fn from_directory_path<T: ToUrlPath>(path: &T) -> Result<Url, ()> {
|
|
|
|
|
|
|
+ pub fn from_directory_path<T: ToUrlPath + ?Sized>(path: &T) -> Result<Url, ()> {
|
|
|
let mut path = try!(path.to_url_path());
|
|
let mut path = try!(path.to_url_path());
|
|
|
// Add an empty path component (i.e. a trailing slash in serialization)
|
|
// Add an empty path component (i.e. a trailing slash in serialization)
|
|
|
// so that the entire path is used as a base URL.
|
|
// so that the entire path is used as a base URL.
|
|
@@ -928,6 +929,51 @@ pub trait ToUrlPath {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+impl ToUrlPath for new_path::Path {
|
|
|
|
|
+ #[cfg(unix)]
|
|
|
|
|
+ fn to_url_path(&self) -> Result<Vec<String>, ()> {
|
|
|
|
|
+ use std::os::unix::prelude::*;
|
|
|
|
|
+ if !self.is_absolute() {
|
|
|
|
|
+ return Err(())
|
|
|
|
|
+ }
|
|
|
|
|
+ // skip the root component
|
|
|
|
|
+ Ok(self.components().skip(1).map(|c| {
|
|
|
|
|
+ percent_encode(c.as_os_str().as_bytes(), DEFAULT_ENCODE_SET)
|
|
|
|
|
+ }).collect())
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(windows)]
|
|
|
|
|
+ fn to_url_path(&self) -> Result<Vec<String>, ()> {
|
|
|
|
|
+ if !self.is_absolute() {
|
|
|
|
|
+ return Err(())
|
|
|
|
|
+ }
|
|
|
|
|
+ let mut components = self.components();
|
|
|
|
|
+ let disk = match components.next() {
|
|
|
|
|
+ Some(new_path::Component::Prefix {
|
|
|
|
|
+ parsed: new_path::Prefix::Disk(byte), ..
|
|
|
|
|
+ }) => byte,
|
|
|
|
|
+
|
|
|
|
|
+ // FIXME: do something with UNC and other prefixes?
|
|
|
|
|
+ _ => return Err(())
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ // Start with the prefix, e.g. "C:"
|
|
|
|
|
+ let mut path = vec![format!("{}:", disk as char)];
|
|
|
|
|
+
|
|
|
|
|
+ for component in components {
|
|
|
|
|
+ if component == new_path::Component::RootDir { continue }
|
|
|
|
|
+ // FIXME: somehow work with non-unicode?
|
|
|
|
|
+ let part = match component.as_os_str().to_str() {
|
|
|
|
|
+ Some(s) => s,
|
|
|
|
|
+ None => return Err(()),
|
|
|
|
|
+ };
|
|
|
|
|
+ path.push(percent_encode(part.as_bytes(), DEFAULT_ENCODE_SET));
|
|
|
|
|
+ }
|
|
|
|
|
+ Ok(path)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
impl ToUrlPath for path::posix::Path {
|
|
impl ToUrlPath for path::posix::Path {
|
|
|
fn to_url_path(&self) -> Result<Vec<String>, ()> {
|
|
fn to_url_path(&self) -> Result<Vec<String>, ()> {
|
|
|
if !self.is_absolute() {
|
|
if !self.is_absolute() {
|
|
@@ -963,6 +1009,58 @@ pub trait FromUrlPath {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+impl FromUrlPath for new_path::PathBuf {
|
|
|
|
|
+ #[cfg(unix)]
|
|
|
|
|
+ fn from_url_path(path: &[String]) -> Result<new_path::PathBuf, ()> {
|
|
|
|
|
+ use std::ffi::OsStr;
|
|
|
|
|
+ use std::os::unix::prelude::*;
|
|
|
|
|
+ use std::path::PathBuf;
|
|
|
|
|
+
|
|
|
|
|
+ if path.is_empty() {
|
|
|
|
|
+ return Ok(PathBuf::new("/"))
|
|
|
|
|
+ }
|
|
|
|
|
+ let mut bytes = Vec::new();
|
|
|
|
|
+ for path_part in path.iter() {
|
|
|
|
|
+ bytes.push(b'/');
|
|
|
|
|
+ percent_decode_to(path_part.as_bytes(), &mut bytes);
|
|
|
|
|
+ }
|
|
|
|
|
+ let os_str = <OsStr as OsStrExt>::from_bytes(&bytes);
|
|
|
|
|
+ let path = PathBuf::new(&os_str);
|
|
|
|
|
+ debug_assert!(path.is_absolute(),
|
|
|
|
|
+ "to_file_path() failed to produce an absolute Path");
|
|
|
|
|
+ Ok(path)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ #[cfg(windows)]
|
|
|
|
|
+ fn from_url_path(path: &[String]) -> Result<new_path::PathBuf, ()> {
|
|
|
|
|
+ use std::path::PathBuf;
|
|
|
|
|
+
|
|
|
|
|
+ if path.is_empty() {
|
|
|
|
|
+ return Err(())
|
|
|
|
|
+ }
|
|
|
|
|
+ let prefix = &*path[0];
|
|
|
|
|
+ if prefix.len() != 2 || !parser::starts_with_ascii_alpha(prefix)
|
|
|
|
|
+ || prefix.as_bytes()[1] != b':' {
|
|
|
|
|
+ return Err(())
|
|
|
|
|
+ }
|
|
|
|
|
+ let mut string = prefix.to_string();
|
|
|
|
|
+ for path_part in path[1..].iter() {
|
|
|
|
|
+ string.push('\\');
|
|
|
|
|
+
|
|
|
|
|
+ // Currently non-unicode windows paths cannot be represented
|
|
|
|
|
+ match String::from_utf8(percent_decode(path_part.as_bytes())) {
|
|
|
|
|
+ Ok(s) => string.push_str(&s),
|
|
|
|
|
+ Err(..) => return Err(()),
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ let path = PathBuf::new(&string);
|
|
|
|
|
+ debug_assert!(path.is_absolute(),
|
|
|
|
|
+ "to_file_path() failed to produce an absolute Path");
|
|
|
|
|
+ Ok(path)
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
impl FromUrlPath for path::posix::Path {
|
|
impl FromUrlPath for path::posix::Path {
|
|
|
fn from_url_path(path: &[String]) -> Result<path::posix::Path, ()> {
|
|
fn from_url_path(path: &[String]) -> Result<path::posix::Path, ()> {
|
|
|
if path.is_empty() {
|
|
if path.is_empty() {
|