Skip to content

Commit 1c15957

Browse files
lovasoaseanmonstar
authored andcommitted
Implement HttpTryFrom<HashMap<String,String>> for HeaderMap (#326)
1 parent fd84409 commit 1c15957

File tree

4 files changed

+64
-5
lines changed

4 files changed

+64
-5
lines changed

src/convert.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::header::{HeaderName, HeaderValue};
1+
use crate::header::{HeaderMap, HeaderName, HeaderValue};
22
use crate::method::Method;
33
use crate::sealed::Sealed;
44
use crate::status::StatusCode;
@@ -55,6 +55,7 @@ reflexive! {
5555
Uri,
5656
Method,
5757
StatusCode,
58+
HeaderMap,
5859
HeaderName,
5960
HeaderValue,
6061
Scheme,

src/header/map.rs

+46-4
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
1-
use super::name::{HdrName, HeaderName, InvalidHeaderName};
2-
use super::HeaderValue;
3-
1+
use std::collections::HashMap;
42
use std::collections::hash_map::RandomState;
53
use std::hash::{BuildHasher, Hash, Hasher};
64
use std::iter::{FromIterator, FusedIterator};
75
use std::marker::PhantomData;
86
use std::{fmt, mem, ops, ptr, vec};
97

8+
use crate::convert::{HttpTryFrom, HttpTryInto};
9+
use crate::Error;
10+
11+
use super::HeaderValue;
12+
use super::name::{HdrName, HeaderName, InvalidHeaderName};
13+
1014
pub use self::as_header_name::AsHeaderName;
1115
pub use self::into_header_name::IntoHeaderName;
1216

@@ -23,6 +27,7 @@ pub use self::into_header_name::IntoHeaderName;
2327
/// ```
2428
/// # use http::HeaderMap;
2529
/// # use http::header::{CONTENT_LENGTH, HOST, LOCATION};
30+
/// # use http::HttpTryFrom;
2631
/// let mut headers = HeaderMap::new();
2732
///
2833
/// headers.insert(HOST, "example.com".parse().unwrap());
@@ -1749,6 +1754,43 @@ impl<T> FromIterator<(HeaderName, T)> for HeaderMap<T> {
17491754
}
17501755
}
17511756

1757+
/// Convert a collection of tuples into a HeaderMap
1758+
///
1759+
/// # Examples
1760+
///
1761+
/// ```
1762+
/// # use http::{HttpTryFrom, Result, header::HeaderMap};
1763+
/// # use std::collections::HashMap;
1764+
/// let mut headers_hashmap: HashMap<String, String> = vec![
1765+
/// ("X-Custom-Header".to_string(), "my value".to_string()),
1766+
/// ].iter().cloned().collect();
1767+
///
1768+
/// let good_headers: Result<HeaderMap> = HeaderMap::try_from(&headers_hashmap);
1769+
/// assert!(good_headers.is_ok());
1770+
///
1771+
/// headers_hashmap.insert("\r".into(), "\0".into());
1772+
/// let bad_headers: Result<HeaderMap> = HeaderMap::try_from(&headers_hashmap);
1773+
/// assert!(bad_headers.is_err());
1774+
/// ```
1775+
impl<'a, K, V> HttpTryFrom<&'a HashMap<K, V>> for HeaderMap<HeaderValue>
1776+
where
1777+
K: Eq + Hash,
1778+
HeaderName: HttpTryFrom<&'a K>,
1779+
HeaderValue: HttpTryFrom<&'a V>
1780+
{
1781+
type Error = Error;
1782+
1783+
fn try_from(c: &'a HashMap<K, V>) -> Result<Self, Self::Error> {
1784+
c.into_iter()
1785+
.map(|(k, v)| -> crate::Result<(HeaderName, HeaderValue)> {
1786+
let name : HeaderName = k.http_try_into()?;
1787+
let value : HeaderValue = v.http_try_into()?;
1788+
Ok((name, value))
1789+
})
1790+
.collect()
1791+
}
1792+
}
1793+
17521794
impl<T> Extend<(Option<HeaderName>, T)> for HeaderMap<T> {
17531795
/// Extend a `HeaderMap` with the contents of another `HeaderMap`.
17541796
///
@@ -3209,7 +3251,7 @@ mod as_header_name {
32093251
use super::{Entry, HdrName, HeaderMap, HeaderName, InvalidHeaderName};
32103252

32113253
/// A marker trait used to identify values that can be used as search keys
3212-
/// to a `HeaderMap`.
3254+
/// to a `HeaderMap`.
32133255
pub trait AsHeaderName: Sealed {}
32143256

32153257
// All methods are on this pub(super) trait, instead of `AsHeaderName`,

src/header/name.rs

+8
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,14 @@ impl<'a> HttpTryFrom<&'a str> for HeaderName {
17761776
}
17771777
}
17781778

1779+
impl<'a> HttpTryFrom<&'a String> for HeaderName {
1780+
type Error = InvalidHeaderName;
1781+
#[inline]
1782+
fn try_from(s: &'a String) -> Result<Self, Self::Error> {
1783+
Self::from_bytes(s.as_bytes())
1784+
}
1785+
}
1786+
17791787
impl<'a> HttpTryFrom<&'a [u8]> for HeaderName {
17801788
type Error = InvalidHeaderName;
17811789
#[inline]

src/header/value.rs

+8
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,14 @@ impl<'a> HttpTryFrom<&'a str> for HeaderValue {
518518
}
519519
}
520520

521+
impl<'a> HttpTryFrom<&'a String> for HeaderValue {
522+
type Error = InvalidHeaderValue;
523+
#[inline]
524+
fn try_from(s: &'a String) -> Result<Self, Self::Error> {
525+
Self::from_bytes(s.as_bytes())
526+
}
527+
}
528+
521529
impl<'a> HttpTryFrom<&'a [u8]> for HeaderValue {
522530
type Error = InvalidHeaderValue;
523531

0 commit comments

Comments
 (0)