@@ -136,7 +136,7 @@ pub enum Error {
136136 #[ error( "Invalid url: \" {0}\" " ) ]
137137 ParseUrl ( String ) ,
138138}
139-
139+ # [ derive ( Clone ) ]
140140pub 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+
458533impl 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) ]
485560mod 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:pwd@example.com" ,
589+ "https://user:pwd@example.com" ,
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