@@ -1603,8 +1603,13 @@ impl Url {
16031603 self . set_host_internal ( Host :: parse_opaque ( host_substr) ?, None ) ;
16041604 }
16051605 } else if self . has_host ( ) {
1606- if SchemeType :: from ( self . scheme ( ) ) . is_special ( ) {
1606+ let scheme_type = SchemeType :: from ( self . scheme ( ) ) ;
1607+ if scheme_type. is_special ( ) {
16071608 return Err ( ParseError :: EmptyHost ) ;
1609+ } else {
1610+ if self . serialization . len ( ) == self . path_start as usize {
1611+ self . serialization . push ( '/' ) ;
1612+ }
16081613 }
16091614 debug_assert ! ( self . byte_at( self . scheme_end) == b':' ) ;
16101615 debug_assert ! ( self . byte_at( self . path_start) == b'/' ) ;
@@ -1907,14 +1912,28 @@ impl Url {
19071912 ///
19081913 /// # fn run() -> Result<(), ParseError> {
19091914 /// let mut url = Url::parse("https://example.net")?;
1910- /// let result = url.set_scheme("foo ");
1911- /// assert_eq!(url.as_str(), "foo ://example.net/");
1915+ /// let result = url.set_scheme("http ");
1916+ /// assert_eq!(url.as_str(), "http ://example.net/");
19121917 /// assert!(result.is_ok());
19131918 /// # Ok(())
19141919 /// # }
19151920 /// # run().unwrap();
19161921 /// ```
1922+ /// Change the URL’s scheme from `foo` to `bar`:
19171923 ///
1924+ /// ```
1925+ /// use url::Url;
1926+ /// # use url::ParseError;
1927+ ///
1928+ /// # fn run() -> Result<(), ParseError> {
1929+ /// let mut url = Url::parse("foo://example.net")?;
1930+ /// let result = url.set_scheme("bar");
1931+ /// assert_eq!(url.as_str(), "bar://example.net");
1932+ /// assert!(result.is_ok());
1933+ /// # Ok(())
1934+ /// # }
1935+ /// # run().unwrap();
1936+ /// ```
19181937 ///
19191938 /// Cannot change URL’s scheme from `https` to `foõ`:
19201939 ///
@@ -1947,14 +1966,49 @@ impl Url {
19471966 /// # }
19481967 /// # run().unwrap();
19491968 /// ```
1969+ /// Cannot change the URL’s scheme from `foo` to `https`:
1970+ ///
1971+ /// ```
1972+ /// use url::Url;
1973+ /// # use url::ParseError;
1974+ ///
1975+ /// # fn run() -> Result<(), ParseError> {
1976+ /// let mut url = Url::parse("foo://example.net")?;
1977+ /// let result = url.set_scheme("https");
1978+ /// assert_eq!(url.as_str(), "foo://example.net");
1979+ /// assert!(result.is_err());
1980+ /// # Ok(())
1981+ /// # }
1982+ /// # run().unwrap();
1983+ /// ```
1984+ /// Cannot change the URL’s scheme from `http` to `foo`:
1985+ ///
1986+ /// ```
1987+ /// use url::Url;
1988+ /// # use url::ParseError;
1989+ ///
1990+ /// # fn run() -> Result<(), ParseError> {
1991+ /// let mut url = Url::parse("http://example.net")?;
1992+ /// let result = url.set_scheme("foo");
1993+ /// assert_eq!(url.as_str(), "http://example.net/");
1994+ /// assert!(result.is_err());
1995+ /// # Ok(())
1996+ /// # }
1997+ /// # run().unwrap();
1998+ /// ```
19501999 pub fn set_scheme ( & mut self , scheme : & str ) -> Result < ( ) , ( ) > {
19512000 let mut parser = Parser :: for_setter ( String :: new ( ) ) ;
19522001 let remaining = parser. parse_scheme ( parser:: Input :: new ( scheme) ) ?;
19532002 let new_scheme_type = SchemeType :: from ( & parser. serialization ) ;
19542003 let old_scheme_type = SchemeType :: from ( self . scheme ( ) ) ;
1955- // Switching from special scheme to non special scheme
1956- // and switching from file to non file is not allowed
1957- if old_scheme_type != new_scheme_type {
2004+ // If url’s scheme is a special scheme and buffer is not a special scheme, then return.
2005+ if new_scheme_type. is_special ( ) && !old_scheme_type. is_special ( ) ||
2006+ // If url’s scheme is not a special scheme and buffer is a special scheme, then return.
2007+ !new_scheme_type. is_special ( ) && old_scheme_type. is_special ( ) ||
2008+ // If url includes credentials or has a non-null port, and buffer is "file", then return.
2009+ // If url’s scheme is "file" and its host is an empty host or null, then return.
2010+ new_scheme_type. is_file ( ) && self . has_authority ( )
2011+ {
19582012 return Err ( ( ) ) ;
19592013 }
19602014
0 commit comments