@@ -255,23 +255,10 @@ impl<'a> Uri<'a> {
255255 let mut resource = self . resource ( ) . to_string ( ) ;
256256
257257 resource = match & relative_uri. get ( ..1 ) {
258- Some ( "#" ) => Uri :: add_part ( & resource, relative_uri, "#" ) ,
259- Some ( "?" ) => Uri :: add_part ( & self . path ( ) . unwrap_or ( "/" ) , relative_uri, "?" ) ,
260- Some ( "/" ) => Uri :: add_part ( & resource, relative_uri, "/" ) ,
261- Some ( _) | None => {
262- let part_idx = resource. rfind ( "/" ) ;
263-
264- match part_idx {
265- Some ( idx) => resource[ ..idx] . to_string ( ) + relative_uri,
266- None => {
267- if resource. starts_with ( "/" ) {
268- resource. to_string ( ) + relative_uri
269- } else {
270- resource. to_string ( ) + "/" + relative_uri
271- }
272- }
273- }
274- }
258+ Some ( "#" ) => Uri :: add_part_start ( & resource, relative_uri, "#" ) ,
259+ Some ( "?" ) => Uri :: add_part_start ( & self . path ( ) . unwrap_or ( "/" ) , relative_uri, "?" ) ,
260+ Some ( "/" ) => Uri :: add_part_start ( & resource, relative_uri, "/" ) ,
261+ Some ( _) | None => Uri :: add_part_end ( & resource, relative_uri, "/" ) ,
275262 } ;
276263
277264 * relative_uri = if let Some ( p) = self . path {
@@ -283,15 +270,43 @@ impl<'a> Uri<'a> {
283270 Uri :: try_from ( relative_uri. as_str ( ) )
284271 }
285272
286- /// Adds a part to a base at the position definied by a separator.
287- /// If the separator is not found, concatenates 2 strings together.
288- fn add_part ( base : & str , part : & str , separator : & str ) -> String {
289- let part_idx = base. find ( separator) ;
273+ /// Adds a part at the beggining of the base.
274+ /// Finds the first occurance of a separator in a base and the first occurance of a separator in a part.
275+ /// Joins all chars before the separator from the base, separator and all chars after the separator from the part.
276+ fn add_part_start ( base : & str , part : & str , separator : & str ) -> String {
277+ let base_idx = base. find ( separator) ;
278+ Uri :: add_part ( base, part, separator, base_idx)
279+ }
280+
281+ /// Adds a part at the end of the base.
282+ /// Finds the last occurance of a separator in a base and the first occurance of a separator in a part.
283+ /// Joins all chars before the separator from the base, separator and all chars after the separator from the part.
284+ fn add_part_end ( base : & str , part : & str , separator : & str ) -> String {
285+ let base_idx = base. rfind ( separator) ;
286+ Uri :: add_part ( base, part, separator, base_idx)
287+ }
288+
289+ /// Adds a part to the base with separator in between.
290+ /// Base index defines where part should be added.
291+ fn add_part ( base : & str , part : & str , separator : & str , base_idx : Option < usize > ) -> String {
292+ let mut output = String :: new ( ) ;
293+ let part_idx = part. find ( separator) ;
294+
295+ if let Some ( idx) = base_idx {
296+ output += & base[ ..idx] ;
297+ } else {
298+ output += base;
299+ }
300+
301+ output += separator;
290302
291- match part_idx {
292- Some ( idx) => base[ ..idx] . to_string ( ) + part,
293- None => base. to_string ( ) + part,
303+ if let Some ( idx) = part_idx {
304+ output += & part[ idx + 1 ..] ;
305+ } else {
306+ output += part;
294307 }
308+
309+ output
295310 }
296311}
297312
@@ -569,7 +584,7 @@ mod tests {
569584 "#fragment" ,
570585 "other-path" ,
571586 "#paragraph" ,
572- "/foo/bar/buz" ,
587+ ". /foo/bar/buz" ,
573588 "?users#1551" ,
574589 ] ;
575590
@@ -832,11 +847,43 @@ mod tests {
832847
833848 #[ test]
834849 fn uri_add_part ( ) {
835- const BASES : [ & str ; 2 ] = [ "/bar/baz?query" , "/bar/baz?query#some-fragment" ] ;
836- const RESULT : & str = "/bar/baz?query#another-fragment" ;
850+ const BASES : [ & str ; 2 ] = [ "/bar/baz/fizz?query" , "/bar/baz?query#some-fragment" ] ;
851+ const RESULT : [ & str ; 2 ] = [
852+ "/bar/baz/fizz?query#another-fragment" ,
853+ "/bar/baz?query#some-fragment#another-fragment" ,
854+ ] ;
855+
856+ for i in 0 ..BASES . len ( ) {
857+ assert_eq ! (
858+ Uri :: add_part( BASES [ i] , "#another-fragment" , "#" , Some ( BASES [ i] . len( ) ) ) ,
859+ RESULT [ i]
860+ ) ;
861+ }
862+ }
863+
864+ #[ test]
865+ fn uri_add_part_start ( ) {
866+ const BASES : [ & str ; 2 ] = [ "/bar/baz/fizz?query" , "/bar/baz?query#some-fragment" ] ;
867+ const RESULT : [ & str ; 2 ] = [
868+ "/bar/baz/fizz?query#another-fragment" ,
869+ "/bar/baz?query#another-fragment" ,
870+ ] ;
871+
872+ for i in 0 ..BASES . len ( ) {
873+ assert_eq ! (
874+ Uri :: add_part_start( BASES [ i] , "#another-fragment" , "#" ) ,
875+ RESULT [ i]
876+ ) ;
877+ }
878+ }
879+
880+ #[ test]
881+ fn uri_add_part_end ( ) {
882+ const BASES : [ & str ; 2 ] = [ "/bar/baz/fizz?query" , "/bar/baz?query#some-fragment" ] ;
883+ const RESULT : [ & str ; 2 ] = [ "/bar/baz/another" , "/bar/another" ] ;
837884
838885 for i in 0 ..BASES . len ( ) {
839- assert_eq ! ( Uri :: add_part ( BASES [ i] , "# another-fragment " , "# " ) , RESULT ) ;
886+ assert_eq ! ( Uri :: add_part_end ( BASES [ i] , "./ another" , "/ " ) , RESULT [ i ] ) ;
840887 }
841888 }
842889
0 commit comments