Skip to content
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

feat: Add TryFrom implementations for MetadataValue #990

Merged
merged 2 commits into from May 2, 2022

Conversation

adamchalmers
Copy link
Contributor

@adamchalmers adamchalmers commented Apr 29, 2022

Motivation

As described in the issue there are several adhoc methods that say "This function is intended to be replaced in the future by a TryFrom implementation once the trait is stabilized in std." Well, TryFrom is stable in std now, so let's use it :)

Solution

I looked at which TryFrom impls http::HeaderValue has, and copied those where it made sense. Seems like MetadataValue is mostly a copy of http::HeaderValue, so I thought it was a good guide.

I tried to avoid repeating code, so often various TryFrom implementations either call into each other, or into the underlying http::HeaderValue TryFrom implementations. I kept the #[inline] attribute when the original call had it, and added a deprecation warning to the original adhoc methods.

Apparently MetadataValue already implements From for all numeric types >= 16 bits. They just don't show up in rustdoc, which is surprising, but I didn't dive in to figure out why. So I only implemented TryFrom around different string and byte representations.

@adamchalmers
Copy link
Contributor Author

As requested, tagging @LucioFranco for a review.

@adamchalmers adamchalmers changed the title Impl TryFrom (from byte slices and byte arrays) for MetadataValue Add TryFrom implementations for MetadataValue Apr 29, 2022
@@ -9,7 +9,7 @@ use tonic::{metadata::MetadataValue, transport::Channel, Request};
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let channel = Channel::from_static("http://[::1]:50051").connect().await?;

let token = MetadataValue::from_str("Bearer some-auth-token")?;
let token: MetadataValue<_> = "Bearer some-auth-token".parse()?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm I actually kinda prefer the look of from_str vs using parse. I wonder if we should not deprecate it and keep it. But just have the TryFrom's use it or the other way around?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm. So, MetadataValue impls FromStr, so it will already have a from_str method from stdlib, which is equivalent to parse. Unfortunately it's not in the stdlib prelude, so if I delete the ad-hoc from_str method then old code will fail to compile (although the compiler will suggest the easy fix of "use std::str::FromStr").

It does kinda annoy me to have an adhoc method named from_str when the stdlib one exists too, just because it seems to make the API a bit larger than it needs to be. But this is a very minor gripe :) So overall I'm happy with the solution of not deprecating from_str if that's what you'd like.

(I'm pretty used to parse() because it's used very often in the stdlib IP types).

So yeah, happy to do whichever, just let me know what you think now that you've ready this silly long reply :)

/// let val = AsciiMetadataValue::try_from_bytes(b"\n");
/// assert!(val.is_err());
/// ```
impl<'a, VE: ValueEncoding> TryFrom<&'a [u8]> for MetadataValue<VE> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this lifetime be elided?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be, but then Rustdoc generates docs with a signature like TryFrom<&'0 str>. If I name the lifetime, then it outputs the signature TryFrom<&'a str> which I think is more readable, more what Rust programmers are used to seeing.

I copied this style of doing it from the hyper docs -- happy to change it to the elided lifetime if you prefer, but I thought matching Hyper's docs is a good tiebreaker when I wasn't sure which was better.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh cool didn't know that, seems fine to me!

tonic/src/metadata/value.rs Outdated Show resolved Hide resolved
@LucioFranco LucioFranco changed the title Add TryFrom implementations for MetadataValue feat: Add TryFrom implementations for MetadataValue May 2, 2022
@LucioFranco LucioFranco merged commit edc5a0d into hyperium:master May 2, 2022
@LucioFranco
Copy link
Member

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants