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

WIP HeaderValue: make Cow<'static, str> #335

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions src/headers/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,27 @@ pub trait Header {
}
}

impl<'a, 'b> Header for (&'a str, &'b str) {
impl Header for (&'static str, &'static str) {
fn header_name(&self) -> HeaderName {
HeaderName::from(self.0)
if self.0.chars().all(|c| c.is_ascii_lowercase()) {
HeaderName::from_lowercase_str(self.0)
} else {
HeaderName::from(self.0)
}
}

fn header_value(&self) -> HeaderValue {
HeaderValue::from_bytes(self.1.to_owned().into_bytes())
.expect("String slice should be valid ASCII")
HeaderValue::from_static_str(self.1)
}
}

impl Header for (String, String) {
fn header_name(&self) -> HeaderName {
self.0.parse().expect("Header name should be valid ASCII")
}

fn header_value(&self) -> HeaderValue {
self.1.parse().expect("Header value should be valid ASCII")
}
}

Expand Down
27 changes: 18 additions & 9 deletions src/headers/header_value.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::convert::TryFrom;
use std::fmt::{self, Debug, Display};
use std::str::FromStr;
Expand All @@ -11,7 +12,7 @@ use crate::Mime;
/// A header value.
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct HeaderValue {
inner: String,
inner: Cow<'static, str>,
Copy link
Member

@jbr jbr Apr 7, 2021

Choose a reason for hiding this comment

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

why not pub struct HeaderValue<'a> { inner: Cow<'a, str> } and just use HeaderValue<'static> where we need it to be 'static?

Copy link
Member

Choose a reason for hiding this comment

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

@jbr That'd make the API a little more awkward to use, and would potentially be a backwards-compatibility issue.

}

impl HeaderValue {
Expand All @@ -25,7 +26,7 @@ impl HeaderValue {

// This is permitted because ASCII is valid UTF-8, and we just checked that.
let string = unsafe { String::from_utf8_unchecked(bytes) };
Ok(Self { inner: string })
Ok(Self { inner: string.into() })
}

/// Converts a vector of bytes to a `HeaderValue` without checking that the string contains
Expand All @@ -39,19 +40,27 @@ impl HeaderValue {
/// that Strings are valid ASCII.
pub unsafe fn from_bytes_unchecked(bytes: Vec<u8>) -> Self {
let string = String::from_utf8_unchecked(bytes);
Self { inner: string }
Self { inner: string.into() }
}

/// Get the header value as a `&str`
pub fn as_str(&self) -> &str {
&self.inner
}

/// Create a new `HeaderValue` from a static-lifetime string slice.
pub(crate) fn from_static_str(value: &'static str) -> Self {
assert!(value.is_ascii(), "Bytes should be valid ASCII");
Self {
inner: Cow::Borrowed(value),
}
}
}

impl From<Mime> for HeaderValue {
fn from(mime: Mime) -> Self {
HeaderValue {
inner: format!("{}", mime),
inner: format!("{}", mime).into(),
}
}
}
Expand All @@ -60,15 +69,15 @@ impl From<Mime> for HeaderValue {
impl From<Cookie<'_>> for HeaderValue {
fn from(cookie: Cookie<'_>) -> Self {
HeaderValue {
inner: cookie.to_string(),
inner: cookie.to_string().into(),
}
}
}

impl From<&Mime> for HeaderValue {
fn from(mime: &Mime) -> Self {
HeaderValue {
inner: format!("{}", mime),
inner: format!("{}", mime).into(),
}
}
}
Expand All @@ -82,7 +91,7 @@ impl FromStr for HeaderValue {
fn from_str(s: &str) -> Result<Self, Self::Err> {
crate::ensure!(s.is_ascii(), "String slice should be valid ASCII");
Ok(Self {
inner: String::from(s),
inner: s.to_owned().into(),
})
}
}
Expand Down Expand Up @@ -113,7 +122,7 @@ impl PartialEq<str> for HeaderValue {
}
}

impl<'a> PartialEq<&'a str> for HeaderValue {
impl<'a, 'v> PartialEq<&'a str> for HeaderValue {
fn eq(&self, other: &&'a str) -> bool {
&self.inner == other
}
Expand All @@ -125,7 +134,7 @@ impl PartialEq<String> for HeaderValue {
}
}

impl<'a> PartialEq<&String> for HeaderValue {
impl<'a, 'v> PartialEq<&String> for HeaderValue {
fn eq(&self, other: &&String) -> bool {
&&self.inner == other
}
Expand Down