-
Notifications
You must be signed in to change notification settings - Fork 318
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
Conversation
This allows an easy conversion from HashMap<String,String> to HeaderMap<HeaderValue>. Doing this conversion used to be unnecessarily verbose because of the required mapping and error type conversions. The implementation is generic: impl<COLLECTION, K, V> HttpTryFrom<COLLECTION> for HeaderMap<HeaderValue> where COLLECTION: IntoIterator<Item=(K, V)>, K: AsRef<str>, V: AsRef<str> so it also works for HashMap<HeaderName, String> and for vectors. Fixes hyperium#325
The broken CI is not due to the changes introduced in this PR, but to #327. |
Hm, what if instead of K and V being |
👍 on the idea. |
@seanmonstar OK, but I will have to add some |
@seanmonstar : I made the change you suggested. It required adding an impl HttpTryFrom<&String> for HeaderName and HeaderValue. |
@seanmonstar Is it ok like that, or is there still something you would like me to change ? |
Any news? |
src/header/map.rs
Outdated
@@ -1720,6 +1724,45 @@ impl<T> FromIterator<(HeaderName, T)> for HeaderMap<T> | |||
} | |||
} | |||
|
|||
impl<T> Sealed for HeaderMap<T> {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There should probably be an identity impl, impl<T> HttpTryFrom<HeaderMap<T>> for HeaderMap<T>
. Would that conflict with the generic one below?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, HeaderMap<T>
is itself IntoIterator<Item=(HttpTryFrom<HeaderName>, HttpTryFrom<HeaderValue>)>
, so HeaderMap::try_from(header_map)
works as expected.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Usually one would expect TryFrom<Me> for Me
to be basically free, but because that conflicts, it would be surprising that it essentially clones a new HeaderMap
....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is indeed sub-optimal, and can fixed later when rust adds support for specialization.
But until then, I think the usability benefits far outweigh this downside. The standard library itself has the same issue in several places, where an implementation is slower than it could be in order to be more generic.
@seanmonstar I implemented your the changes you suggested. Hope this can be merged soon. |
It's worth noting that the current conversion can be done fairly ergonomically already: let mut map = HashMap::new();
map.insert("hello", "world");
map.insert("and", "good day");
let headers = map
.into_iter()
.map(|(name, value)| {
Ok((
name.parse()?,
value.parse()?,
))
})
.collect::<Result<HeaderMap, http::Error>>(); |
@seanmonstar The main advantage of implementing HttpTryFrom is not only to remove all these lines of boilerplate, but also to allow libraries to provide functions that accept a trait instead of having the users manually converting to custom types all the time. Also, shouldn't it have been discussed earlier ? |
True, I'm very sorry I didn't realize how to make the original request shorter. I didn't think there would be a conflict with a generic I recognize what the goal is, I'm just pointing out what exists already. I believe that the identity implementation isn't "free" would be surprising to everyone. |
@seanmonstar I answered above. I see what you mean, but I don't think this should block merging this. Do you ? |
I prefer the generic option, but if you think the slight HeaderMap to HeaderMap conversion overhead is a real problem people would encounter, we can switch to having a separate implementation for a few standard library containers (maybe only Vec and HashMap), and that wouldn't conflict with |
A reason I think it'd be surprising is, for example, if some For the completely generic situation, I think the code I pasted a few comments ago is ok. If wanting to add |
|
@seanmonstar I added a marker trait to limit the generic implementation to just a few standard library types, so that the generic implementation does not apply to |
I appreciate the goal, but I think there's value in staying conservative, because we can't really make breaking changes, since We could start with just |
@seamonstar I removed the implementation for non-HashMap types. I hope this can be merged now. |
@lovasoa Thank you! I see this is targeting master, but I assume you want to use this before 0.2 releases? If so, if you can change the target to Would you be able to remove the marker trait for now, since we'll only have the |
Ok, I'll change the target of the PR. I think the marker trait is still needed to implement the conversion from both HashMap and &HashMap. Or is there another way? |
Woops, I'm so sorry, I got confused. Most of the other repos I'm working in have converted master to the newer version, but this one still has master as 0.1. I'll merge this in first, and then update to be more consistent. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much!
Er, it seems there was no |
@seanmonstar I fixed rust 1.20 compatibility. I think this is ready for merging. |
This allows an easy conversion from HashMap<String,String>
to HeaderMap.
Doing this conversion used to be unnecessarily verbose
because of the required mapping and error type conversions.
The implementation is generic:
so it also works for HashMap<HeaderName, String> and for vectors.
Fixes #325