Răsfoiți Sursa

Add Url::domain and Url::ip_address

Simon Sapin 10 ani în urmă
părinte
comite
5364f2b19f
3 a modificat fișierele cu 44 adăugiri și 0 ștergeri
  1. 1 0
      Cargo.toml
  2. 17 0
      build.rs
  3. 26 0
      src/lib.rs

+ 1 - 0
Cargo.toml

@@ -10,6 +10,7 @@ repository = "https://github.com/servo/rust-url"
 readme = "README.md"
 keywords = ["url", "parser"]
 license = "MIT/Apache-2.0"
+build = "build.rs"
 
 [[test]]
 name = "form_urlencoded"

+ 17 - 0
build.rs

@@ -0,0 +1,17 @@
+use std::process::{Command, Stdio};
+use std::io::Write;
+
+fn main() {
+    let mut child = Command::new(option_env!("RUSTC").unwrap_or("rustc"))
+        .args(&["-", "--crate-type", "lib", "-Z", "no-trans"])
+        .stdin(Stdio::piped())
+        .stdout(Stdio::null())
+        .stderr(Stdio::null())
+        .spawn()
+        .unwrap();
+    child.stdin.as_mut().unwrap().write_all(b"use std::net::IpAddr;").unwrap();
+    if child.wait().unwrap().success() {
+        // We can use `IpAddr` as it is `#[stable]` in this version of Rust.
+        println!("cargo:rustc-cfg=has_ipaddr")
+    }
+}

+ 26 - 0
src/lib.rs

@@ -130,6 +130,7 @@ use percent_encoding::{PATH_SEGMENT_ENCODE_SET, percent_encode, percent_decode};
 use std::cmp;
 use std::fmt;
 use std::hash;
+#[cfg(has_ipaddr)] use std::net::IpAddr;
 use std::ops::{Range, RangeFrom, RangeTo};
 use std::path::{Path, PathBuf};
 use std::str;
@@ -241,7 +242,9 @@ impl Url {
     }
 
     /// Return the string representation of the host (domain or IP address) for this URL, if any.
+    ///
     /// Non-ASCII domains are punycode-encoded per IDNA.
+    /// IPv6 addresses are given between `[` and `]` brackets.
     ///
     /// Non-relative URLs (typical of `data:` and `mailto:`) and some `file:` URLs
     /// don’t have a host.
@@ -271,6 +274,29 @@ impl Url {
         }
     }
 
+    /// If this URL has a host and it is a domain name (not an IP address), return it.
+    pub fn domain(&self) -> Option<&str> {
+        match self.host {
+            HostInternal::None => None,
+            HostInternal::Domain => Some(self.slice(self.host_start..self.host_end)),
+            HostInternal::Ipv4(_) => None,
+            HostInternal::Ipv6(_) => None,
+        }
+    }
+
+    /// If this URL has a host and it is an IP address (not a domain name), return it.
+    ///
+    /// This does **not** resolve domain names.
+    #[cfg(has_ipaddr)]
+    pub fn ip_address(&self) -> Option<IpAddr> {
+        match self.host {
+            HostInternal::None => None,
+            HostInternal::Domain => None,
+            HostInternal::Ipv4(address) => Some(IpAddr::V4(address)),
+            HostInternal::Ipv6(address) => Some(IpAddr::V6(address)),
+        }
+    }
+
     /// Return the port number for this URL, if any.
     #[inline]
     pub fn port(&self) -> Option<u16> {