Przeglądaj źródła

Auto merge of #133 - untitaker:issue-132-port-eq, r=SimonSapin

Make port: None equal to port: default_port

Fix #132

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/rust-url/133)
<!-- Reviewable:end -->
bors-servo 11 lat temu
rodzic
commit
fedf144f1c
2 zmienionych plików z 88 dodań i 1 usunięć
  1. 42 1
      src/lib.rs
  2. 46 0
      src/tests.rs

+ 42 - 1
src/lib.rs

@@ -137,6 +137,8 @@ use std::fmt::{self, Formatter};
 use std::str;
 use std::path::{Path, PathBuf};
 use std::borrow::Borrow;
+use std::hash::{Hash, Hasher};
+use std::cmp::Ordering;
 
 #[cfg(feature="serde_serialization")]
 use std::str::FromStr;
@@ -226,7 +228,7 @@ pub enum SchemeData {
 }
 
 /// Components for URLs in a *relative* scheme such as HTTP.
-#[derive(PartialEq, Eq, Clone, Debug, Hash, PartialOrd, Ord)]
+#[derive(Clone, Debug)]
 #[cfg_attr(feature="heap_size", derive(HeapSizeOf))]
 pub struct RelativeSchemeData {
     /// The username of the URL, as a possibly empty, percent-encoded string.
@@ -266,6 +268,45 @@ pub struct RelativeSchemeData {
     pub path: Vec<String>,
 }
 
+impl RelativeSchemeData {
+    fn get_identity_key(&self) -> (&String, &Option<String>, &Host, Option<u16>, Option<u16>, &Vec<String>) {
+        (
+            &self.username,
+            &self.password,
+            &self.host,
+            self.port.or(self.default_port),
+            self.default_port,
+            &self.path
+        )
+    }
+}
+
+
+impl PartialEq for RelativeSchemeData {
+    fn eq(&self, other: &RelativeSchemeData) -> bool {
+        self.get_identity_key() == other.get_identity_key()
+    }
+}
+
+impl Eq for RelativeSchemeData {}
+
+impl Hash for RelativeSchemeData {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.get_identity_key().hash(state)
+    }
+}
+
+impl PartialOrd for RelativeSchemeData {
+    fn partial_cmp(&self, other: &RelativeSchemeData) -> Option<Ordering> {
+        self.get_identity_key().partial_cmp(&other.get_identity_key())
+    }
+}
+
+impl Ord for RelativeSchemeData {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.get_identity_key().cmp(&other.get_identity_key())
+    }
+}
 
 impl str::FromStr for Url {
     type Err = ParseError;

+ 46 - 0
src/tests.rs

@@ -301,3 +301,49 @@ fn issue_124() {
     let url: Url = "file:..".parse().unwrap();
     assert_eq!(url.path().unwrap(), [""]);
 }
+
+#[test]
+fn relative_scheme_data_equality() {
+    use std::hash::{Hash, Hasher, SipHasher};
+
+    fn check_eq(a: &Url, b: &Url) {
+        assert_eq!(a, b);
+
+        let mut h1 = SipHasher::new();
+        a.hash(&mut h1);
+        let mut h2 = SipHasher::new();
+        b.hash(&mut h2);
+        assert_eq!(h1.finish(), h2.finish());
+    }
+
+    fn url(s: &str) -> Url {
+        let rv = s.parse().unwrap();
+        check_eq(&rv, &rv);
+        rv
+    }
+
+    // Doesn't care if default port is given.
+    let a: Url = url("https://example.com/");
+    let b: Url = url("https://example.com:443/");
+    check_eq(&a, &b);
+
+    // Different ports
+    let a: Url = url("http://example.com/");
+    let b: Url = url("http://example.com:8080/");
+    assert!(a != b);
+
+    // Different scheme
+    let a: Url = url("http://example.com/");
+    let b: Url = url("https://example.com/");
+    assert!(a != b);
+
+    // Different host
+    let a: Url = url("http://foo.com/");
+    let b: Url = url("http://bar.com/");
+    assert!(a != b);
+
+    // Missing path, automatically substituted. Semantically the same.
+    let a: Url = url("http://foo.com");
+    let b: Url = url("http://foo.com/");
+    check_eq(&a, &b);
+}