Skip to content

Commit fedf144

Browse files
author
bors-servo
committed
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 -->
2 parents a3cd772 + ab7f6fc commit fedf144

File tree

2 files changed

+88
-1
lines changed

2 files changed

+88
-1
lines changed

src/lib.rs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ use std::fmt::{self, Formatter};
137137
use std::str;
138138
use std::path::{Path, PathBuf};
139139
use std::borrow::Borrow;
140+
use std::hash::{Hash, Hasher};
141+
use std::cmp::Ordering;
140142

141143
#[cfg(feature="serde_serialization")]
142144
use std::str::FromStr;
@@ -226,7 +228,7 @@ pub enum SchemeData {
226228
}
227229

228230
/// Components for URLs in a *relative* scheme such as HTTP.
229-
#[derive(PartialEq, Eq, Clone, Debug, Hash, PartialOrd, Ord)]
231+
#[derive(Clone, Debug)]
230232
#[cfg_attr(feature="heap_size", derive(HeapSizeOf))]
231233
pub struct RelativeSchemeData {
232234
/// The username of the URL, as a possibly empty, percent-encoded string.
@@ -266,6 +268,45 @@ pub struct RelativeSchemeData {
266268
pub path: Vec<String>,
267269
}
268270

271+
impl RelativeSchemeData {
272+
fn get_identity_key(&self) -> (&String, &Option<String>, &Host, Option<u16>, Option<u16>, &Vec<String>) {
273+
(
274+
&self.username,
275+
&self.password,
276+
&self.host,
277+
self.port.or(self.default_port),
278+
self.default_port,
279+
&self.path
280+
)
281+
}
282+
}
283+
284+
285+
impl PartialEq for RelativeSchemeData {
286+
fn eq(&self, other: &RelativeSchemeData) -> bool {
287+
self.get_identity_key() == other.get_identity_key()
288+
}
289+
}
290+
291+
impl Eq for RelativeSchemeData {}
292+
293+
impl Hash for RelativeSchemeData {
294+
fn hash<H: Hasher>(&self, state: &mut H) {
295+
self.get_identity_key().hash(state)
296+
}
297+
}
298+
299+
impl PartialOrd for RelativeSchemeData {
300+
fn partial_cmp(&self, other: &RelativeSchemeData) -> Option<Ordering> {
301+
self.get_identity_key().partial_cmp(&other.get_identity_key())
302+
}
303+
}
304+
305+
impl Ord for RelativeSchemeData {
306+
fn cmp(&self, other: &Self) -> Ordering {
307+
self.get_identity_key().cmp(&other.get_identity_key())
308+
}
309+
}
269310

270311
impl str::FromStr for Url {
271312
type Err = ParseError;

src/tests.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,49 @@ fn issue_124() {
301301
let url: Url = "file:..".parse().unwrap();
302302
assert_eq!(url.path().unwrap(), [""]);
303303
}
304+
305+
#[test]
306+
fn relative_scheme_data_equality() {
307+
use std::hash::{Hash, Hasher, SipHasher};
308+
309+
fn check_eq(a: &Url, b: &Url) {
310+
assert_eq!(a, b);
311+
312+
let mut h1 = SipHasher::new();
313+
a.hash(&mut h1);
314+
let mut h2 = SipHasher::new();
315+
b.hash(&mut h2);
316+
assert_eq!(h1.finish(), h2.finish());
317+
}
318+
319+
fn url(s: &str) -> Url {
320+
let rv = s.parse().unwrap();
321+
check_eq(&rv, &rv);
322+
rv
323+
}
324+
325+
// Doesn't care if default port is given.
326+
let a: Url = url("https://example.com/");
327+
let b: Url = url("https://example.com:443/");
328+
check_eq(&a, &b);
329+
330+
// Different ports
331+
let a: Url = url("http://example.com/");
332+
let b: Url = url("http://example.com:8080/");
333+
assert!(a != b);
334+
335+
// Different scheme
336+
let a: Url = url("http://example.com/");
337+
let b: Url = url("https://example.com/");
338+
assert!(a != b);
339+
340+
// Different host
341+
let a: Url = url("http://foo.com/");
342+
let b: Url = url("http://bar.com/");
343+
assert!(a != b);
344+
345+
// Missing path, automatically substituted. Semantically the same.
346+
let a: Url = url("http://foo.com");
347+
let b: Url = url("http://foo.com/");
348+
check_eq(&a, &b);
349+
}

0 commit comments

Comments
 (0)