Просмотр исходного кода

No flat enums. [breaking-change]

Simon Sapin 12 лет назад
Родитель
Сommit
56d10e0f3d
5 измененных файлов с 169 добавлено и 192 удалено
  1. 20 25
      src/host.rs
  2. 55 63
      src/lib.rs
  3. 69 77
      src/parser.rs
  4. 7 8
      src/tests.rs
  5. 18 19
      src/urlutils.rs

+ 20 - 25
src/host.rs

@@ -6,15 +6,10 @@
 // option. This file may not be copied, modified, or distributed
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 // except according to those terms.
 
 
-pub use Host::{Domain,Ipv6};
-
 use std::ascii::OwnedAsciiExt;
 use std::ascii::OwnedAsciiExt;
 use std::cmp;
 use std::cmp;
 use std::fmt::{mod, Formatter, Show};
 use std::fmt::{mod, Formatter, Show};
-use parser::{
-    ParseResult,
-    InvalidIpv6Address, EmptyHost, NonAsciiDomainsNotSupportedYet, InvalidDomainCharacter,
-};
+use parser::{ParseResult, ParseError};
 use percent_encoding::{from_hex, percent_decode};
 use percent_encoding::{from_hex, percent_decode};
 
 
 
 
@@ -63,25 +58,25 @@ impl Host {
     /// FIXME: Add IDNA support for non-ASCII domains.
     /// FIXME: Add IDNA support for non-ASCII domains.
     pub fn parse(input: &str) -> ParseResult<Host> {
     pub fn parse(input: &str) -> ParseResult<Host> {
         if input.len() == 0 {
         if input.len() == 0 {
-            Err(EmptyHost)
+            Err(ParseError::EmptyHost)
         } else if input.starts_with("[") {
         } else if input.starts_with("[") {
             if input.ends_with("]") {
             if input.ends_with("]") {
-                Ipv6Address::parse(input.slice(1, input.len() - 1)).map(Ipv6)
+                Ipv6Address::parse(input.slice(1, input.len() - 1)).map(Host::Ipv6)
             } else {
             } else {
-                Err(InvalidIpv6Address)
+                Err(ParseError::InvalidIpv6Address)
             }
             }
         } else {
         } else {
             let decoded = percent_decode(input.as_bytes());
             let decoded = percent_decode(input.as_bytes());
             let domain = String::from_utf8_lossy(decoded.as_slice());
             let domain = String::from_utf8_lossy(decoded.as_slice());
             // TODO: Remove this check and use IDNA "domain to ASCII"
             // TODO: Remove this check and use IDNA "domain to ASCII"
             if !domain.as_slice().is_ascii() {
             if !domain.as_slice().is_ascii() {
-                Err(NonAsciiDomainsNotSupportedYet)
+                Err(ParseError::NonAsciiDomainsNotSupportedYet)
             } else if domain.as_slice().find([
             } else if domain.as_slice().find([
                 '\0', '\t', '\n', '\r', ' ', '#', '%', '/', ':', '?', '@', '[', '\\', ']'
                 '\0', '\t', '\n', '\r', ' ', '#', '%', '/', ':', '?', '@', '[', '\\', ']'
             ].as_slice()).is_some() {
             ].as_slice()).is_some() {
-                Err(InvalidDomainCharacter)
+                Err(ParseError::InvalidDomainCharacter)
             } else {
             } else {
-                Ok(Domain(domain.into_string().into_ascii_lower()))
+                Ok(Host::Domain(domain.into_string().into_ascii_lower()))
             }
             }
         }
         }
     }
     }
@@ -98,8 +93,8 @@ impl Host {
 impl Show for Host {
 impl Show for Host {
     fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
     fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
         match *self {
         match *self {
-            Domain(ref domain) => domain.fmt(formatter),
-            Ipv6(ref address) => {
+            Host::Domain(ref domain) => domain.fmt(formatter),
+            Host::Ipv6(ref address) => {
                 try!(formatter.write(b"["));
                 try!(formatter.write(b"["));
                 try!(address.fmt(formatter));
                 try!(address.fmt(formatter));
                 formatter.write(b"]")
                 formatter.write(b"]")
@@ -121,7 +116,7 @@ impl Ipv6Address {
         let mut i = 0u;
         let mut i = 0u;
         if input[0] == b':' {
         if input[0] == b':' {
             if input[1] != b':' {
             if input[1] != b':' {
-                return Err(InvalidIpv6Address)
+                return Err(ParseError::InvalidIpv6Address)
             }
             }
             i = 2;
             i = 2;
             piece_pointer = 1;
             piece_pointer = 1;
@@ -130,11 +125,11 @@ impl Ipv6Address {
 
 
         while i < len {
         while i < len {
             if piece_pointer == 8 {
             if piece_pointer == 8 {
-                return Err(InvalidIpv6Address)
+                return Err(ParseError::InvalidIpv6Address)
             }
             }
             if input[i] == b':' {
             if input[i] == b':' {
                 if compress_pointer.is_some() {
                 if compress_pointer.is_some() {
-                    return Err(InvalidIpv6Address)
+                    return Err(ParseError::InvalidIpv6Address)
                 }
                 }
                 i += 1;
                 i += 1;
                 piece_pointer += 1;
                 piece_pointer += 1;
@@ -157,7 +152,7 @@ impl Ipv6Address {
                 match input[i] {
                 match input[i] {
                     b'.' => {
                     b'.' => {
                         if i == start {
                         if i == start {
-                            return Err(InvalidIpv6Address)
+                            return Err(ParseError::InvalidIpv6Address)
                         }
                         }
                         i = start;
                         i = start;
                         is_ip_v4 = true;
                         is_ip_v4 = true;
@@ -165,10 +160,10 @@ impl Ipv6Address {
                     b':' => {
                     b':' => {
                         i += 1;
                         i += 1;
                         if i == len {
                         if i == len {
-                            return Err(InvalidIpv6Address)
+                            return Err(ParseError::InvalidIpv6Address)
                         }
                         }
                     },
                     },
-                    _ => return Err(InvalidIpv6Address)
+                    _ => return Err(ParseError::InvalidIpv6Address)
                 }
                 }
             }
             }
             if is_ip_v4 {
             if is_ip_v4 {
@@ -180,7 +175,7 @@ impl Ipv6Address {
 
 
         if is_ip_v4 {
         if is_ip_v4 {
             if piece_pointer > 6 {
             if piece_pointer > 6 {
-                return Err(InvalidIpv6Address)
+                return Err(ParseError::InvalidIpv6Address)
             }
             }
             let mut dots_seen = 0u;
             let mut dots_seen = 0u;
             while i < len {
             while i < len {
@@ -193,11 +188,11 @@ impl Ipv6Address {
                     };
                     };
                     value = value * 10 + digit as u16;
                     value = value * 10 + digit as u16;
                     if value == 0 || value > 255 {
                     if value == 0 || value > 255 {
-                        return Err(InvalidIpv6Address)
+                        return Err(ParseError::InvalidIpv6Address)
                     }
                     }
                 }
                 }
                 if dots_seen < 3 && !(i < len && input[i] == b'.') {
                 if dots_seen < 3 && !(i < len && input[i] == b'.') {
-                    return Err(InvalidIpv6Address)
+                    return Err(ParseError::InvalidIpv6Address)
                 }
                 }
                 pieces[piece_pointer] = pieces[piece_pointer] * 0x100 + value;
                 pieces[piece_pointer] = pieces[piece_pointer] * 0x100 + value;
                 if dots_seen == 0 || dots_seen == 2 {
                 if dots_seen == 0 || dots_seen == 2 {
@@ -205,7 +200,7 @@ impl Ipv6Address {
                 }
                 }
                 i += 1;
                 i += 1;
                 if dots_seen == 3 && i < len {
                 if dots_seen == 3 && i < len {
-                    return Err(InvalidIpv6Address)
+                    return Err(ParseError::InvalidIpv6Address)
                 }
                 }
                 dots_seen += 1;
                 dots_seen += 1;
             }
             }
@@ -223,7 +218,7 @@ impl Ipv6Address {
                 }
                 }
             }
             }
             _ => if piece_pointer != 8 {
             _ => if piece_pointer != 8 {
-                return Err(InvalidIpv6Address)
+                return Err(ParseError::InvalidIpv6Address)
             }
             }
         }
         }
         Ok(Ipv6Address { pieces: pieces })
         Ok(Ipv6Address { pieces: pieces })

+ 55 - 63
src/lib.rs

@@ -40,15 +40,15 @@ explicitly to rustc.
 First, URL parsing may fail for various reasons and therefore returns a `Result`.
 First, URL parsing may fail for various reasons and therefore returns a `Result`.
 
 
 ```
 ```
-use url::{Url, InvalidIpv6Address};
+use url::{Url, ParseError};
 
 
-assert!(Url::parse("http://[:::1]") == Err(InvalidIpv6Address))
+assert!(Url::parse("http://[:::1]") == Err(ParseError::InvalidIpv6Address))
 ```
 ```
 
 
 Let’s parse a valid URL and look at its components.
 Let’s parse a valid URL and look at its components.
 
 
 ```
 ```
-use url::{Url, RelativeSchemeData, NonRelativeSchemeData};
+use url::{Url, SchemeData};
 
 
 let issue_list_url = Url::parse(
 let issue_list_url = Url::parse(
     "https://github.com/rust-lang/rust/issues?labels=E-easy&state=open"
     "https://github.com/rust-lang/rust/issues?labels=E-easy&state=open"
@@ -64,8 +64,8 @@ assert!(issue_list_url.path() == Some(["rust-lang".to_string(),
 assert!(issue_list_url.query == Some("labels=E-easy&state=open".to_string()));
 assert!(issue_list_url.query == Some("labels=E-easy&state=open".to_string()));
 assert!(issue_list_url.fragment == None);
 assert!(issue_list_url.fragment == None);
 match issue_list_url.scheme_data {
 match issue_list_url.scheme_data {
-    RelativeSchemeData(..) => {},  // Expected
-    NonRelativeSchemeData(..) => panic!(),
+    SchemeData::Relative(..) => {},  // Expected
+    SchemeData::NonRelative(..) => panic!(),
 }
 }
 ```
 ```
 
 
@@ -75,12 +75,12 @@ Every other components has accessors because they only apply to URLs said to be
 “in a relative scheme”. `https` is a relative scheme, but `data` is not:
 “in a relative scheme”. `https` is a relative scheme, but `data` is not:
 
 
 ```
 ```
-use url::{Url, NonRelativeSchemeData};
+use url::{Url, SchemeData};
 
 
 let data_url = Url::parse("data:text/plain,Hello#").unwrap();
 let data_url = Url::parse("data:text/plain,Hello#").unwrap();
 
 
 assert!(data_url.scheme == "data".to_string());
 assert!(data_url.scheme == "data".to_string());
-assert!(data_url.scheme_data == NonRelativeSchemeData("text/plain,Hello".to_string()));
+assert!(data_url.scheme_data == SchemeData::NonRelative("text/plain,Hello".to_string()));
 assert!(data_url.non_relative_scheme_data() == Some("text/plain,Hello"));
 assert!(data_url.non_relative_scheme_data() == Some("text/plain,Hello"));
 assert!(data_url.query == None);
 assert!(data_url.query == None);
 assert!(data_url.fragment == Some("".to_string()));
 assert!(data_url.fragment == Some("".to_string()));
@@ -98,9 +98,9 @@ Many contexts allow URL *references* that can be relative to a *base URL*:
 Since parsed URL are absolute, giving a base is required:
 Since parsed URL are absolute, giving a base is required:
 
 
 ```
 ```
-use url::{Url, RelativeUrlWithoutBase};
+use url::{Url, ParseError};
 
 
-assert!(Url::parse("../main.css") == Err(RelativeUrlWithoutBase))
+assert!(Url::parse("../main.css") == Err(ParseError::RelativeUrlWithoutBase))
 ```
 ```
 
 
 `UrlParser` is a method-chaining API to provide various optional parameters
 `UrlParser` is a method-chaining API to provide various optional parameters
@@ -128,16 +128,8 @@ use std::path;
 
 
 use encoding::EncodingRef;
 use encoding::EncodingRef;
 
 
-pub use SchemeData::{RelativeSchemeData,NonRelativeSchemeData};
-pub use SchemeType::{NonRelativeScheme,RelativeScheme,FileLikeRelativeScheme};
-pub use host::{Host, Domain, Ipv6, Ipv6Address};
-pub use parser::{
-    ErrorHandler, ParseResult, ParseError,
-    EmptyHost, InvalidScheme, InvalidPort, InvalidIpv6Address, InvalidDomainCharacter,
-    InvalidCharacter, InvalidBackslash, InvalidPercentEncoded, InvalidAtSymbolInUser,
-    ExpectedTwoSlashes, NonUrlCodePoint, RelativeUrlWithScheme, RelativeUrlWithoutBase,
-    RelativeUrlWithNonRelativeBase, NonAsciiDomainsNotSupportedYet,
-};
+pub use host::{Host, Ipv6Address};
+pub use parser::{ErrorHandler, ParseResult, ParseError};
 
 
 #[deprecated = "Moved to the `percent_encoding` module"]
 #[deprecated = "Moved to the `percent_encoding` module"]
 pub use percent_encoding::{
 pub use percent_encoding::{
@@ -196,19 +188,19 @@ pub struct Url {
 #[deriving(PartialEq, Eq, Clone)]
 #[deriving(PartialEq, Eq, Clone)]
 pub enum SchemeData {
 pub enum SchemeData {
     /// Components for URLs in a *relative* scheme such as HTTP.
     /// Components for URLs in a *relative* scheme such as HTTP.
-    RelativeSchemeData(UrlRelativeSchemeData),
+    Relative(RelativeSchemeData),
 
 
     /// No further structure is assumed for *non-relative* schemes such as `data` and `mailto`.
     /// No further structure is assumed for *non-relative* schemes such as `data` and `mailto`.
     ///
     ///
     /// This is a single percent-encoded string, whose interpretation depends on the scheme.
     /// This is a single percent-encoded string, whose interpretation depends on the scheme.
     ///
     ///
     /// Percent encoded strings are within the ASCII range.
     /// Percent encoded strings are within the ASCII range.
-    NonRelativeSchemeData(String),
+    NonRelative(String),
 }
 }
 
 
 /// Components for URLs in a *relative* scheme such as HTTP.
 /// Components for URLs in a *relative* scheme such as HTTP.
 #[deriving(PartialEq, Eq, Clone)]
 #[deriving(PartialEq, Eq, Clone)]
-pub struct UrlRelativeSchemeData {
+pub struct RelativeSchemeData {
     /// The username of the URL, as a possibly empty, pecent-encoded string.
     /// The username of the URL, as a possibly empty, pecent-encoded string.
     ///
     ///
     /// Percent encoded strings are within the ASCII range.
     /// Percent encoded strings are within the ASCII range.
@@ -321,14 +313,14 @@ impl<'a> UrlParser<'a> {
     /// ```ignore
     /// ```ignore
     /// fn whatwg_scheme_type_mapper(scheme: &str) -> SchemeType {
     /// fn whatwg_scheme_type_mapper(scheme: &str) -> SchemeType {
     ///     match scheme {
     ///     match scheme {
-    ///         "file" => FileLikeRelativeScheme,
-    ///         "ftp" => RelativeScheme(21),
-    ///         "gopher" => RelativeScheme(70),
-    ///         "http" => RelativeScheme(80),
-    ///         "https" => RelativeScheme(443),
-    ///         "ws" => RelativeScheme(80),
-    ///         "wss" => RelativeScheme(443),
-    ///         _ => NonRelativeScheme,
+    ///         "file" => SchemeType::FileLike,
+    ///         "ftp" => SchemeType::Relative(21),
+    ///         "gopher" => SchemeType::Relative(70),
+    ///         "http" => SchemeType::Relative(80),
+    ///         "https" => SchemeType::Relative(443),
+    ///         "ws" => SchemeType::Relative(80),
+    ///         "wss" => SchemeType::Relative(443),
+    ///         _ => NonRelative,
     ///     }
     ///     }
     /// }
     /// }
     /// ```
     /// ```
@@ -414,7 +406,7 @@ pub enum SchemeType {
     /// (everything other than the scheme, query string, and fragment identifier)
     /// (everything other than the scheme, query string, and fragment identifier)
     /// is parsed as a single percent-encoded string of which no structure is assumed.
     /// is parsed as a single percent-encoded string of which no structure is assumed.
     /// That string may need to be parsed further, per a scheme-specific format.
     /// That string may need to be parsed further, per a scheme-specific format.
-    NonRelativeScheme,
+    NonRelative,
 
 
     /// Indicate that the scheme is *relative*, and what the default port number is.
     /// Indicate that the scheme is *relative*, and what the default port number is.
     ///
     ///
@@ -423,22 +415,22 @@ pub enum SchemeType {
     /// Relative URL references are supported, if a base URL was given.
     /// Relative URL references are supported, if a base URL was given.
     /// The string value indicates the default port number as a string of ASCII digits,
     /// The string value indicates the default port number as a string of ASCII digits,
     /// or the empty string to indicate no default port number.
     /// or the empty string to indicate no default port number.
-    RelativeScheme(u16),
+    Relative(u16),
 
 
     /// Indicate a *relative* scheme similar to the *file* scheme.
     /// Indicate a *relative* scheme similar to the *file* scheme.
     ///
     ///
     /// For example, you might want to have distinct `git+file` and `hg+file` URL schemes.
     /// For example, you might want to have distinct `git+file` and `hg+file` URL schemes.
     ///
     ///
-    /// This is like `RelativeScheme` except the host can be empty, there is no port number,
+    /// This is like `Relative` except the host can be empty, there is no port number,
     /// and path parsing has (platform-independent) quirks to support Windows filenames.
     /// and path parsing has (platform-independent) quirks to support Windows filenames.
-    FileLikeRelativeScheme,
+    FileLike,
 }
 }
 
 
 
 
 impl SchemeType {
 impl SchemeType {
     pub fn default_port(&self) -> Option<u16> {
     pub fn default_port(&self) -> Option<u16> {
         match self {
         match self {
-            &RelativeScheme(default_port) => Some(default_port),
+            &SchemeType::Relative(default_port) => Some(default_port),
             _ => None,
             _ => None,
         }
         }
     }
     }
@@ -447,14 +439,14 @@ impl SchemeType {
 /// http://url.spec.whatwg.org/#relative-scheme
 /// http://url.spec.whatwg.org/#relative-scheme
 pub fn whatwg_scheme_type_mapper(scheme: &str) -> SchemeType {
 pub fn whatwg_scheme_type_mapper(scheme: &str) -> SchemeType {
     match scheme {
     match scheme {
-        "file" => FileLikeRelativeScheme,
-        "ftp" => RelativeScheme(21),
-        "gopher" => RelativeScheme(70),
-        "http" => RelativeScheme(80),
-        "https" => RelativeScheme(443),
-        "ws" => RelativeScheme(80),
-        "wss" => RelativeScheme(443),
-        _ => NonRelativeScheme,
+        "file" => SchemeType::FileLike,
+        "ftp" => SchemeType::Relative(21),
+        "gopher" => SchemeType::Relative(70),
+        "http" => SchemeType::Relative(80),
+        "https" => SchemeType::Relative(443),
+        "ws" => SchemeType::Relative(80),
+        "wss" => SchemeType::Relative(443),
+        _ => SchemeType::NonRelative,
     }
     }
 }
 }
 
 
@@ -505,12 +497,12 @@ impl Url {
     fn from_path_common(path: Vec<String>) -> Url {
     fn from_path_common(path: Vec<String>) -> Url {
         Url {
         Url {
             scheme: "file".to_string(),
             scheme: "file".to_string(),
-            scheme_data: RelativeSchemeData(UrlRelativeSchemeData {
+            scheme_data: SchemeData::Relative(RelativeSchemeData {
                 username: "".to_string(),
                 username: "".to_string(),
                 password: None,
                 password: None,
                 port: None,
                 port: None,
                 default_port: None,
                 default_port: None,
-                host: Domain("".to_string()),
+                host: Host::Domain("".to_string()),
                 path: path,
                 path: path,
             }),
             }),
             query: None,
             query: None,
@@ -541,8 +533,8 @@ impl Url {
     #[inline]
     #[inline]
     pub fn to_file_path<T: FromUrlPath>(&self) -> Result<T, ()> {
     pub fn to_file_path<T: FromUrlPath>(&self) -> Result<T, ()> {
         match self.scheme_data {
         match self.scheme_data {
-            RelativeSchemeData(ref scheme_data) => scheme_data.to_file_path(),
-            NonRelativeSchemeData(..) => Err(()),
+            SchemeData::Relative(ref scheme_data) => scheme_data.to_file_path(),
+            SchemeData::NonRelative(..) => Err(()),
         }
         }
     }
     }
 
 
@@ -560,8 +552,8 @@ impl Url {
     #[inline]
     #[inline]
     pub fn non_relative_scheme_data<'a>(&'a self) -> Option<&'a str> {
     pub fn non_relative_scheme_data<'a>(&'a self) -> Option<&'a str> {
         match self.scheme_data {
         match self.scheme_data {
-            RelativeSchemeData(..) => None,
-            NonRelativeSchemeData(ref scheme_data) => Some(scheme_data.as_slice()),
+            SchemeData::Relative(..) => None,
+            SchemeData::NonRelative(ref scheme_data) => Some(scheme_data.as_slice()),
         }
         }
     }
     }
 
 
@@ -569,27 +561,27 @@ impl Url {
     #[inline]
     #[inline]
     pub fn non_relative_scheme_data_mut<'a>(&'a mut self) -> Option<&'a mut String> {
     pub fn non_relative_scheme_data_mut<'a>(&'a mut self) -> Option<&'a mut String> {
         match self.scheme_data {
         match self.scheme_data {
-            RelativeSchemeData(..) => None,
-            NonRelativeSchemeData(ref mut scheme_data) => Some(scheme_data),
+            SchemeData::Relative(..) => None,
+            SchemeData::NonRelative(ref mut scheme_data) => Some(scheme_data),
         }
         }
     }
     }
 
 
     /// If the URL is in a *relative scheme*, return the structured scheme data.
     /// If the URL is in a *relative scheme*, return the structured scheme data.
     #[inline]
     #[inline]
-    pub fn relative_scheme_data<'a>(&'a self) -> Option<&'a UrlRelativeSchemeData> {
+    pub fn relative_scheme_data<'a>(&'a self) -> Option<&'a RelativeSchemeData> {
         match self.scheme_data {
         match self.scheme_data {
-            RelativeSchemeData(ref scheme_data) => Some(scheme_data),
-            NonRelativeSchemeData(..) => None,
+            SchemeData::Relative(ref scheme_data) => Some(scheme_data),
+            SchemeData::NonRelative(..) => None,
         }
         }
     }
     }
 
 
     /// If the URL is in a *relative scheme*,
     /// If the URL is in a *relative scheme*,
     /// return a mutable reference to the structured scheme data.
     /// return a mutable reference to the structured scheme data.
     #[inline]
     #[inline]
-    pub fn relative_scheme_data_mut<'a>(&'a mut self) -> Option<&'a mut UrlRelativeSchemeData> {
+    pub fn relative_scheme_data_mut<'a>(&'a mut self) -> Option<&'a mut RelativeSchemeData> {
         match self.scheme_data {
         match self.scheme_data {
-            RelativeSchemeData(ref mut scheme_data) => Some(scheme_data),
-            NonRelativeSchemeData(..) => None,
+            SchemeData::Relative(ref mut scheme_data) => Some(scheme_data),
+            SchemeData::NonRelative(..) => None,
         }
         }
     }
     }
 
 
@@ -787,14 +779,14 @@ impl Show for Url {
 impl Show for SchemeData {
 impl Show for SchemeData {
     fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
     fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
         match *self {
         match *self {
-            RelativeSchemeData(ref scheme_data) => scheme_data.fmt(formatter),
-            NonRelativeSchemeData(ref scheme_data) => scheme_data.fmt(formatter),
+            SchemeData::Relative(ref scheme_data) => scheme_data.fmt(formatter),
+            SchemeData::NonRelative(ref scheme_data) => scheme_data.fmt(formatter),
         }
         }
     }
     }
 }
 }
 
 
 
 
-impl UrlRelativeSchemeData {
+impl RelativeSchemeData {
     /// Percent-decode the URL’s username.
     /// Percent-decode the URL’s username.
     ///
     ///
     /// This is “lossy”: invalid UTF-8 percent-encoded byte sequences
     /// This is “lossy”: invalid UTF-8 percent-encoded byte sequences
@@ -846,7 +838,7 @@ impl UrlRelativeSchemeData {
     #[inline]
     #[inline]
     pub fn domain<'a>(&'a self) -> Option<&'a str> {
     pub fn domain<'a>(&'a self) -> Option<&'a str> {
         match self.host {
         match self.host {
-            Domain(ref domain) => Some(domain.as_slice()),
+            Host::Domain(ref domain) => Some(domain.as_slice()),
             _ => None,
             _ => None,
         }
         }
     }
     }
@@ -855,7 +847,7 @@ impl UrlRelativeSchemeData {
     #[inline]
     #[inline]
     pub fn domain_mut<'a>(&'a mut self) -> Option<&'a mut String> {
     pub fn domain_mut<'a>(&'a mut self) -> Option<&'a mut String> {
         match self.host {
         match self.host {
-            Domain(ref mut domain) => Some(domain),
+            Host::Domain(ref mut domain) => Some(domain),
             _ => None,
             _ => None,
         }
         }
     }
     }
@@ -889,7 +881,7 @@ impl UrlRelativeSchemeData {
 }
 }
 
 
 
 
-impl Show for UrlRelativeSchemeData {
+impl Show for RelativeSchemeData {
     fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
     fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
         // Write the scheme-trailing double slashes.
         // Write the scheme-trailing double slashes.
         try!(formatter.write(b"//"));
         try!(formatter.write(b"//"));

+ 69 - 77
src/parser.rs

@@ -5,15 +5,7 @@
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
 // option. This file may not be copied, modified, or distributed
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 // except according to those terms.
-pub use ParseError::{
-    EmptyHost,InvalidScheme,InvalidPort,InvalidIpv6Address,InvalidDomainCharacter,
-    InvalidCharacter,InvalidBackslash,InvalidPercentEncoded,InvalidAtSymbolInUser,
-    ExpectedTwoSlashes,ExpectedInitialSlash,NonUrlCodePoint,RelativeUrlWithScheme,
-    RelativeUrlWithoutBase,RelativeUrlWithNonRelativeBase,
-    NonAsciiDomainsNotSupportedYet
-};
 
 
-pub use self::Context::{SetterContext,UrlParserContext};
 use std::ascii::AsciiExt;
 use std::ascii::AsciiExt;
 use std::error::Error;
 use std::error::Error;
 use std::fmt::{mod, Formatter, Show};
 use std::fmt::{mod, Formatter, Show};
@@ -21,11 +13,7 @@ use std::str::CharRange;
 
 
 use encoding;
 use encoding;
 
 
-use super::{
-    UrlParser, Url, RelativeSchemeData, NonRelativeSchemeData, Host, Domain,
-    SchemeType, FileLikeRelativeScheme, RelativeScheme, NonRelativeScheme,
-    UrlRelativeSchemeData,
-};
+use super::{UrlParser, Url, SchemeData, RelativeSchemeData, Host, SchemeType};
 use percent_encoding::{
 use percent_encoding::{
     utf8_percent_encode_to, percent_encode,
     utf8_percent_encode_to, percent_encode,
     SIMPLE_ENCODE_SET, DEFAULT_ENCODE_SET, USERINFO_ENCODE_SET, QUERY_ENCODE_SET
     SIMPLE_ENCODE_SET, DEFAULT_ENCODE_SET, USERINFO_ENCODE_SET, QUERY_ENCODE_SET
@@ -108,59 +96,59 @@ pub type ErrorHandler = fn(reason: ParseError) -> ParseResult<()>;
 
 
 #[deriving(PartialEq, Eq)]
 #[deriving(PartialEq, Eq)]
 pub enum Context {
 pub enum Context {
-    UrlParserContext,
-    SetterContext,
+    UrlParser,
+    Setter,
 }
 }
 
 
 
 
 pub fn parse_url(input: &str, parser: &UrlParser) -> ParseResult<Url> {
 pub fn parse_url(input: &str, parser: &UrlParser) -> ParseResult<Url> {
     let input = input.trim_chars([' ', '\t', '\n', '\r', '\x0C'].as_slice());
     let input = input.trim_chars([' ', '\t', '\n', '\r', '\x0C'].as_slice());
-    let (scheme, remaining) = match parse_scheme(input, UrlParserContext) {
+    let (scheme, remaining) = match parse_scheme(input, Context::UrlParser) {
         Some((scheme, remaining)) => (scheme, remaining),
         Some((scheme, remaining)) => (scheme, remaining),
         // No-scheme state
         // No-scheme state
         None => return match parser.base_url {
         None => return match parser.base_url {
-            Some(&Url { ref scheme, scheme_data: RelativeSchemeData(ref base),
+            Some(&Url { ref scheme, scheme_data: SchemeData::Relative(ref base),
                         ref query, .. }) => {
                         ref query, .. }) => {
                 let scheme_type = parser.get_scheme_type(scheme.as_slice());
                 let scheme_type = parser.get_scheme_type(scheme.as_slice());
                 parse_relative_url(input, scheme.clone(), scheme_type, base, query, parser)
                 parse_relative_url(input, scheme.clone(), scheme_type, base, query, parser)
             },
             },
-            Some(_) => Err(RelativeUrlWithNonRelativeBase),
-            None => Err(RelativeUrlWithoutBase),
+            Some(_) => Err(ParseError::RelativeUrlWithNonRelativeBase),
+            None => Err(ParseError::RelativeUrlWithoutBase),
         },
         },
     };
     };
     let scheme_type = parser.get_scheme_type(scheme.as_slice());
     let scheme_type = parser.get_scheme_type(scheme.as_slice());
     match scheme_type {
     match scheme_type {
-        FileLikeRelativeScheme => {
+        SchemeType::FileLike => {
             // Relative state?
             // Relative state?
             match parser.base_url {
             match parser.base_url {
-                Some(&Url { scheme: ref base_scheme, scheme_data: RelativeSchemeData(ref base),
+                Some(&Url { scheme: ref base_scheme, scheme_data: SchemeData::Relative(ref base),
                             ref query, .. })
                             ref query, .. })
                 if scheme == *base_scheme => {
                 if scheme == *base_scheme => {
                     parse_relative_url(remaining, scheme, scheme_type, base, query, parser)
                     parse_relative_url(remaining, scheme, scheme_type, base, query, parser)
                 },
                 },
                 // FIXME: Should not have to use a made-up base URL.
                 // FIXME: Should not have to use a made-up base URL.
-                _ => parse_relative_url(remaining, scheme, scheme_type, &UrlRelativeSchemeData {
-                    username: String::new(), password: None, host: Domain(String::new()),
+                _ => parse_relative_url(remaining, scheme, scheme_type, &RelativeSchemeData {
+                    username: String::new(), password: None, host: Host::Domain(String::new()),
                     port: None, default_port: None, path: Vec::new()
                     port: None, default_port: None, path: Vec::new()
                 }, &None, parser)
                 }, &None, parser)
             }
             }
         },
         },
-        RelativeScheme(..) => {
+        SchemeType::Relative(..) => {
             match parser.base_url {
             match parser.base_url {
-                Some(&Url { scheme: ref base_scheme, scheme_data: RelativeSchemeData(ref base),
+                Some(&Url { scheme: ref base_scheme, scheme_data: SchemeData::Relative(ref base),
                             ref query, .. })
                             ref query, .. })
                 if scheme == *base_scheme && !remaining.starts_with("//") => {
                 if scheme == *base_scheme && !remaining.starts_with("//") => {
-                    try!(parser.parse_error(RelativeUrlWithScheme));
+                    try!(parser.parse_error(ParseError::RelativeUrlWithScheme));
                     parse_relative_url(remaining, scheme, scheme_type, base, query, parser)
                     parse_relative_url(remaining, scheme, scheme_type, base, query, parser)
                 },
                 },
                 _ => parse_absolute_url(scheme, scheme_type, remaining, parser),
                 _ => parse_absolute_url(scheme, scheme_type, remaining, parser),
             }
             }
         },
         },
-        NonRelativeScheme => {
+        SchemeType::NonRelative => {
             // Scheme data state
             // Scheme data state
             let (scheme_data, remaining) = try!(parse_scheme_data(remaining, parser));
             let (scheme_data, remaining) = try!(parse_scheme_data(remaining, parser));
             let (query, fragment) = try!(parse_query_and_fragment(remaining, parser));
             let (query, fragment) = try!(parse_query_and_fragment(remaining, parser));
-            Ok(Url { scheme: scheme, scheme_data: NonRelativeSchemeData(scheme_data),
+            Ok(Url { scheme: scheme, scheme_data: SchemeData::NonRelative(scheme_data),
                      query: query, fragment: fragment })
                      query: query, fragment: fragment })
         }
         }
     }
     }
@@ -183,8 +171,8 @@ pub fn parse_scheme<'a>(input: &'a str, context: Context) -> Option<(String, &'a
     }
     }
     // EOF before ':'
     // EOF before ':'
     match context {
     match context {
-        SetterContext => Some((input.to_ascii_lower(), "")),
-        UrlParserContext => None
+        Context::Setter => Some((input.to_ascii_lower(), "")),
+        Context::UrlParser => None
     }
     }
 }
 }
 
 
@@ -198,8 +186,8 @@ fn parse_absolute_url<'a>(scheme: String, scheme_type: SchemeType,
     // Host state
     // Host state
     let (host, port, default_port, remaining) = try!(parse_host(remaining, scheme_type, parser));
     let (host, port, default_port, remaining) = try!(parse_host(remaining, scheme_type, parser));
     let (path, remaining) = try!(parse_path_start(
     let (path, remaining) = try!(parse_path_start(
-        remaining, UrlParserContext, scheme_type, parser));
-    let scheme_data = RelativeSchemeData(UrlRelativeSchemeData {
+        remaining, Context::UrlParser, scheme_type, parser));
+    let scheme_data = SchemeData::Relative(RelativeSchemeData {
         username: username, password: password,
         username: username, password: password,
         host: host, port: port, default_port: default_port,
         host: host, port: port, default_port: default_port,
         path: path });
         path: path });
@@ -209,19 +197,21 @@ fn parse_absolute_url<'a>(scheme: String, scheme_type: SchemeType,
 
 
 
 
 fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeType,
 fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeType,
-                          base: &UrlRelativeSchemeData, base_query: &Option<String>,
+                          base: &RelativeSchemeData, base_query: &Option<String>,
                           parser: &UrlParser)
                           parser: &UrlParser)
                           -> ParseResult<Url> {
                           -> ParseResult<Url> {
     if input.is_empty() {
     if input.is_empty() {
-        return Ok(Url { scheme: scheme, scheme_data: RelativeSchemeData(base.clone()),
+        return Ok(Url { scheme: scheme, scheme_data: SchemeData::Relative(base.clone()),
                         query: base_query.clone(), fragment: None })
                         query: base_query.clone(), fragment: None })
     }
     }
     match input.char_at(0) {
     match input.char_at(0) {
         '/' | '\\' => {
         '/' | '\\' => {
             // Relative slash state
             // Relative slash state
             if input.len() > 1 && is_match!(input.char_at(1), '/' | '\\') {
             if input.len() > 1 && is_match!(input.char_at(1), '/' | '\\') {
-                if input.char_at(1) == '\\' { try!(parser.parse_error(InvalidBackslash)) }
-                if scheme_type == FileLikeRelativeScheme {
+                if input.char_at(1) == '\\' {
+                    try!(parser.parse_error(ParseError::InvalidBackslash))
+                }
+                if scheme_type == SchemeType::FileLike {
                     // File host state
                     // File host state
                     let remaining = input.slice_from(2);
                     let remaining = input.slice_from(2);
                     let (host, remaining) = if remaining.len() >= 2
                     let (host, remaining) = if remaining.len() >= 2
@@ -232,13 +222,13 @@ fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeTyp
                                          '/' | '\\' | '?' | '#'))
                                          '/' | '\\' | '?' | '#'))
                     {
                     {
                         // Windows drive letter quirk
                         // Windows drive letter quirk
-                        (Domain(String::new()), remaining)
+                        (Host::Domain(String::new()), remaining)
                     } else {
                     } else {
                         try!(parse_file_host(remaining, parser))
                         try!(parse_file_host(remaining, parser))
                     };
                     };
                     let (path, remaining) = try!(parse_path_start(
                     let (path, remaining) = try!(parse_path_start(
-                        remaining, UrlParserContext, scheme_type, parser));
-                    let scheme_data = RelativeSchemeData(UrlRelativeSchemeData {
+                        remaining, Context::UrlParser, scheme_type, parser));
+                    let scheme_data = SchemeData::Relative(RelativeSchemeData {
                         username: String::new(), password: None,
                         username: String::new(), password: None,
                         host: host, port: None, default_port: None, path: path
                         host: host, port: None, default_port: None, path: path
                     });
                     });
@@ -251,14 +241,14 @@ fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeTyp
             } else {
             } else {
                 // Relative path state
                 // Relative path state
                 let (path, remaining) = try!(parse_path(
                 let (path, remaining) = try!(parse_path(
-                    &[], input.slice_from(1), UrlParserContext, scheme_type, parser));
-                let scheme_data = RelativeSchemeData(if scheme_type == FileLikeRelativeScheme {
-                    UrlRelativeSchemeData {
+                    &[], input.slice_from(1), Context::UrlParser, scheme_type, parser));
+                let scheme_data = SchemeData::Relative(if scheme_type == SchemeType::FileLike {
+                    RelativeSchemeData {
                         username: String::new(), password: None, host:
                         username: String::new(), password: None, host:
-                        Domain(String::new()), port: None, default_port: None, path: path
+                        Host::Domain(String::new()), port: None, default_port: None, path: path
                     }
                     }
                 } else {
                 } else {
-                    UrlRelativeSchemeData {
+                    RelativeSchemeData {
                         username: base.username.clone(),
                         username: base.username.clone(),
                         password: base.password.clone(),
                         password: base.password.clone(),
                         host: base.host.clone(),
                         host: base.host.clone(),
@@ -275,16 +265,16 @@ fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeTyp
         },
         },
         '?' => {
         '?' => {
             let (query, fragment) = try!(parse_query_and_fragment(input, parser));
             let (query, fragment) = try!(parse_query_and_fragment(input, parser));
-            Ok(Url { scheme: scheme, scheme_data: RelativeSchemeData(base.clone()),
+            Ok(Url { scheme: scheme, scheme_data: SchemeData::Relative(base.clone()),
                      query: query, fragment: fragment })
                      query: query, fragment: fragment })
         },
         },
         '#' => {
         '#' => {
             let fragment = Some(try!(parse_fragment(input.slice_from(1), parser)));
             let fragment = Some(try!(parse_fragment(input.slice_from(1), parser)));
-            Ok(Url { scheme: scheme, scheme_data: RelativeSchemeData(base.clone()),
+            Ok(Url { scheme: scheme, scheme_data: SchemeData::Relative(base.clone()),
                      query: base_query.clone(), fragment: fragment })
                      query: base_query.clone(), fragment: fragment })
         }
         }
         _ => {
         _ => {
-            let (scheme_data, remaining) = if scheme_type == FileLikeRelativeScheme
+            let (scheme_data, remaining) = if scheme_type == SchemeType::FileLike
                && input.len() >= 2
                && input.len() >= 2
                && starts_with_ascii_alpha(input)
                && starts_with_ascii_alpha(input)
                && is_match!(input.char_at(1), ':' | '|')
                && is_match!(input.char_at(1), ':' | '|')
@@ -293,10 +283,10 @@ fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeTyp
             {
             {
                 // Windows drive letter quirk
                 // Windows drive letter quirk
                 let (path, remaining) = try!(parse_path(
                 let (path, remaining) = try!(parse_path(
-                    &[], input, UrlParserContext, scheme_type, parser));
-                 (RelativeSchemeData(UrlRelativeSchemeData {
+                    &[], input, Context::UrlParser, scheme_type, parser));
+                 (SchemeData::Relative(RelativeSchemeData {
                     username: String::new(), password: None,
                     username: String::new(), password: None,
-                    host: Domain(String::new()),
+                    host: Host::Domain(String::new()),
                     port: None,
                     port: None,
                     default_port: None,
                     default_port: None,
                     path: path
                     path: path
@@ -305,8 +295,8 @@ fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeTyp
                 let base_path = base.path.slice_to(base.path.len() - 1);
                 let base_path = base.path.slice_to(base.path.len() - 1);
                 // Relative path state
                 // Relative path state
                 let (path, remaining) = try!(parse_path(
                 let (path, remaining) = try!(parse_path(
-                    base_path, input, UrlParserContext, scheme_type, parser));
-                (RelativeSchemeData(UrlRelativeSchemeData {
+                    base_path, input, Context::UrlParser, scheme_type, parser));
+                (SchemeData::Relative(RelativeSchemeData {
                     username: base.username.clone(),
                     username: base.username.clone(),
                     password: base.password.clone(),
                     password: base.password.clone(),
                     host: base.host.clone(),
                     host: base.host.clone(),
@@ -326,7 +316,7 @@ fn parse_relative_url<'a>(input: &'a str, scheme: String, scheme_type: SchemeTyp
 fn skip_slashes<'a>(input: &'a str, parser: &UrlParser) -> ParseResult<&'a str> {
 fn skip_slashes<'a>(input: &'a str, parser: &UrlParser) -> ParseResult<&'a str> {
     let first_non_slash = input.find(|c| !is_match!(c, '/' | '\\')).unwrap_or(input.len());
     let first_non_slash = input.find(|c| !is_match!(c, '/' | '\\')).unwrap_or(input.len());
     if input.slice_to(first_non_slash) != "//" {
     if input.slice_to(first_non_slash) != "//" {
-        try!(parser.parse_error(ExpectedTwoSlashes));
+        try!(parser.parse_error(ParseError::ExpectedTwoSlashes));
     }
     }
     Ok(input.slice_from(first_non_slash))
     Ok(input.slice_from(first_non_slash))
 }
 }
@@ -338,7 +328,9 @@ fn parse_userinfo<'a>(input: &'a str, parser: &UrlParser)
     for (i, c) in input.char_indices() {
     for (i, c) in input.char_indices() {
         match c {
         match c {
             '@' => {
             '@' => {
-                if last_at.is_some() { try!(parser.parse_error(InvalidAtSymbolInUser)) }
+                if last_at.is_some() {
+                    try!(parser.parse_error(ParseError::InvalidAtSymbolInUser))
+                }
                 last_at = Some(i)
                 last_at = Some(i)
             },
             },
             '/' | '\\' | '?' | '#' => break,
             '/' | '\\' | '?' | '#' => break,
@@ -358,7 +350,7 @@ fn parse_userinfo<'a>(input: &'a str, parser: &UrlParser)
                 password = Some(try!(parse_password(input.slice_from(i + 1), parser)));
                 password = Some(try!(parse_password(input.slice_from(i + 1), parser)));
                 break
                 break
             },
             },
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
             _ => {
             _ => {
                 try!(check_url_code_point(input, i, c, parser));
                 try!(check_url_code_point(input, i, c, parser));
                 // The spec says to use the default encode set,
                 // The spec says to use the default encode set,
@@ -376,7 +368,7 @@ fn parse_password(input: &str, parser: &UrlParser) -> ParseResult<String> {
     let mut password = String::new();
     let mut password = String::new();
     for (i, c, next_i) in input.char_ranges() {
     for (i, c, next_i) in input.char_ranges() {
         match c {
         match c {
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
             _ => {
             _ => {
                 try!(check_url_code_point(input, i, c, parser));
                 try!(check_url_code_point(input, i, c, parser));
                 // The spec says to use the default encode set,
                 // The spec says to use the default encode set,
@@ -417,7 +409,7 @@ pub fn parse_hostname<'a>(input: &'a str, parser: &UrlParser)
                 end = i;
                 end = i;
                 break
                 break
             },
             },
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
             c => {
             c => {
                 match c {
                 match c {
                     '[' => inside_square_brackets = true,
                     '[' => inside_square_brackets = true,
@@ -443,7 +435,7 @@ pub fn parse_port<'a>(input: &'a str, scheme_type: SchemeType, parser: &UrlParse
             '0'...'9' => {
             '0'...'9' => {
                 port = port * 10 + (c as u32 - '0' as u32);
                 port = port * 10 + (c as u32 - '0' as u32);
                 if port > ::std::u16::MAX as u32 {
                 if port > ::std::u16::MAX as u32 {
-                    return Err(InvalidPort)
+                    return Err(ParseError::InvalidPort)
                 }
                 }
                 has_any_digit = true;
                 has_any_digit = true;
             },
             },
@@ -451,8 +443,8 @@ pub fn parse_port<'a>(input: &'a str, scheme_type: SchemeType, parser: &UrlParse
                 end = i;
                 end = i;
                 break
                 break
             },
             },
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
-            _ => return Err(InvalidPort)
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
+            _ => return Err(ParseError::InvalidPort)
         }
         }
     }
     }
     let default_port = scheme_type.default_port();
     let default_port = scheme_type.default_port();
@@ -473,12 +465,12 @@ fn parse_file_host<'a>(input: &'a str, parser: &UrlParser) -> ParseResult<(Host,
                 end = i;
                 end = i;
                 break
                 break
             },
             },
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
             _ => host_input.push(c)
             _ => host_input.push(c)
         }
         }
     }
     }
     let host = if host_input.is_empty() {
     let host = if host_input.is_empty() {
-        Domain(String::new())
+        Host::Domain(String::new())
     } else {
     } else {
         try!(Host::parse(host_input.as_slice()))
         try!(Host::parse(host_input.as_slice()))
     };
     };
@@ -490,13 +482,13 @@ pub fn parse_standalone_path(input: &str, parser: &UrlParser)
                              -> ParseResult<(Vec<String>, Option<String>, Option<String>)> {
                              -> ParseResult<(Vec<String>, Option<String>, Option<String>)> {
     if !input.starts_with("/") {
     if !input.starts_with("/") {
         if input.starts_with("\\") {
         if input.starts_with("\\") {
-            try!(parser.parse_error(InvalidBackslash));
+            try!(parser.parse_error(ParseError::InvalidBackslash));
         } else {
         } else {
-            return Err(ExpectedInitialSlash)
+            return Err(ParseError::ExpectedInitialSlash)
         }
         }
     }
     }
     let (path, remaining) = try!(parse_path(
     let (path, remaining) = try!(parse_path(
-        &[], input.slice_from(1), UrlParserContext, RelativeScheme(0), parser));
+        &[], input.slice_from(1), Context::UrlParser, SchemeType::Relative(0), parser));
     let (query, fragment) = try!(parse_query_and_fragment(remaining, parser));
     let (query, fragment) = try!(parse_query_and_fragment(remaining, parser));
     Ok((path, query, fragment))
     Ok((path, query, fragment))
 }
 }
@@ -511,7 +503,7 @@ pub fn parse_path_start<'a>(input: &'a str, context: Context, scheme_type: Schem
         match input.char_at(0) {
         match input.char_at(0) {
             '/' => i = 1,
             '/' => i = 1,
             '\\' => {
             '\\' => {
-                try!(parser.parse_error(InvalidBackslash));
+                try!(parser.parse_error(ParseError::InvalidBackslash));
                 i = 1;
                 i = 1;
             },
             },
             _ => ()
             _ => ()
@@ -540,16 +532,16 @@ fn parse_path<'a>(base_path: &[String], input: &'a str, context: Context,
                     break
                     break
                 },
                 },
                 '\\' => {
                 '\\' => {
-                    try!(parser.parse_error(InvalidBackslash));
+                    try!(parser.parse_error(ParseError::InvalidBackslash));
                     ends_with_slash = true;
                     ends_with_slash = true;
                     end = i;
                     end = i;
                     break
                     break
                 },
                 },
-                '?' | '#' if context == UrlParserContext => {
+                '?' | '#' if context == Context::UrlParser => {
                     end = i;
                     end = i;
                     break
                     break
                 },
                 },
-                '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+                '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
                 _ => {
                 _ => {
                     try!(check_url_code_point(input, i, c, parser));
                     try!(check_url_code_point(input, i, c, parser));
                     utf8_percent_encode_to(input.slice(i, next_i),
                     utf8_percent_encode_to(input.slice(i, next_i),
@@ -571,7 +563,7 @@ fn parse_path<'a>(base_path: &[String], input: &'a str, context: Context,
                 }
                 }
             },
             },
             _ => {
             _ => {
-                if scheme_type == FileLikeRelativeScheme
+                if scheme_type == SchemeType::FileLike
                    && path.is_empty()
                    && path.is_empty()
                    && path_part.len() == 2
                    && path_part.len() == 2
                    && starts_with_ascii_alpha(path_part.as_slice())
                    && starts_with_ascii_alpha(path_part.as_slice())
@@ -602,7 +594,7 @@ fn parse_scheme_data<'a>(input: &'a str, parser: &UrlParser)
                 end = i;
                 end = i;
                 break
                 break
             },
             },
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
             _ => {
             _ => {
                 try!(check_url_code_point(input, i, c, parser));
                 try!(check_url_code_point(input, i, c, parser));
                 utf8_percent_encode_to(input.slice(i, next_i),
                 utf8_percent_encode_to(input.slice(i, next_i),
@@ -623,7 +615,7 @@ fn parse_query_and_fragment(input: &str, parser: &UrlParser)
         '#' => Ok((None, Some(try!(parse_fragment(input.slice_from(1), parser))))),
         '#' => Ok((None, Some(try!(parse_fragment(input.slice_from(1), parser))))),
         '?' => {
         '?' => {
             let (query, remaining) = try!(parse_query(
             let (query, remaining) = try!(parse_query(
-                input.slice_from(1), UrlParserContext, parser));
+                input.slice_from(1), Context::UrlParser, parser));
             let fragment = match remaining {
             let fragment = match remaining {
                 Some(remaining) => Some(try!(parse_fragment(remaining, parser))),
                 Some(remaining) => Some(try!(parse_fragment(remaining, parser))),
                 None => None
                 None => None
@@ -642,11 +634,11 @@ pub fn parse_query<'a>(input: &'a str, context: Context, parser: &UrlParser)
     let mut remaining = None;
     let mut remaining = None;
     for (i, c) in input.char_indices() {
     for (i, c) in input.char_indices() {
         match c {
         match c {
-            '#' if context == UrlParserContext => {
+            '#' if context == Context::UrlParser => {
                 remaining = Some(input.slice_from(i + 1));
                 remaining = Some(input.slice_from(i + 1));
                 break
                 break
             },
             },
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
             _ => {
             _ => {
                 try!(check_url_code_point(input, i, c, parser));
                 try!(check_url_code_point(input, i, c, parser));
                 query.push(c);
                 query.push(c);
@@ -670,7 +662,7 @@ pub fn parse_fragment<'a>(input: &'a str, parser: &UrlParser) -> ParseResult<Str
     let mut fragment = String::new();
     let mut fragment = String::new();
     for (i, c, next_i) in input.char_ranges() {
     for (i, c, next_i) in input.char_ranges() {
         match c {
         match c {
-            '\t' | '\n' | '\r' => try!(parser.parse_error(InvalidCharacter)),
+            '\t' | '\n' | '\r' => try!(parser.parse_error(ParseError::InvalidCharacter)),
             _ => {
             _ => {
                 try!(check_url_code_point(input, i, c, parser));
                 try!(check_url_code_point(input, i, c, parser));
                 utf8_percent_encode_to(input.slice(i, next_i),
                 utf8_percent_encode_to(input.slice(i, next_i),
@@ -771,10 +763,10 @@ fn check_url_code_point(input: &str, i: uint, c: char, parser: &UrlParser)
                         -> ParseResult<()> {
                         -> ParseResult<()> {
     if c == '%' {
     if c == '%' {
         if !starts_with_2_hex(input.slice_from(i + 1)) {
         if !starts_with_2_hex(input.slice_from(i + 1)) {
-            try!(parser.parse_error(InvalidPercentEncoded));
+            try!(parser.parse_error(ParseError::InvalidPercentEncoded));
         }
         }
     } else if !is_url_code_point(c) {
     } else if !is_url_code_point(c) {
-        try!(parser.parse_error(NonUrlCodePoint));
+        try!(parser.parse_error(ParseError::NonUrlCodePoint));
     }
     }
     Ok(())
     Ok(())
 }
 }

+ 7 - 8
src/tests.rs

@@ -10,8 +10,7 @@
 use std::char;
 use std::char;
 use std::num::from_str_radix;
 use std::num::from_str_radix;
 use std::path;
 use std::path;
-use super::{UrlParser, Url, RelativeSchemeData, NonRelativeSchemeData, Domain};
-use super::UrlRelativeSchemeData;
+use super::{UrlParser, Url, SchemeData, RelativeSchemeData, Host};
 
 
 
 
 #[test]
 #[test]
@@ -70,7 +69,7 @@ fn url_parsing() {
 
 
         assert_eq!(Some(scheme), expected_scheme);
         assert_eq!(Some(scheme), expected_scheme);
         match scheme_data {
         match scheme_data {
-            RelativeSchemeData(UrlRelativeSchemeData {
+            SchemeData::Relative(RelativeSchemeData {
                 username, password, host, port, default_port: _, path,
                 username, password, host, port, default_port: _, path,
             }) => {
             }) => {
                 assert_eq!(username, expected_username);
                 assert_eq!(username, expected_username);
@@ -80,7 +79,7 @@ fn url_parsing() {
                 assert_eq!(port, expected_port);
                 assert_eq!(port, expected_port);
                 assert_eq!(Some(format!("/{}", path.connect("/"))), expected_path);
                 assert_eq!(Some(format!("/{}", path.connect("/"))), expected_path);
             },
             },
-            NonRelativeSchemeData(scheme_data) => {
+            SchemeData::NonRelative(scheme_data) => {
                 assert_eq!(Some(scheme_data), expected_path);
                 assert_eq!(Some(scheme_data), expected_path);
                 assert_eq!(String::new(), expected_username);
                 assert_eq!(String::new(), expected_username);
                 assert_eq!(None, expected_password);
                 assert_eq!(None, expected_password);
@@ -209,7 +208,7 @@ fn file_paths() {
     assert_eq!(Url::from_file_path(&path::windows::Path::new(r"\\ucn\")), Err(()));
     assert_eq!(Url::from_file_path(&path::windows::Path::new(r"\\ucn\")), Err(()));
 
 
     let mut url = Url::from_file_path(&path::posix::Path::new("/foo/bar")).unwrap();
     let mut url = Url::from_file_path(&path::posix::Path::new("/foo/bar")).unwrap();
-    assert_eq!(url.host(), Some(&Domain("".to_string())));
+    assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
     assert_eq!(url.path(), Some(["foo".to_string(), "bar".to_string()].as_slice()));
     assert_eq!(url.path(), Some(["foo".to_string(), "bar".to_string()].as_slice()));
     assert!(url.to_file_path() == Ok(path::posix::Path::new("/foo/bar")));
     assert!(url.to_file_path() == Ok(path::posix::Path::new("/foo/bar")));
 
 
@@ -225,7 +224,7 @@ fn file_paths() {
         /* note: byte string, invalid UTF-8 */ b"/foo/ba\x80r")));
         /* note: byte string, invalid UTF-8 */ b"/foo/ba\x80r")));
 
 
     let mut url = Url::from_file_path(&path::windows::Path::new(r"C:\foo\bar")).unwrap();
     let mut url = Url::from_file_path(&path::windows::Path::new(r"C:\foo\bar")).unwrap();
-    assert_eq!(url.host(), Some(&Domain("".to_string())));
+    assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
     assert_eq!(url.path(), Some(["C:".to_string(), "foo".to_string(), "bar".to_string()].as_slice()));
     assert_eq!(url.path(), Some(["C:".to_string(), "foo".to_string(), "bar".to_string()].as_slice()));
     assert!(url.to_file_path::<path::windows::Path>()
     assert!(url.to_file_path::<path::windows::Path>()
             == Ok(path::windows::Path::new(r"C:\foo\bar")));
             == Ok(path::windows::Path::new(r"C:\foo\bar")));
@@ -252,11 +251,11 @@ fn directory_paths() {
     assert_eq!(Url::from_directory_path(&path::windows::Path::new(r"\\ucn\")), Err(()));
     assert_eq!(Url::from_directory_path(&path::windows::Path::new(r"\\ucn\")), Err(()));
 
 
     let url = Url::from_directory_path(&path::posix::Path::new("/foo/bar")).unwrap();
     let url = Url::from_directory_path(&path::posix::Path::new("/foo/bar")).unwrap();
-    assert_eq!(url.host(), Some(&Domain("".to_string())));
+    assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
     assert_eq!(url.path(), Some(["foo".to_string(), "bar".to_string(), "".to_string()].as_slice()));
     assert_eq!(url.path(), Some(["foo".to_string(), "bar".to_string(), "".to_string()].as_slice()));
 
 
     let url = Url::from_directory_path(&path::windows::Path::new(r"C:\foo\bar")).unwrap();
     let url = Url::from_directory_path(&path::windows::Path::new(r"C:\foo\bar")).unwrap();
-    assert_eq!(url.host(), Some(&Domain("".to_string())));
+    assert_eq!(url.host(), Some(&Host::Domain("".to_string())));
     assert_eq!(url.path(), Some([
     assert_eq!(url.path(), Some([
         "C:".to_string(), "foo".to_string(), "bar".to_string(), "".to_string()].as_slice()));
         "C:".to_string(), "foo".to_string(), "bar".to_string(), "".to_string()].as_slice()));
 }
 }

+ 18 - 19
src/urlutils.rs

@@ -10,9 +10,8 @@
 //! These methods are not meant for use in Rust code,
 //! These methods are not meant for use in Rust code,
 //! only to help implement the JavaScript URLUtils API: http://url.spec.whatwg.org/#urlutils
 //! only to help implement the JavaScript URLUtils API: http://url.spec.whatwg.org/#urlutils
 
 
-use super::{Url, UrlParser, RelativeSchemeData, NonRelativeSchemeData, FileLikeRelativeScheme};
-use super::UrlRelativeSchemeData;
-use parser::{ParseError, ParseResult};
+use super::{Url, UrlParser, SchemeType, SchemeData, RelativeSchemeData};
+use parser::{ParseError, ParseResult, Context};
 use percent_encoding::{utf8_percent_encode_to, USERNAME_ENCODE_SET, PASSWORD_ENCODE_SET};
 use percent_encoding::{utf8_percent_encode_to, USERNAME_ENCODE_SET, PASSWORD_ENCODE_SET};
 
 
 
 
@@ -39,7 +38,7 @@ trait UrlUtils {
 impl<'a> UrlUtils for UrlUtilsWrapper<'a> {
 impl<'a> UrlUtils for UrlUtilsWrapper<'a> {
     /// `URLUtils.protocol` setter
     /// `URLUtils.protocol` setter
     fn set_scheme(&mut self, input: &str) -> ParseResult<()> {
     fn set_scheme(&mut self, input: &str) -> ParseResult<()> {
-        match ::parser::parse_scheme(input.as_slice(), ::parser::SetterContext) {
+        match ::parser::parse_scheme(input.as_slice(), Context::Setter) {
             Some((scheme, _)) => {
             Some((scheme, _)) => {
                 self.url.scheme = scheme;
                 self.url.scheme = scheme;
                 Ok(())
                 Ok(())
@@ -51,32 +50,32 @@ impl<'a> UrlUtils for UrlUtilsWrapper<'a> {
     /// `URLUtils.username` setter
     /// `URLUtils.username` setter
     fn set_username(&mut self, input: &str) -> ParseResult<()> {
     fn set_username(&mut self, input: &str) -> ParseResult<()> {
         match self.url.scheme_data {
         match self.url.scheme_data {
-            RelativeSchemeData(UrlRelativeSchemeData { ref mut username, .. }) => {
+            SchemeData::Relative(RelativeSchemeData { ref mut username, .. }) => {
                 username.truncate(0);
                 username.truncate(0);
                 utf8_percent_encode_to(input, USERNAME_ENCODE_SET, username);
                 utf8_percent_encode_to(input, USERNAME_ENCODE_SET, username);
                 Ok(())
                 Ok(())
             },
             },
-            NonRelativeSchemeData(_) => Err(ParseError::CannotSetUsernameWithNonRelativeScheme)
+            SchemeData::NonRelative(_) => Err(ParseError::CannotSetUsernameWithNonRelativeScheme)
         }
         }
     }
     }
 
 
     /// `URLUtils.password` setter
     /// `URLUtils.password` setter
     fn set_password(&mut self, input: &str) -> ParseResult<()> {
     fn set_password(&mut self, input: &str) -> ParseResult<()> {
         match self.url.scheme_data {
         match self.url.scheme_data {
-            RelativeSchemeData(UrlRelativeSchemeData { ref mut password, .. }) => {
+            SchemeData::Relative(RelativeSchemeData { ref mut password, .. }) => {
                 let mut new_password = String::new();
                 let mut new_password = String::new();
                 utf8_percent_encode_to(input, PASSWORD_ENCODE_SET, &mut new_password);
                 utf8_percent_encode_to(input, PASSWORD_ENCODE_SET, &mut new_password);
                 *password = Some(new_password);
                 *password = Some(new_password);
                 Ok(())
                 Ok(())
             },
             },
-            NonRelativeSchemeData(_) => Err(ParseError::CannotSetPasswordWithNonRelativeScheme)
+            SchemeData::NonRelative(_) => Err(ParseError::CannotSetPasswordWithNonRelativeScheme)
         }
         }
     }
     }
 
 
     /// `URLUtils.host` setter
     /// `URLUtils.host` setter
     fn set_host_and_port(&mut self, input: &str) -> ParseResult<()> {
     fn set_host_and_port(&mut self, input: &str) -> ParseResult<()> {
         match self.url.scheme_data {
         match self.url.scheme_data {
-            RelativeSchemeData(UrlRelativeSchemeData {
+            SchemeData::Relative(RelativeSchemeData {
                 ref mut host, ref mut port, ref mut default_port, ..
                 ref mut host, ref mut port, ref mut default_port, ..
             }) => {
             }) => {
                 let scheme_type = self.parser.get_scheme_type(self.url.scheme.as_slice());
                 let scheme_type = self.parser.get_scheme_type(self.url.scheme.as_slice());
@@ -87,28 +86,28 @@ impl<'a> UrlUtils for UrlUtilsWrapper<'a> {
                 *default_port = new_default_port;
                 *default_port = new_default_port;
                 Ok(())
                 Ok(())
             },
             },
-            NonRelativeSchemeData(_) => Err(ParseError::CannotSetHostPortWithNonRelativeScheme)
+            SchemeData::NonRelative(_) => Err(ParseError::CannotSetHostPortWithNonRelativeScheme)
         }
         }
     }
     }
 
 
     /// `URLUtils.hostname` setter
     /// `URLUtils.hostname` setter
     fn set_host(&mut self, input: &str) -> ParseResult<()> {
     fn set_host(&mut self, input: &str) -> ParseResult<()> {
         match self.url.scheme_data {
         match self.url.scheme_data {
-            RelativeSchemeData(UrlRelativeSchemeData { ref mut host, .. }) => {
+            SchemeData::Relative(RelativeSchemeData { ref mut host, .. }) => {
                 let (new_host, _) = try!(::parser::parse_hostname(input, self.parser));
                 let (new_host, _) = try!(::parser::parse_hostname(input, self.parser));
                 *host = new_host;
                 *host = new_host;
                 Ok(())
                 Ok(())
             },
             },
-            NonRelativeSchemeData(_) => Err(ParseError::CannotSetHostWithNonRelativeScheme)
+            SchemeData::NonRelative(_) => Err(ParseError::CannotSetHostWithNonRelativeScheme)
         }
         }
     }
     }
 
 
     /// `URLUtils.port` setter
     /// `URLUtils.port` setter
     fn set_port(&mut self, input: &str) -> ParseResult<()> {
     fn set_port(&mut self, input: &str) -> ParseResult<()> {
         match self.url.scheme_data {
         match self.url.scheme_data {
-            RelativeSchemeData(UrlRelativeSchemeData { ref mut port, ref mut default_port, .. }) => {
+            SchemeData::Relative(RelativeSchemeData { ref mut port, ref mut default_port, .. }) => {
                 let scheme_type = self.parser.get_scheme_type(self.url.scheme.as_slice());
                 let scheme_type = self.parser.get_scheme_type(self.url.scheme.as_slice());
-                if scheme_type == FileLikeRelativeScheme {
+                if scheme_type == SchemeType::FileLike {
                     return Err(ParseError::CannotSetPortWithFileLikeScheme);
                     return Err(ParseError::CannotSetPortWithFileLikeScheme);
                 }
                 }
                 let (new_port, new_default_port, _) = try!(::parser::parse_port(
                 let (new_port, new_default_port, _) = try!(::parser::parse_port(
@@ -117,21 +116,21 @@ impl<'a> UrlUtils for UrlUtilsWrapper<'a> {
                 *default_port = new_default_port;
                 *default_port = new_default_port;
                 Ok(())
                 Ok(())
             },
             },
-            NonRelativeSchemeData(_) => Err(ParseError::CannotSetPortWithNonRelativeScheme)
+            SchemeData::NonRelative(_) => Err(ParseError::CannotSetPortWithNonRelativeScheme)
         }
         }
     }
     }
 
 
     /// `URLUtils.pathname` setter
     /// `URLUtils.pathname` setter
     fn set_path(&mut self, input: &str) -> ParseResult<()> {
     fn set_path(&mut self, input: &str) -> ParseResult<()> {
         match self.url.scheme_data {
         match self.url.scheme_data {
-            RelativeSchemeData(UrlRelativeSchemeData { ref mut path, .. }) => {
+            SchemeData::Relative(RelativeSchemeData { ref mut path, .. }) => {
                 let scheme_type = self.parser.get_scheme_type(self.url.scheme.as_slice());
                 let scheme_type = self.parser.get_scheme_type(self.url.scheme.as_slice());
                 let (new_path, _) = try!(::parser::parse_path_start(
                 let (new_path, _) = try!(::parser::parse_path_start(
-                    input, ::parser::SetterContext, scheme_type, self.parser));
+                    input, Context::Setter, scheme_type, self.parser));
                 *path = new_path;
                 *path = new_path;
                 Ok(())
                 Ok(())
             },
             },
-            NonRelativeSchemeData(_) => Err(ParseError::CannotSetPathWithNonRelativeScheme)
+            SchemeData::NonRelative(_) => Err(ParseError::CannotSetPathWithNonRelativeScheme)
         }
         }
     }
     }
 
 
@@ -142,7 +141,7 @@ impl<'a> UrlUtils for UrlUtilsWrapper<'a> {
         } else {
         } else {
             let input = if input.starts_with("?") { input.slice_from(1) } else { input };
             let input = if input.starts_with("?") { input.slice_from(1) } else { input };
             let (new_query, _) = try!(::parser::parse_query(
             let (new_query, _) = try!(::parser::parse_query(
-                input, ::parser::SetterContext, self.parser));
+                input, Context::Setter, self.parser));
             Some(new_query)
             Some(new_query)
         };
         };
         Ok(())
         Ok(())