Explorar o código

Auto merge of #237 - servo:v4-in-v6, r=Manishearth

Fix support for for IPv4-in-IPv6 syntax.

r? @Manishearth

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/237)
<!-- Reviewable:end -->
bors-servo %!s(int64=10) %!d(string=hai) anos
pai
achega
37b4562390
Modificáronse 4 ficheiros con 105 adicións e 9 borrados
  1. 1 1
      Cargo.toml
  2. 17 7
      src/host.rs
  3. 4 1
      src/lib.rs
  4. 83 0
      tests/urltestdata.json

+ 1 - 1
Cargo.toml

@@ -1,7 +1,7 @@
 [package]
 
 name = "url"
-version = "1.2.2"
+version = "1.2.3"
 authors = ["The rust-url developers"]
 
 description = "URL library for Rust, based on the WHATWG URL Standard"

+ 17 - 7
src/host.rs

@@ -371,23 +371,33 @@ fn parse_ipv6addr(input: &str) -> ParseResult<Ipv6Addr> {
         }
         let mut dots_seen = 0;
         while i < len {
-            // FIXME: https://github.com/whatwg/url/commit/1c22aa119c354e0020117e02571cec53f7c01064
-            let mut value = 0u16;
+            let mut value = None;
             while i < len {
                 let digit = match input[i] {
                     c @ b'0' ... b'9' => c - b'0',
                     _ => break
                 };
-                value = value * 10 + digit as u16;
-                if value == 0 || value > 255 {
-                    return Err(ParseError::InvalidIpv6Address)
+                match value {
+                    None => value = Some(digit as u16),
+                    Some(0) => return Err(ParseError::InvalidIpv6Address),  // No leading zero
+                    Some(ref mut v) => {
+                        *v = *v * 10 + digit as u16;
+                        if *v > 255 {
+                            return Err(ParseError::InvalidIpv6Address)
+                        }
+                    }
                 }
+                i += 1;
             }
             if dots_seen < 3 && !(i < len && input[i] == b'.') {
                 return Err(ParseError::InvalidIpv6Address)
             }
-            pieces[piece_pointer] = pieces[piece_pointer] * 0x100 + value;
-            if dots_seen == 0 || dots_seen == 2 {
+            pieces[piece_pointer] = if let Some(v) = value {
+                pieces[piece_pointer] * 0x100 + v
+            } else {
+                return Err(ParseError::InvalidIpv6Address)
+            };
+            if dots_seen == 1 || dots_seen == 3 {
                 piece_pointer += 1;
             }
             i += 1;

+ 4 - 1
src/lib.rs

@@ -314,7 +314,10 @@ impl Url {
             match self.host {
                 HostInternal::None => assert_eq!(host_str, ""),
                 HostInternal::Ipv4(address) => assert_eq!(host_str, address.to_string()),
-                HostInternal::Ipv6(address) => assert_eq!(host_str, format!("[{}]", address)),
+                HostInternal::Ipv6(address) => {
+                    let h: Host<String> = Host::Ipv6(address);
+                    assert_eq!(host_str, h.to_string())
+                }
                 HostInternal::Domain => {
                     if SchemeType::from(self.scheme()).is_special() {
                         assert!(!host_str.is_empty())

+ 83 - 0
tests/urltestdata.json

@@ -840,6 +840,36 @@
     "search": "",
     "hash": ""
   },
+  {
+    "input": "http://[::127.0.0.1]",
+    "base": "http://example.org/foo/bar",
+    "href": "http://[::7f00:1]/",
+    "origin": "http://[::7f00:1]",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "[::7f00:1]",
+    "hostname": "[::7f00:1]",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
+  {
+    "input": "http://[0:0:0:0:0:0:13.1.68.3]",
+    "base": "http://example.org/foo/bar",
+    "href": "http://[::d01:4403]/",
+    "origin": "http://[::d01:4403]",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "[::d01:4403]",
+    "hostname": "[::d01:4403]",
+    "port": "",
+    "pathname": "/",
+    "search": "",
+    "hash": ""
+  },
   {
     "input": "http://[2001::1]:80",
     "base": "http://example.org/foo/bar",
@@ -1289,6 +1319,21 @@
     "search": "",
     "hash": "#test"
   },
+  {
+    "input": "tel:1234567890",
+    "base": "http://example.org/foo/bar",
+    "href": "tel:1234567890",
+    "origin": "null",
+    "protocol": "tel:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "1234567890",
+    "search": "",
+    "hash": ""
+  },
   "# Based on http://trac.webkit.org/browser/trunk/LayoutTests/fast/url/file.html",
   {
     "input": "file:c:\\foo\\bar.html",
@@ -4273,5 +4318,43 @@
     "search": "??a=b&c=d",
     "searchParams": "%3Fa=b&c=d",
     "hash": ""
+  },
+  "# Scheme only",
+  {
+    "input": "http:",
+    "base": "http://example.org/foo/bar",
+    "href": "http://example.org/foo/bar",
+    "origin": "http://example.org",
+    "protocol": "http:",
+    "username": "",
+    "password": "",
+    "host": "example.org",
+    "hostname": "example.org",
+    "port": "",
+    "pathname": "/foo/bar",
+    "search": "",
+    "searchParams": "",
+    "hash": ""
+  },
+  {
+    "input": "http:",
+    "base": "https://example.org/foo/bar",
+    "failure": true
+  },
+  {
+    "input": "sc:",
+    "base": "https://example.org/foo/bar",
+    "href": "sc:",
+    "origin": "null",
+    "protocol": "sc:",
+    "username": "",
+    "password": "",
+    "host": "",
+    "hostname": "",
+    "port": "",
+    "pathname": "",
+    "search": "",
+    "searchParams": "",
+    "hash": ""
   }
 ]