@@ -229,16 +229,10 @@ impl<'a> Uri<'a> {
229229 ///assert_eq!(uri.resource(), "/bar/baz?query#fragment");
230230 ///```
231231 pub fn resource ( & self ) -> & str {
232- let mut result = "/" ;
233-
234- for v in & [ self . path , self . query , self . fragment ] {
235- if let Some ( r) = v {
236- result = & self . inner [ r. start ..] ;
237- break ;
238- }
232+ match self . path {
233+ Some ( p) => & self . inner [ p. start ..] ,
234+ None => "/" ,
239235 }
240-
241- result
242236 }
243237}
244238
@@ -265,30 +259,38 @@ impl<'a> TryFrom<&'a str> for Uri<'a> {
265259 fn try_from ( s : & ' a str ) -> Result < Self , Self :: Error > {
266260 let ( scheme, mut uri_part) = get_chunks ( & s, Some ( RangeC :: new ( 0 , s. len ( ) ) ) , ":" ) ;
267261 let scheme = scheme. ok_or ( ParseErr :: UriErr ) ?;
262+ let ( mut authority, mut query, mut fragment) = ( None , None , None ) ;
268263
269- let mut authority = None ;
270-
271- if let Some ( u) = & uri_part {
272- if s[ * u] . contains ( "//" ) {
264+ if let Some ( u) = uri_part {
265+ if s[ u] . contains ( "//" ) {
273266 let ( auth, part) = get_chunks ( & s, Some ( RangeC :: new ( u. start + 2 , u. end ) ) , "/" ) ;
274267
275- authority = if let Some ( a) = auth {
276- Some ( Authority :: try_from ( & s[ a] ) ?)
277- } else {
278- None
268+ if let Some ( a) = auth {
269+ authority = Some ( Authority :: try_from ( & s[ a] ) ?)
279270 } ;
280271
281272 uri_part = part;
282273 }
283274 }
284275
285- let ( mut path , uri_part ) = get_chunks ( & s , uri_part, "?" ) ;
286-
287- if authority . is_some ( ) || & s [ scheme ] == "file" {
288- path = path . map ( |p| RangeC :: new ( p . start - 1 , p . end ) ) ;
276+ if let Some ( u ) = uri_part {
277+ if & s [ u . start - 1 ..u . start ] == "/" {
278+ uri_part = Some ( RangeC :: new ( u . start - 1 , u . end ) ) ;
279+ }
289280 }
290281
291- let ( query, fragment) = get_chunks ( & s, uri_part, "#" ) ;
282+ let mut path = uri_part;
283+
284+ if let Some ( u) = uri_part {
285+ if s[ u] . contains ( "?" ) && s[ u] . contains ( "#" ) {
286+ ( path, uri_part) = get_chunks ( & s, uri_part, "?" ) ;
287+ ( query, fragment) = get_chunks ( & s, uri_part, "#" ) ;
288+ } else if s[ u] . contains ( "?" ) {
289+ ( path, query) = get_chunks ( & s, uri_part, "?" ) ;
290+ } else if s[ u] . contains ( "#" ) {
291+ ( path, fragment) = get_chunks ( & s, uri_part, "#" ) ;
292+ }
293+ }
292294
293295 Ok ( Uri {
294296 inner : s,
@@ -405,17 +407,14 @@ impl<'a> TryFrom<&'a str> for Authority<'a> {
405407
406408 let uri_part = if s. contains ( '@' ) {
407409 let ( info, part) = get_chunks ( & s, Some ( RangeC :: new ( 0 , s. len ( ) ) ) , "@" ) ;
408- let ( name, pass) = get_chunks ( & s, info, ":" ) ;
409-
410- username = name;
411- password = pass;
410+ ( username, password) = get_chunks ( & s, info, ":" ) ;
412411
413412 part
414413 } else {
415414 Some ( RangeC :: new ( 0 , s. len ( ) ) )
416415 } ;
417416
418- let split_by = if s. contains ( '] ' ) && s. contains ( '[ ' ) {
417+ let split_by = if s. contains ( '[ ' ) && s. contains ( '] ' ) {
419418 "]:"
420419 } else {
421420 ":"
@@ -498,12 +497,14 @@ fn get_chunks<'a>(
498497mod tests {
499498 use super :: * ;
500499
501- const TEST_URIS : [ & str ; 5 ] = [
500+ const TEST_URIS : [ & str ; 7 ] = [
502501 "https://user:info@foo.com:12/bar/baz?query#fragment" ,
503502 "file:///C:/Users/User/Pictures/screenshot.png" ,
504503 "https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol" ,
505504 "mailto:John.Doe@example.com" ,
506505 "https://[4b10:bbb0:0:d0::ba7:8001]:443/" ,
506+ "http://example.com/?query=val" ,
507+ "https://example.com/#fragment" ,
507508 ] ;
508509
509510 const TEST_AUTH : [ & str ; 4 ] = [
@@ -552,12 +553,11 @@ mod tests {
552553 . iter ( )
553554 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
554555 . collect ( ) ;
556+ const RESULT : [ & str ; 7 ] = [ "https" , "file" , "https" , "mailto" , "https" , "http" , "https" ] ;
555557
556- assert_eq ! ( uris[ 0 ] . scheme( ) , "https" ) ;
557- assert_eq ! ( uris[ 1 ] . scheme( ) , "file" ) ;
558- assert_eq ! ( uris[ 2 ] . scheme( ) , "https" ) ;
559- assert_eq ! ( uris[ 3 ] . scheme( ) , "mailto" ) ;
560- assert_eq ! ( uris[ 4 ] . scheme( ) , "https" ) ;
558+ for i in 0 ..RESULT . len ( ) {
559+ assert_eq ! ( uris[ i] . scheme( ) , RESULT [ i] ) ;
560+ }
561561 }
562562
563563 #[ test]
@@ -566,12 +566,11 @@ mod tests {
566566 . iter ( )
567567 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
568568 . collect ( ) ;
569+ const RESULT : [ Option < & str > ; 7 ] = [ Some ( "user:info" ) , None , None , None , None , None , None ] ;
569570
570- assert_eq ! ( uris[ 0 ] . user_info( ) , Some ( "user:info" ) ) ;
571- assert_eq ! ( uris[ 1 ] . user_info( ) , None ) ;
572- assert_eq ! ( uris[ 2 ] . user_info( ) , None ) ;
573- assert_eq ! ( uris[ 3 ] . user_info( ) , None ) ;
574- assert_eq ! ( uris[ 4 ] . user_info( ) , None ) ;
571+ for i in 0 ..RESULT . len ( ) {
572+ assert_eq ! ( uris[ i] . user_info( ) , RESULT [ i] ) ;
573+ }
575574 }
576575
577576 #[ test]
@@ -581,11 +580,19 @@ mod tests {
581580 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
582581 . collect ( ) ;
583582
584- assert_eq ! ( uris[ 0 ] . host( ) , Some ( "foo.com" ) ) ;
585- assert_eq ! ( uris[ 1 ] . host( ) , None ) ;
586- assert_eq ! ( uris[ 2 ] . host( ) , Some ( "en.wikipedia.org" ) ) ;
587- assert_eq ! ( uris[ 3 ] . host( ) , None ) ;
588- assert_eq ! ( uris[ 4 ] . host( ) , Some ( "[4b10:bbb0:0:d0::ba7:8001]" ) ) ;
583+ const RESULT : [ Option < & str > ; 7 ] = [
584+ Some ( "foo.com" ) ,
585+ None ,
586+ Some ( "en.wikipedia.org" ) ,
587+ None ,
588+ Some ( "[4b10:bbb0:0:d0::ba7:8001]" ) ,
589+ Some ( "example.com" ) ,
590+ Some ( "example.com" ) ,
591+ ] ;
592+
593+ for i in 0 ..RESULT . len ( ) {
594+ assert_eq ! ( uris[ i] . host( ) , RESULT [ i] ) ;
595+ }
589596 }
590597
591598 #[ test]
@@ -612,7 +619,11 @@ mod tests {
612619 assert_eq ! ( uris[ 0 ] . port( ) , Some ( 12 ) ) ;
613620 assert_eq ! ( uris[ 4 ] . port( ) , Some ( 443 ) ) ;
614621
615- for i in 1 ..3 {
622+ for i in 1 ..4 {
623+ assert_eq ! ( uris[ i] . port( ) , None ) ;
624+ }
625+
626+ for i in 5 ..7 {
616627 assert_eq ! ( uris[ i] . port( ) , None ) ;
617628 }
618629 }
@@ -624,11 +635,13 @@ mod tests {
624635 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
625636 . collect ( ) ;
626637
627- assert_eq ! ( uris[ 0 ] . corr_port( ) , 12 ) ;
628- assert_eq ! ( uris[ 1 ] . corr_port( ) , HTTP_PORT ) ;
629- assert_eq ! ( uris[ 2 ] . corr_port( ) , HTTPS_PORT ) ;
630- assert_eq ! ( uris[ 3 ] . corr_port( ) , HTTP_PORT ) ;
631- assert_eq ! ( uris[ 4 ] . corr_port( ) , HTTPS_PORT ) ;
638+ const RESULT : [ u16 ; 7 ] = [
639+ 12 , HTTP_PORT , HTTPS_PORT , HTTP_PORT , HTTPS_PORT , HTTP_PORT , HTTPS_PORT ,
640+ ] ;
641+
642+ for i in 0 ..RESULT . len ( ) {
643+ assert_eq ! ( uris[ i] . corr_port( ) , RESULT [ i] ) ;
644+ }
632645 }
633646
634647 #[ test]
@@ -638,14 +651,19 @@ mod tests {
638651 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
639652 . collect ( ) ;
640653
641- assert_eq ! ( uris[ 0 ] . path( ) , Some ( "/bar/baz" ) ) ;
642- assert_eq ! (
643- uris[ 1 ] . path( ) ,
644- Some ( "/C:/Users/User/Pictures/screenshot.png" )
645- ) ;
646- assert_eq ! ( uris[ 2 ] . path( ) , Some ( "/wiki/Hypertext_Transfer_Protocol" ) ) ;
647- assert_eq ! ( uris[ 3 ] . path( ) , Some ( "John.Doe@example.com" ) ) ;
648- assert_eq ! ( uris[ 4 ] . path( ) , None ) ;
654+ const RESULT : [ Option < & str > ; 7 ] = [
655+ Some ( "/bar/baz" ) ,
656+ Some ( "/C:/Users/User/Pictures/screenshot.png" ) ,
657+ Some ( "/wiki/Hypertext_Transfer_Protocol" ) ,
658+ Some ( "John.Doe@example.com" ) ,
659+ None ,
660+ Some ( "/" ) ,
661+ Some ( "/" ) ,
662+ ] ;
663+
664+ for i in 0 ..RESULT . len ( ) {
665+ assert_eq ! ( uris[ i] . path( ) , RESULT [ i] ) ;
666+ }
649667 }
650668
651669 #[ test]
@@ -655,10 +673,18 @@ mod tests {
655673 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
656674 . collect ( ) ;
657675
658- assert_eq ! ( uris[ 0 ] . query( ) , Some ( "query" ) ) ;
659-
660- for i in 1 ..4 {
661- assert_eq ! ( uris[ i] . query( ) , None ) ;
676+ const RESULT : [ Option < & str > ; 7 ] = [
677+ Some ( "query" ) ,
678+ None ,
679+ None ,
680+ None ,
681+ None ,
682+ Some ( "query=val" ) ,
683+ None ,
684+ ] ;
685+
686+ for i in 0 ..RESULT . len ( ) {
687+ assert_eq ! ( uris[ i] . query( ) , RESULT [ i] ) ;
662688 }
663689 }
664690
@@ -669,10 +695,18 @@ mod tests {
669695 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
670696 . collect ( ) ;
671697
672- assert_eq ! ( uris[ 0 ] . fragment( ) , Some ( "fragment" ) ) ;
673-
674- for i in 1 ..4 {
675- assert_eq ! ( uris[ i] . fragment( ) , None ) ;
698+ const RESULT : [ Option < & str > ; 7 ] = [
699+ Some ( "fragment" ) ,
700+ None ,
701+ None ,
702+ None ,
703+ None ,
704+ None ,
705+ Some ( "fragment" ) ,
706+ ] ;
707+
708+ for i in 0 ..RESULT . len ( ) {
709+ assert_eq ! ( uris[ i] . fragment( ) , RESULT [ i] ) ;
676710 }
677711 }
678712
@@ -683,11 +717,19 @@ mod tests {
683717 . map ( |uri| Uri :: try_from ( * uri) . unwrap ( ) )
684718 . collect ( ) ;
685719
686- assert_eq ! ( uris[ 0 ] . resource( ) , "/bar/baz?query#fragment" ) ;
687- assert_eq ! ( uris[ 1 ] . resource( ) , "/C:/Users/User/Pictures/screenshot.png" ) ;
688- assert_eq ! ( uris[ 2 ] . resource( ) , "/wiki/Hypertext_Transfer_Protocol" ) ;
689- assert_eq ! ( uris[ 3 ] . resource( ) , "John.Doe@example.com" ) ;
690- assert_eq ! ( uris[ 4 ] . resource( ) , "/" ) ;
720+ const RESULT : [ & str ; 7 ] = [
721+ "/bar/baz?query#fragment" ,
722+ "/C:/Users/User/Pictures/screenshot.png" ,
723+ "/wiki/Hypertext_Transfer_Protocol" ,
724+ "John.Doe@example.com" ,
725+ "/" ,
726+ "/?query=val" ,
727+ "/#fragment"
728+ ] ;
729+
730+ for i in 0 ..RESULT . len ( ) {
731+ assert_eq ! ( uris[ i] . resource( ) , RESULT [ i] ) ;
732+ }
691733 }
692734
693735 #[ test]
0 commit comments