diff --git a/url/src/lib.rs b/url/src/lib.rs index f9830f272..4e24b20ef 100644 --- a/url/src/lib.rs +++ b/url/src/lib.rs @@ -2339,6 +2339,15 @@ impl<'a> TryFrom<&'a str> for Url { } } +impl<'a> TryFrom<&'a [u8]> for Url { + type Error = ParseError; + + fn try_from(bytes: &'a [u8]) -> Result { + let s = std::str::from_utf8(bytes).map_err(|_| ParseError::InvalidUtf8)?; + Url::parse(s) + } +} + /// Display the serialization of this URL. impl fmt::Display for Url { #[inline] diff --git a/url/src/parser.rs b/url/src/parser.rs index be7992e00..47150265d 100644 --- a/url/src/parser.rs +++ b/url/src/parser.rs @@ -87,6 +87,7 @@ simple_enum_error! { InvalidIpv4Address => "invalid IPv4 address", InvalidIpv6Address => "invalid IPv6 address", InvalidDomainCharacter => "invalid domain character", + InvalidUtf8 => "invalid UTF-8", RelativeUrlWithoutBase => "relative URL without a base", RelativeUrlWithCannotBeABaseBase => "relative URL with a cannot-be-a-base base", SetHostOnCannotBeABaseUrl => "a cannot-be-a-base URL doesn’t have a host to set", diff --git a/url/tests/unit.rs b/url/tests/unit.rs index adaa54de6..e9b4bba69 100644 --- a/url/tests/unit.rs +++ b/url/tests/unit.rs @@ -10,9 +10,10 @@ use std::borrow::Cow; use std::cell::{Cell, RefCell}; +use std::convert::TryFrom; use std::net::{Ipv4Addr, Ipv6Addr}; use std::path::{Path, PathBuf}; -use url::{form_urlencoded, Host, Url}; +use url::{form_urlencoded, Host, ParseError, Url}; #[test] fn size() { @@ -169,6 +170,21 @@ fn from_str() { assert!("http://testing.com/this".parse::().is_ok()); } +#[test] +fn try_from_str() { + assert!(Url::try_from("http://testing.com/this").is_ok()); +} + +#[test] +fn try_from_slice() { + assert!(Url::try_from(&b"http://testing.com/this"[..]).is_ok()); +} + +#[test] +fn try_from_slice_invalid_utf8() { + assert!(Url::try_from(&[0, 159, 146, 150][..]) == Err(ParseError::InvalidUtf8)); +} + #[test] fn parse_with_params() { let url = Url::parse_with_params(