Skip to content

Commit 6c4083c

Browse files
prasannavlseanmonstar
authored andcommitted
introduce TryFrom (#333)
1 parent 4cd6ca7 commit 6c4083c

File tree

3 files changed

+153
-72
lines changed

3 files changed

+153
-72
lines changed

src/uri/authority.rs

+37-11
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Deprecated in 1.26, needed until our minimum version is >=1.23.
22
#[allow(unused, deprecated)]
33
use std::ascii::AsciiExt;
4+
use std::convert::TryFrom;
45
use std::hash::{Hash, Hasher};
56
use std::str::FromStr;
67
use std::{cmp, fmt, str};
@@ -26,8 +27,7 @@ impl Authority {
2627

2728
/// Attempt to convert an `Authority` from `Bytes`.
2829
///
29-
/// This function will be replaced by a `TryFrom` implementation once the
30-
/// trait lands in stable.
30+
/// This function has been replaced by `TryFrom` implementation.
3131
///
3232
/// # Examples
3333
///
@@ -46,15 +46,7 @@ impl Authority {
4646
/// # }
4747
/// ```
4848
pub fn from_shared(s: Bytes) -> Result<Self, InvalidUriBytes> {
49-
let authority_end = Authority::parse_non_empty(&s[..]).map_err(InvalidUriBytes)?;
50-
51-
if authority_end != s.len() {
52-
return Err(ErrorKind::InvalidUriChar.into());
53-
}
54-
55-
Ok(Authority {
56-
data: unsafe { ByteStr::from_utf8_unchecked(s) },
57-
})
49+
TryFrom::try_from(s)
5850
}
5951

6052
/// Attempt to convert an `Authority` from a static string.
@@ -269,6 +261,40 @@ impl Authority {
269261
}
270262
}
271263

264+
impl TryFrom<Bytes> for Authority {
265+
type Error = InvalidUriBytes;
266+
/// Attempt to convert an `Authority` from `Bytes`.
267+
///
268+
/// # Examples
269+
///
270+
/// ```
271+
/// # extern crate http;
272+
/// # use http::uri::*;
273+
/// extern crate bytes;
274+
///
275+
/// use std::convert::TryFrom;
276+
/// use bytes::Bytes;
277+
///
278+
/// # pub fn main() {
279+
/// let bytes = Bytes::from("example.com");
280+
/// let authority = Authority::try_from(bytes).unwrap();
281+
///
282+
/// assert_eq!(authority.host(), "example.com");
283+
/// # }
284+
/// ```
285+
fn try_from(s: Bytes) -> Result<Self, Self::Error> {
286+
let authority_end = Authority::parse_non_empty(&s[..]).map_err(InvalidUriBytes)?;
287+
288+
if authority_end != s.len() {
289+
return Err(ErrorKind::InvalidUriChar.into());
290+
}
291+
292+
Ok(Authority {
293+
data: unsafe { ByteStr::from_utf8_unchecked(s) },
294+
})
295+
}
296+
}
297+
272298
impl AsRef<str> for Authority {
273299
fn as_ref(&self) -> &str {
274300
self.as_str()

src/uri/mod.rs

+77-49
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
2525
use crate::byte_str::ByteStr;
2626
use crate::HttpTryFrom;
27+
use std::convert::TryFrom;
2728

2829
use bytes::Bytes;
2930

@@ -241,8 +242,7 @@ impl Uri {
241242

242243
/// Attempt to convert a `Uri` from `Bytes`
243244
///
244-
/// This function will be replaced by a `TryFrom` implementation once the
245-
/// trait lands in stable.
245+
/// This function has been replaced by `TryFrom` implementation.
246246
///
247247
/// # Examples
248248
///
@@ -262,53 +262,7 @@ impl Uri {
262262
/// # }
263263
/// ```
264264
pub fn from_shared(s: Bytes) -> Result<Uri, InvalidUriBytes> {
265-
use self::ErrorKind::*;
266-
267-
if s.len() > MAX_LEN {
268-
return Err(TooLong.into());
269-
}
270-
271-
match s.len() {
272-
0 => {
273-
return Err(Empty.into());
274-
}
275-
1 => match s[0] {
276-
b'/' => {
277-
return Ok(Uri {
278-
scheme: Scheme::empty(),
279-
authority: Authority::empty(),
280-
path_and_query: PathAndQuery::slash(),
281-
});
282-
}
283-
b'*' => {
284-
return Ok(Uri {
285-
scheme: Scheme::empty(),
286-
authority: Authority::empty(),
287-
path_and_query: PathAndQuery::star(),
288-
});
289-
}
290-
_ => {
291-
let authority = Authority::from_shared(s)?;
292-
293-
return Ok(Uri {
294-
scheme: Scheme::empty(),
295-
authority: authority,
296-
path_and_query: PathAndQuery::empty(),
297-
});
298-
}
299-
},
300-
_ => {}
301-
}
302-
303-
if s[0] == b'/' {
304-
return Ok(Uri {
305-
scheme: Scheme::empty(),
306-
authority: Authority::empty(),
307-
path_and_query: PathAndQuery::from_shared(s)?,
308-
});
309-
}
310-
311-
parse_full(s)
265+
TryFrom::try_from(s)
312266
}
313267

314268
/// Convert a `Uri` from a static string.
@@ -679,6 +633,80 @@ impl Uri {
679633
}
680634
}
681635

636+
impl TryFrom<Bytes> for Uri {
637+
type Error = InvalidUriBytes;
638+
639+
/// Attempt to convert a `Uri` from `Bytes`
640+
///
641+
/// # Examples
642+
///
643+
/// ```
644+
/// # extern crate http;
645+
/// # use http::uri::*;
646+
/// extern crate bytes;
647+
///
648+
/// use std::convert::TryFrom;
649+
/// use bytes::Bytes;
650+
///
651+
/// # pub fn main() {
652+
/// let bytes = Bytes::from("http://example.com/foo");
653+
/// let uri = Uri::try_from(bytes).unwrap();
654+
///
655+
/// assert_eq!(uri.host().unwrap(), "example.com");
656+
/// assert_eq!(uri.path(), "/foo");
657+
/// # }
658+
/// ```
659+
fn try_from(s: Bytes) -> Result<Uri, Self::Error> {
660+
use self::ErrorKind::*;
661+
662+
if s.len() > MAX_LEN {
663+
return Err(TooLong.into());
664+
}
665+
666+
match s.len() {
667+
0 => {
668+
return Err(Empty.into());
669+
}
670+
1 => match s[0] {
671+
b'/' => {
672+
return Ok(Uri {
673+
scheme: Scheme::empty(),
674+
authority: Authority::empty(),
675+
path_and_query: PathAndQuery::slash(),
676+
});
677+
}
678+
b'*' => {
679+
return Ok(Uri {
680+
scheme: Scheme::empty(),
681+
authority: Authority::empty(),
682+
path_and_query: PathAndQuery::star(),
683+
});
684+
}
685+
_ => {
686+
let authority = Authority::from_shared(s)?;
687+
688+
return Ok(Uri {
689+
scheme: Scheme::empty(),
690+
authority: authority,
691+
path_and_query: PathAndQuery::empty(),
692+
});
693+
}
694+
},
695+
_ => {}
696+
}
697+
698+
if s[0] == b'/' {
699+
return Ok(Uri {
700+
scheme: Scheme::empty(),
701+
authority: Authority::empty(),
702+
path_and_query: PathAndQuery::from_shared(s)?,
703+
});
704+
}
705+
706+
parse_full(s)
707+
}
708+
}
709+
682710
impl<'a> HttpTryFrom<&'a str> for Uri {
683711
type Error = InvalidUri;
684712

src/uri/scheme.rs

+39-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Deprecated in 1.26, needed until our minimum version is >=1.23.
22
#[allow(unused, deprecated)]
33
use std::ascii::AsciiExt;
4+
use std::convert::TryFrom;
45
use std::fmt;
56
use std::hash::{Hash, Hasher};
67
use std::str::FromStr;
@@ -43,8 +44,7 @@ impl Scheme {
4344

4445
/// Attempt to convert a `Scheme` from `Bytes`
4546
///
46-
/// This function will be replaced by a `TryFrom` implementation once the
47-
/// trait lands in stable.
47+
/// This function has been replaced by `TryFrom` implementation
4848
///
4949
/// # Examples
5050
///
@@ -63,16 +63,7 @@ impl Scheme {
6363
/// # }
6464
/// ```
6565
pub fn from_shared(s: Bytes) -> Result<Self, InvalidUriBytes> {
66-
use self::Scheme2::*;
67-
68-
match Scheme2::parse_exact(&s[..]).map_err(InvalidUriBytes)? {
69-
None => Err(ErrorKind::InvalidScheme.into()),
70-
Standard(p) => Ok(Standard(p).into()),
71-
Other(_) => {
72-
let b = unsafe { ByteStr::from_utf8_unchecked(s) };
73-
Ok(Other(Box::new(b)).into())
74-
}
75-
}
66+
TryFrom::try_from(s)
7667
}
7768

7869
pub(super) fn empty() -> Self {
@@ -118,6 +109,42 @@ impl HttpTryFrom<Bytes> for Scheme {
118109
}
119110
}
120111

112+
impl TryFrom<Bytes> for Scheme {
113+
type Error = InvalidUriBytes;
114+
115+
/// Attempt to convert a `Scheme` from `Bytes`
116+
///
117+
/// # Examples
118+
///
119+
/// ```
120+
/// # extern crate http;
121+
/// # use http::uri::*;
122+
/// extern crate bytes;
123+
///
124+
/// use std::convert::TryFrom;
125+
/// use bytes::Bytes;
126+
///
127+
/// # pub fn main() {
128+
/// let bytes = Bytes::from("http");
129+
/// let scheme = Scheme::try_from(bytes).unwrap();
130+
///
131+
/// assert_eq!(scheme.as_str(), "http");
132+
/// # }
133+
/// ```
134+
fn try_from(s: Bytes) -> Result<Self, Self::Error> {
135+
use self::Scheme2::*;
136+
137+
match Scheme2::parse_exact(&s[..]).map_err(InvalidUriBytes)? {
138+
None => Err(ErrorKind::InvalidScheme.into()),
139+
Standard(p) => Ok(Standard(p).into()),
140+
Other(_) => {
141+
let b = unsafe { ByteStr::from_utf8_unchecked(s) };
142+
Ok(Other(Box::new(b)).into())
143+
}
144+
}
145+
}
146+
}
147+
121148
impl<'a> HttpTryFrom<&'a [u8]> for Scheme {
122149
type Error = InvalidUri;
123150
#[inline]

0 commit comments

Comments
 (0)