|
7 | 7 | //! - The [`Resolve`](Resolve) trait and related types to build a custom |
8 | 8 | //! resolver for use with the `HttpConnector`. |
9 | 9 | use std::{fmt, io, vec}; |
| 10 | +use std::error::Error; |
10 | 11 | use std::net::{ |
11 | 12 | IpAddr, Ipv4Addr, Ipv6Addr, |
12 | 13 | SocketAddr, ToSocketAddrs, |
13 | 14 | SocketAddrV4, SocketAddrV6, |
14 | 15 | }; |
| 16 | +use std::str::FromStr; |
15 | 17 | use std::sync::Arc; |
16 | 18 |
|
17 | 19 | use futures::{Async, Future, Poll}; |
@@ -72,6 +74,32 @@ impl fmt::Debug for Name { |
72 | 74 | } |
73 | 75 | } |
74 | 76 |
|
| 77 | +impl FromStr for Name { |
| 78 | + type Err = InvalidNameError; |
| 79 | + |
| 80 | + fn from_str(host: &str) -> Result<Self, Self::Err> { |
| 81 | + // Possibly add validation later |
| 82 | + Ok(Name::new(host.to_owned())) |
| 83 | + } |
| 84 | +} |
| 85 | + |
| 86 | +/// Error indicating a given string was not a valid domain name. |
| 87 | +#[derive(Debug)] |
| 88 | +pub struct InvalidNameError(()); |
| 89 | + |
| 90 | +impl fmt::Display for InvalidNameError { |
| 91 | + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
| 92 | + self.description().fmt(f) |
| 93 | + } |
| 94 | +} |
| 95 | + |
| 96 | +impl Error for InvalidNameError { |
| 97 | + fn description(&self) -> &str { |
| 98 | + "Not a valid domain name" |
| 99 | + } |
| 100 | +} |
| 101 | + |
| 102 | + |
75 | 103 | impl GaiResolver { |
76 | 104 | /// Construct a new `GaiResolver`. |
77 | 105 | /// |
@@ -317,4 +345,10 @@ mod tests { |
317 | 345 | assert!(preferred.next().unwrap().is_ipv6()); |
318 | 346 | assert!(fallback.next().unwrap().is_ipv4()); |
319 | 347 | } |
| 348 | + |
| 349 | + #[test] |
| 350 | + fn test_name_from_str() { |
| 351 | + let name = Name::from_str("test.example.com").expect("Should be a valid domain"); |
| 352 | + assert_eq!(name.as_str(), "test.example.com"); |
| 353 | + } |
320 | 354 | } |
0 commit comments