diff --git a/Cargo.toml b/Cargo.toml index 54d163e0..695718e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,5 +21,6 @@ version = "0.2" optional = true [dependencies] +uuid = "0.1.17" rustc-serialize = "0.3" matches = "0.1" diff --git a/src/lib.rs b/src/lib.rs index f947214b..efaef148 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,6 +119,7 @@ assert!(css_url.serialize() == "http://servo.github.io/rust-url/main.css".to_str */ extern crate rustc_serialize; +extern crate uuid; #[macro_use] extern crate matches; @@ -136,6 +137,8 @@ use percent_encoding::{percent_encode, lossy_utf8_percent_decode, DEFAULT_ENCODE use format::{PathFormatter, UserInfoFormatter, UrlNoFragmentFormatter}; use encoding::EncodingOverride; +use uuid::Uuid; + mod encoding; mod host; mod parser; @@ -180,6 +183,20 @@ pub struct Url { pub fragment: Option, } +/// Opaque identifier for URLs that have file or other schemes +#[derive(PartialEq, Eq, Clone, Debug)] +pub struct OpaqueOrigin(Uuid); + +/// The origin of the URL +#[derive(PartialEq, Eq, Clone, Debug)] +pub enum Origin { + /// A globally unique identifier + UID(OpaqueOrigin), + + /// Consists of the URL's scheme, host and port + Tuple(String, Host, u16) +} + /// The components of the URL whose representation depends on where the scheme is *relative*. #[derive(PartialEq, Eq, Clone, Debug)] pub enum SchemeData { @@ -557,6 +574,26 @@ impl Url { self.to_string() } + // Return the origin of this URL (https://url.spec.whatwg.org/#origin) + pub fn origin(&self) -> Origin { + match &*self.scheme { + "blob" => { + let result = Url::parse(self.non_relative_scheme_data().unwrap()); + match result { + Ok(ref url) => url.origin(), + Err(_) => Origin::UID(OpaqueOrigin(Uuid::new_v4())) + } + }, + "ftp" | "gopher" | "http" | "https" | "ws" | "wss" => { + Origin::Tuple(self.scheme.clone(), self.host().unwrap().clone(), + self.port_or_default().unwrap()) + }, + // TODO: Figure out what to do if the scheme is a file + "file" => Origin::UID(OpaqueOrigin(Uuid::new_v4())), + _ => Origin::UID(OpaqueOrigin(Uuid::new_v4())) + } + } + /// Return the serialization of this URL, without the fragment identifier, as a string pub fn serialize_no_fragment(&self) -> String { UrlNoFragmentFormatter{ url: self }.to_string()