@@ -301,7 +301,7 @@ impl Url {
301301 /// ```rust
302302 /// use url::Url;
303303 /// # use url::ParseError;
304- ///
304+ ///
305305 /// # fn run() -> Result<(), ParseError> {
306306 /// let base = Url::parse("https://example.net/a/b.html")?;
307307 /// let url = base.join("c.png")?;
@@ -729,6 +729,28 @@ impl Url {
729729 !matches ! ( self . host, HostInternal :: None )
730730 }
731731
732+ /// Equivalent to `url.port().is_some()`.
733+ ///
734+ /// # Examples
735+ ///
736+ /// ```
737+ /// use url::Url;
738+ /// # use url::ParseError;
739+ ///
740+ /// # fn run() -> Result<(), ParseError> {
741+ /// let url = Url::parse("http://example.com:8080")?;
742+ /// assert!(url.has_port());
743+ ///
744+ /// let url = Url::parse("file:///tmp/something")?;
745+ /// assert!(!url.has_port());
746+ /// # Ok(())
747+ /// # }
748+ /// # run().unwrap();
749+ /// ```
750+ pub fn has_port ( & self ) -> bool {
751+ self . port . is_some ( )
752+ }
753+
732754 /// Return the string representation of the host (domain or IP address) for this URL, if any.
733755 ///
734756 /// Non-ASCII domains are punycode-encoded per IDNA.
@@ -1310,7 +1332,7 @@ impl Url {
13101332 /// ```
13111333 /// use url::Url;
13121334 /// # use url::ParseError;
1313- ///
1335+ ///
13141336 /// # fn run() -> Result<(), ParseError> {
13151337 /// let mut url = Url::parse("foo://example.net")?;
13161338 /// let result = url.set_host(None);
@@ -1326,7 +1348,7 @@ impl Url {
13261348 /// ```
13271349 /// use url::Url;
13281350 /// # use url::ParseError;
1329- ///
1351+ ///
13301352 /// # fn run() -> Result<(), ParseError> {
13311353 /// let mut url = Url::parse("https://example.net")?;
13321354 /// let result = url.set_host(None);
@@ -1342,7 +1364,7 @@ impl Url {
13421364 /// ```
13431365 /// use url::Url;
13441366 /// # use url::ParseError;
1345- ///
1367+ ///
13461368 /// # fn run() -> Result<(), ParseError> {
13471369 /// let mut url = Url::parse("mailto:rms@example.net")?;
13481370 ///
@@ -1552,7 +1574,7 @@ impl Url {
15521574 /// ```
15531575 /// use url::Url;
15541576 /// # use url::ParseError;
1555- ///
1577+ ///
15561578 /// # fn run() -> Result<(), ParseError> {
15571579 /// let mut url = Url::parse("https://example.net")?;
15581580 /// let result = url.set_scheme("foo");
@@ -1569,7 +1591,7 @@ impl Url {
15691591 /// ```
15701592 /// use url::Url;
15711593 /// # use url::ParseError;
1572- ///
1594+ ///
15731595 /// # fn run() -> Result<(), ParseError> {
15741596 /// let mut url = Url::parse("https://example.net")?;
15751597 /// let result = url.set_scheme("foõ");
@@ -1585,7 +1607,7 @@ impl Url {
15851607 /// ```
15861608 /// use url::Url;
15871609 /// # use url::ParseError;
1588- ///
1610+ ///
15891611 /// # fn run() -> Result<(), ParseError> {
15901612 /// let mut url = Url::parse("mailto:rms@example.net")?;
15911613 /// let result = url.set_scheme("https");
@@ -1598,8 +1620,8 @@ impl Url {
15981620 pub fn set_scheme ( & mut self , scheme : & str ) -> Result < ( ) , ( ) > {
15991621 let mut parser = Parser :: for_setter ( String :: new ( ) ) ;
16001622 let remaining = parser. parse_scheme ( parser:: Input :: new ( scheme) ) ?;
1601- if !remaining. is_empty ( ) ||
1602- ( ! self . has_host ( ) && SchemeType :: from ( & parser. serialization ) . is_special ( ) ) {
1623+ if !( remaining. is_empty ( ) &&
1624+ self . can_use_scheme ( & parser. serialization ) ) {
16031625 return Err ( ( ) )
16041626 }
16051627 let old_scheme_end = self . scheme_end ;
@@ -1622,6 +1644,14 @@ impl Url {
16221644 Ok ( ( ) )
16231645 }
16241646
1647+ fn can_use_scheme ( & self , scheme : & str ) -> bool {
1648+ match SchemeType :: from ( scheme) {
1649+ SchemeType :: File => !( self . has_host ( ) || self . has_port ( ) ) ,
1650+ SchemeType :: SpecialNotFile => self . has_host ( ) ,
1651+ SchemeType :: NotSpecial => true
1652+ }
1653+ }
1654+
16251655 /// Convert a file name as `std::path::Path` into an URL in the `file` scheme.
16261656 ///
16271657 /// This returns `Err` if the given path is not absolute or,
@@ -1634,7 +1664,7 @@ impl Url {
16341664 /// ```
16351665 /// # if cfg!(unix) {
16361666 /// use url::Url;
1637- ///
1667+ ///
16381668 /// # fn run() -> Result<(), ()> {
16391669 /// let url = Url::from_file_path("/tmp/foo.txt")?;
16401670 /// assert_eq!(url.as_str(), "file:///tmp/foo.txt");
0 commit comments