Skip to content

Implement HttpTryFrom<HashMap<String,String>> for HeaderMap #326

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jul 25, 2019
3 changes: 2 additions & 1 deletion src/convert.rs
Original file line number Diff line number Diff line change
@@ -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,
52 changes: 47 additions & 5 deletions src/header/map.rs
Original file line number Diff line number Diff line change
@@ -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<T> FromIterator<(HeaderName, T)> for HeaderMap<T>
}
}

/// Convert a collection of tuples into a HeaderMap
///
/// # Examples
///
/// ```
/// # use http::{HttpTryFrom, Result, header::HeaderMap};
/// # use std::collections::HashMap;
/// let mut headers_hashmap: HashMap<String, String> = vec![
/// ("X-Custom-Header".to_string(), "my value".to_string()),
/// ].iter().cloned().collect();
///
/// let good_headers: Result<HeaderMap> = HeaderMap::try_from(&headers_hashmap);
/// assert!(good_headers.is_ok());
///
/// headers_hashmap.insert("\r".into(), "\0".into());
/// let bad_headers: Result<HeaderMap> = HeaderMap::try_from(&headers_hashmap);
/// assert!(bad_headers.is_err());
/// ```
impl<'a, K, V> HttpTryFrom<&'a HashMap<K, V>> for HeaderMap<HeaderValue>
where
K: Eq + Hash,
HeaderName: HttpTryFrom<&'a K>,
HeaderValue: HttpTryFrom<&'a V>
{
type Error = Error;

fn try_from(c: &'a HashMap<K, V>) -> Result<Self, Self::Error> {
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<T> Extend<(Option<HeaderName>, T)> for HeaderMap<T> {
/// 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`,
8 changes: 8 additions & 0 deletions src/header/name.rs
Original file line number Diff line number Diff line change
@@ -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, Self::Error> {
Self::from_bytes(s.as_bytes())
}
}

impl<'a> HttpTryFrom<&'a [u8]> for HeaderName {
type Error = InvalidHeaderName;
#[inline]
8 changes: 8 additions & 0 deletions src/header/value.rs
Original file line number Diff line number Diff line change
@@ -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, Self::Error> {
Self::from_bytes(s.as_bytes())
}
}

impl<'a> HttpTryFrom<&'a [u8]> for HeaderValue {
type Error = InvalidHeaderValue;