@@ -1663,8 +1663,13 @@ impl Url {
1663
1663
self . set_host_internal ( Host :: parse_opaque ( host_substr) ?, None ) ;
1664
1664
}
1665
1665
} else if self . has_host ( ) {
1666
- if SchemeType :: from ( self . scheme ( ) ) . is_special ( ) {
1666
+ let scheme_type = SchemeType :: from ( self . scheme ( ) ) ;
1667
+ if scheme_type. is_special ( ) {
1667
1668
return Err ( ParseError :: EmptyHost ) ;
1669
+ } else {
1670
+ if self . serialization . len ( ) == self . path_start as usize {
1671
+ self . serialization . push ( '/' ) ;
1672
+ }
1668
1673
}
1669
1674
debug_assert ! ( self . byte_at( self . scheme_end) == b':' ) ;
1670
1675
debug_assert ! ( self . byte_at( self . path_start) == b'/' ) ;
@@ -1967,14 +1972,28 @@ impl Url {
1967
1972
///
1968
1973
/// # fn run() -> Result<(), ParseError> {
1969
1974
/// let mut url = Url::parse("https://example.net")?;
1970
- /// let result = url.set_scheme("foo ");
1971
- /// assert_eq!(url.as_str(), "foo ://example.net/");
1975
+ /// let result = url.set_scheme("http ");
1976
+ /// assert_eq!(url.as_str(), "http ://example.net/");
1972
1977
/// assert!(result.is_ok());
1973
1978
/// # Ok(())
1974
1979
/// # }
1975
1980
/// # run().unwrap();
1976
1981
/// ```
1982
+ /// Change the URL’s scheme from `foo` to `bar`:
1977
1983
///
1984
+ /// ```
1985
+ /// use url::Url;
1986
+ /// # use url::ParseError;
1987
+ ///
1988
+ /// # fn run() -> Result<(), ParseError> {
1989
+ /// let mut url = Url::parse("foo://example.net")?;
1990
+ /// let result = url.set_scheme("bar");
1991
+ /// assert_eq!(url.as_str(), "bar://example.net");
1992
+ /// assert!(result.is_ok());
1993
+ /// # Ok(())
1994
+ /// # }
1995
+ /// # run().unwrap();
1996
+ /// ```
1978
1997
///
1979
1998
/// Cannot change URL’s scheme from `https` to `foõ`:
1980
1999
///
@@ -2007,14 +2026,55 @@ impl Url {
2007
2026
/// # }
2008
2027
/// # run().unwrap();
2009
2028
/// ```
2029
+ /// Cannot change the URL’s scheme from `foo` to `https`:
2030
+ ///
2031
+ /// ```
2032
+ /// use url::Url;
2033
+ /// # use url::ParseError;
2034
+ ///
2035
+ /// # fn run() -> Result<(), ParseError> {
2036
+ /// let mut url = Url::parse("foo://example.net")?;
2037
+ /// let result = url.set_scheme("https");
2038
+ /// assert_eq!(url.as_str(), "foo://example.net");
2039
+ /// assert!(result.is_err());
2040
+ /// # Ok(())
2041
+ /// # }
2042
+ /// # run().unwrap();
2043
+ /// ```
2044
+ /// Cannot change the URL’s scheme from `http` to `foo`:
2045
+ ///
2046
+ /// ```
2047
+ /// use url::Url;
2048
+ /// # use url::ParseError;
2049
+ ///
2050
+ /// # fn run() -> Result<(), ParseError> {
2051
+ /// let mut url = Url::parse("http://example.net")?;
2052
+ /// let result = url.set_scheme("foo");
2053
+ /// assert_eq!(url.as_str(), "http://example.net/");
2054
+ /// assert!(result.is_err());
2055
+ /// # Ok(())
2056
+ /// # }
2057
+ /// # run().unwrap();
2058
+ /// ```
2010
2059
pub fn set_scheme ( & mut self , scheme : & str ) -> Result < ( ) , ( ) > {
2011
2060
let mut parser = Parser :: for_setter ( String :: new ( ) ) ;
2012
2061
let remaining = parser. parse_scheme ( parser:: Input :: new ( scheme) ) ?;
2013
- if !remaining. is_empty ( )
2014
- || ( !self . has_host ( ) && SchemeType :: from ( & parser. serialization ) . is_special ( ) )
2062
+ let new_scheme_type = SchemeType :: from ( & parser. serialization ) ;
2063
+ let old_scheme_type = SchemeType :: from ( self . scheme ( ) ) ;
2064
+ // If url’s scheme is a special scheme and buffer is not a special scheme, then return.
2065
+ if new_scheme_type. is_special ( ) && !old_scheme_type. is_special ( ) ||
2066
+ // If url’s scheme is not a special scheme and buffer is a special scheme, then return.
2067
+ !new_scheme_type. is_special ( ) && old_scheme_type. is_special ( ) ||
2068
+ // If url includes credentials or has a non-null port, and buffer is "file", then return.
2069
+ // If url’s scheme is "file" and its host is an empty host or null, then return.
2070
+ new_scheme_type. is_file ( ) && self . has_authority ( )
2015
2071
{
2016
2072
return Err ( ( ) ) ;
2017
2073
}
2074
+
2075
+ if !remaining. is_empty ( ) || ( !self . has_host ( ) && new_scheme_type. is_special ( ) ) {
2076
+ return Err ( ( ) ) ;
2077
+ }
2018
2078
let old_scheme_end = self . scheme_end ;
2019
2079
let new_scheme_end = to_u32 ( parser. serialization . len ( ) ) . unwrap ( ) ;
2020
2080
let adjust = |index : & mut u32 | {
@@ -2036,6 +2096,13 @@ impl Url {
2036
2096
2037
2097
parser. serialization . push_str ( self . slice ( old_scheme_end..) ) ;
2038
2098
self . serialization = parser. serialization ;
2099
+
2100
+ // Update the port so it can be removed
2101
+ // If it is the scheme's default
2102
+ // We don't mind it silently failing
2103
+ // If there was no port in the first place
2104
+ let _ = self . set_port ( self . port ( ) ) ;
2105
+
2039
2106
Ok ( ( ) )
2040
2107
}
2041
2108
0 commit comments