Skip to content

Commit f67bdcc

Browse files
chancedanonrig
authored andcommitted
implements numerous traits for Url
The traits include: - `std::fmt::Debug` - `std::cmp::PartialEq` - `std::cmp::Eq` - `std::cmp::PartialOrd` - `std::cmp::Ord` - `std::hash::Hash` - `std::borrow::Borrow<str>` - `std::borrow::Borrow<[u8]>` - `std::convert::AsRef<[u8]>` - `std::convert::TryFrom<&str>` - `std::convert::TryFrom<String>` - `std::convert::TryFrom<&String>`
1 parent 02e29e4 commit f67bdcc

File tree

1 file changed

+134
-2
lines changed

1 file changed

+134
-2
lines changed

src/lib.rs

Lines changed: 134 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ pub enum Error {
136136
#[error("Invalid url: \"{0}\"")]
137137
ParseUrl(String),
138138
}
139-
139+
#[derive(Clone)]
140140
pub struct Url {
141141
url: *mut ffi::ada_url,
142142
}
@@ -455,13 +455,88 @@ impl Url {
455455
}
456456
}
457457

458+
/// URLs compare like their stringification.
459+
impl PartialEq for Url {
460+
fn eq(&self, other: &Self) -> bool {
461+
self.href() == other.href()
462+
}
463+
}
464+
465+
impl Eq for Url {}
466+
467+
impl PartialOrd for Url {
468+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
469+
self.href().partial_cmp(other.href())
470+
}
471+
}
472+
473+
impl Ord for Url {
474+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
475+
self.href().cmp(other.href())
476+
}
477+
}
478+
479+
impl std::hash::Hash for Url {
480+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
481+
self.href().hash(state)
482+
}
483+
}
484+
485+
impl std::borrow::Borrow<str> for Url {
486+
fn borrow(&self) -> &str {
487+
self.href()
488+
}
489+
}
490+
491+
impl std::borrow::Borrow<[u8]> for Url {
492+
fn borrow(&self) -> &[u8] {
493+
self.href().as_bytes()
494+
}
495+
}
496+
497+
impl std::convert::AsRef<[u8]> for Url {
498+
fn as_ref(&self) -> &[u8] {
499+
self.href().as_bytes()
500+
}
501+
}
502+
503+
impl std::fmt::Debug for Url {
504+
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
505+
write!(f, "\"{}\"", self.href())
506+
}
507+
}
508+
509+
impl TryFrom<&str> for Url {
510+
type Error = Error;
511+
512+
fn try_from(value: &str) -> Result<Self, Self::Error> {
513+
Self::parse(value, None)
514+
}
515+
}
516+
517+
impl TryFrom<String> for Url {
518+
type Error = Error;
519+
520+
fn try_from(value: String) -> Result<Self, Self::Error> {
521+
Self::parse(&value, None)
522+
}
523+
}
524+
525+
impl TryFrom<&String> for Url {
526+
type Error = Error;
527+
528+
fn try_from(value: &String) -> Result<Self, Self::Error> {
529+
Self::parse(value, None)
530+
}
531+
}
532+
458533
impl std::ops::Deref for Url {
459534
type Target = str;
460535
fn deref(&self) -> &Self::Target {
461536
self.href()
462537
}
463538
}
464-
impl AsRef<str> for Url {
539+
impl std::convert::AsRef<str> for Url {
465540
fn as_ref(&self) -> &str {
466541
self.href()
467542
}
@@ -483,7 +558,64 @@ impl std::str::FromStr for Url {
483558

484559
#[cfg(test)]
485560
mod test {
561+
486562
use super::*;
563+
#[test]
564+
fn should_display_serialization() {
565+
let tests = [
566+
("http://example.com/", "http://example.com/"),
567+
("HTTP://EXAMPLE.COM", "http://example.com/"),
568+
(
569+
"http://user:pwd@domain:8080.com",
570+
"http://user:pwd@domain:8080.com/",
571+
),
572+
];
573+
for (value, expected) in tests {
574+
let url = Url::parse(value, None).expect("Should have parsed url");
575+
assert_eq!(format!("{}", url), expected);
576+
assert_eq!(url.to_string(), expected);
577+
}
578+
}
579+
580+
#[test]
581+
fn should_compare_urls() {
582+
let tests = [
583+
("http://example.com/", "http://example.com/", true),
584+
("http://example.com/", "https://example.com/", false),
585+
("http://example.com#", "https://example.com/#", false),
586+
("http://example.com", "https://example.com#", false),
587+
(
588+
"https://user:[email protected]",
589+
"https://user:[email protected]",
590+
true,
591+
),
592+
];
593+
for (left, right, expected) in tests {
594+
let left_url = Url::parse(left, None).expect("Should have parsed url");
595+
let right_url = Url::parse(right, None).expect("Should have parsed url");
596+
assert_eq!(
597+
left_url == right_url,
598+
expected,
599+
"left: {left}, right: {right}, expected: {expected}",
600+
);
601+
}
602+
}
603+
#[test]
604+
fn clone_should_create_new_instance() {
605+
let url = Url::parse("http://example.com/", None).expect("Should have parsed url");
606+
let cloned = url.clone();
607+
assert_eq!(url, cloned);
608+
assert_ne!(url.as_ptr(), cloned.as_ptr());
609+
}
610+
#[test]
611+
fn should_order_alphabetically() {
612+
let left = Url::parse("https://example.com/", None).expect("Should have parsed url");
613+
let right = Url::parse("https://zoo.tld/", None).expect("Should have parsed url");
614+
assert!(left < right);
615+
let left = Url::parse("https://c.tld/", None).expect("Should have parsed url");
616+
let right = Url::parse("https://a.tld/", None).expect("Should have parsed url");
617+
assert!(right < left);
618+
}
487619

488620
#[test]
489621
fn should_parse_simple_url() {

0 commit comments

Comments
 (0)