diff --git a/Cargo.toml b/Cargo.toml index eb2380599..38c7e3c5a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,5 +33,6 @@ version = "*" 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 7f5ac9618..fb7c48bc3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -122,6 +122,7 @@ assert!(css_url.serialize() == "http://servo.github.io/rust-url/main.css".to_str #![cfg_attr(feature="heap_size", plugin(heapsize_plugin))] extern crate rustc_serialize; +extern crate uuid; #[macro_use] extern crate matches; @@ -148,6 +149,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; @@ -193,6 +196,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, Hash, PartialOrd, Ord)] #[cfg_attr(feature="heap_size", derive(HeapSizeOf))] @@ -570,6 +587,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()