Skip to content

Commit

Permalink
Implement HttpTryFrom<HashMap<String,String>> for HeaderMap (#326)
Browse files Browse the repository at this point in the history
  • Loading branch information
lovasoa authored and seanmonstar committed Nov 25, 2019
1 parent fd84409 commit 1c15957
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 5 deletions.
3 changes: 2 additions & 1 deletion src/convert.rs
@@ -1,4 +1,4 @@
use crate::header::{HeaderName, HeaderValue};
use crate::header::{HeaderMap, HeaderName, HeaderValue};
use crate::method::Method;
use crate::sealed::Sealed;
use crate::status::StatusCode;
Expand Down Expand Up @@ -55,6 +55,7 @@ reflexive! {
Uri,
Method,
StatusCode,
HeaderMap,
HeaderName,
HeaderValue,
Scheme,
Expand Down
50 changes: 46 additions & 4 deletions src/header/map.rs
@@ -1,12 +1,16 @@
use super::name::{HdrName, HeaderName, InvalidHeaderName};
use super::HeaderValue;

use std::collections::HashMap;
use std::collections::hash_map::RandomState;
use std::hash::{BuildHasher, Hash, Hasher};
use std::iter::{FromIterator, FusedIterator};
use std::marker::PhantomData;
use std::{fmt, mem, ops, ptr, vec};

use crate::convert::{HttpTryFrom, HttpTryInto};
use crate::Error;

use super::HeaderValue;
use super::name::{HdrName, HeaderName, InvalidHeaderName};

pub use self::as_header_name::AsHeaderName;
pub use self::into_header_name::IntoHeaderName;

Expand All @@ -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());
Expand Down Expand Up @@ -1749,6 +1754,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)| -> crate::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`.
///
Expand Down Expand Up @@ -3209,7 +3251,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`,
Expand Down
8 changes: 8 additions & 0 deletions src/header/name.rs
Expand Up @@ -1776,6 +1776,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]
Expand Down
8 changes: 8 additions & 0 deletions src/header/value.rs
Expand Up @@ -518,6 +518,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;

Expand Down

0 comments on commit 1c15957

Please sign in to comment.