diff --git a/src/convert.rs b/src/convert.rs index 7f61c8ca..16943f77 100644 --- a/src/convert.rs +++ b/src/convert.rs @@ -1,5 +1,5 @@ use Error; -use header::{HeaderName, HeaderValue}; +use header::{HeaderName, HeaderValue, HeaderMap}; use method::Method; use sealed::Sealed; use status::StatusCode; @@ -56,6 +56,7 @@ reflexive! { Uri, Method, StatusCode, + HeaderMap, HeaderName, HeaderValue, Scheme, diff --git a/src/header/map.rs b/src/header/map.rs index 66f987cc..fd86cc6f 100644 --- a/src/header/map.rs +++ b/src/header/map.rs @@ -1,12 +1,16 @@ -use super::HeaderValue; -use super::name::{HeaderName, HdrName, InvalidHeaderName}; - use std::{fmt, mem, ops, ptr, vec}; use std::collections::hash_map::RandomState; -use std::hash::{BuildHasher, Hasher, Hash}; +use std::collections::HashMap; +use std::hash::{BuildHasher, Hash, Hasher}; use std::iter::FromIterator; use std::marker::PhantomData; +use convert::{HttpTryFrom, HttpTryInto}; +use Error; + +use super::HeaderValue; +use super::name::{HdrName, HeaderName, InvalidHeaderName}; + pub use self::as_header_name::AsHeaderName; pub use self::into_header_name::IntoHeaderName; @@ -23,6 +27,7 @@ pub use self::into_header_name::IntoHeaderName; /// ``` /// # use http::HeaderMap; /// # use http::header::{CONTENT_LENGTH, HOST, LOCATION}; +/// # use http::HttpTryFrom; /// let mut headers = HeaderMap::new(); /// /// headers.insert(HOST, "example.com".parse().unwrap()); @@ -1720,6 +1725,43 @@ impl FromIterator<(HeaderName, T)> for HeaderMap } } +/// Convert a collection of tuples into a HeaderMap +/// +/// # Examples +/// +/// ``` +/// # use http::{HttpTryFrom, Result, header::HeaderMap}; +/// # use std::collections::HashMap; +/// let mut headers_hashmap: HashMap = vec![ +/// ("X-Custom-Header".to_string(), "my value".to_string()), +/// ].iter().cloned().collect(); +/// +/// let good_headers: Result = HeaderMap::try_from(&headers_hashmap); +/// assert!(good_headers.is_ok()); +/// +/// headers_hashmap.insert("\r".into(), "\0".into()); +/// let bad_headers: Result = HeaderMap::try_from(&headers_hashmap); +/// assert!(bad_headers.is_err()); +/// ``` +impl<'a, K, V> HttpTryFrom<&'a HashMap> for HeaderMap + where + K: Eq + Hash, + HeaderName: HttpTryFrom<&'a K>, + HeaderValue: HttpTryFrom<&'a V> +{ + type Error = Error; + + fn try_from(c: &'a HashMap) -> Result { + c.into_iter() + .map(|(k, v)| -> ::Result<(HeaderName, HeaderValue)> { + let name : HeaderName = k.http_try_into()?; + let value : HeaderValue = v.http_try_into()?; + Ok((name, value)) + }) + .collect() + } +} + impl Extend<(Option, T)> for HeaderMap { /// Extend a `HeaderMap` with the contents of another `HeaderMap`. /// @@ -3161,7 +3203,7 @@ mod as_header_name { use super::{Entry, HdrName, HeaderMap, HeaderName, InvalidHeaderName}; /// A marker trait used to identify values that can be used as search keys - /// to a `HeaderMap`. + /// to a `HeaderMap`. pub trait AsHeaderName: Sealed {} // All methods are on this pub(super) trait, instead of `AsHeaderName`, diff --git a/src/header/name.rs b/src/header/name.rs index 28b1469e..d5c128c4 100644 --- a/src/header/name.rs +++ b/src/header/name.rs @@ -1772,6 +1772,14 @@ impl<'a> HttpTryFrom<&'a str> for HeaderName { } } +impl<'a> HttpTryFrom<&'a String> for HeaderName { + type Error = InvalidHeaderName; + #[inline] + fn try_from(s: &'a String) -> Result { + Self::from_bytes(s.as_bytes()) + } +} + impl<'a> HttpTryFrom<&'a [u8]> for HeaderName { type Error = InvalidHeaderName; #[inline] diff --git a/src/header/value.rs b/src/header/value.rs index a56baf79..a295ce55 100644 --- a/src/header/value.rs +++ b/src/header/value.rs @@ -521,6 +521,14 @@ impl<'a> HttpTryFrom<&'a str> for HeaderValue { } } +impl<'a> HttpTryFrom<&'a String> for HeaderValue { + type Error = InvalidHeaderValue; + #[inline] + fn try_from(s: &'a String) -> Result { + Self::from_bytes(s.as_bytes()) + } +} + impl<'a> HttpTryFrom<&'a [u8]> for HeaderValue { type Error = InvalidHeaderValue;