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

Remove Bytes from the public API #369

Merged
merged 3 commits into from
Dec 2, 2019
Merged
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
8 changes: 4 additions & 4 deletions benches/header_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn from_shared_short(b: &mut Bencher) {
b.bytes = SHORT.len() as u64;
let bytes = Bytes::from_static(SHORT);
b.iter(|| {
HeaderValue::from_shared(bytes.clone()).unwrap();
HeaderValue::from_maybe_shared(bytes.clone()).unwrap();
});
}

Expand All @@ -23,7 +23,7 @@ fn from_shared_long(b: &mut Bencher) {
b.bytes = LONG.len() as u64;
let bytes = Bytes::from_static(LONG);
b.iter(|| {
HeaderValue::from_shared(bytes.clone()).unwrap();
HeaderValue::from_maybe_shared(bytes.clone()).unwrap();
});
}

Expand All @@ -32,7 +32,7 @@ fn from_shared_unchecked_short(b: &mut Bencher) {
b.bytes = SHORT.len() as u64;
let bytes = Bytes::from_static(SHORT);
b.iter(|| unsafe {
HeaderValue::from_shared_unchecked(bytes.clone());
HeaderValue::from_maybe_shared_unchecked(bytes.clone());
});
}

Expand All @@ -41,6 +41,6 @@ fn from_shared_unchecked_long(b: &mut Bencher) {
b.bytes = LONG.len() as u64;
let bytes = Bytes::from_static(LONG);
b.iter(|| unsafe {
HeaderValue::from_shared_unchecked(bytes.clone());
HeaderValue::from_maybe_shared_unchecked(bytes.clone());
});
}
17 changes: 17 additions & 0 deletions src/convert.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
macro_rules! if_downcast_into {
($in_ty:ty, $out_ty:ty, $val:ident, $body:expr) => ({
if std::any::TypeId::of::<$in_ty>() == std::any::TypeId::of::<$out_ty>() {
// Store the value in an `Option` so we can `take`
// it after casting to `&mut dyn Any`.
let mut slot = Some($val);
// Re-write the `$val` ident with the downcasted value.
let $val = (&mut slot as &mut dyn std::any::Any)
.downcast_mut::<Option<$out_ty>>()
.unwrap()
.take()
.unwrap();
// Run the $body in scope of the replaced val.
$body
}
})
}
33 changes: 0 additions & 33 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ enum ErrorKind {
StatusCode(status::InvalidStatusCode),
Method(method::InvalidMethod),
Uri(uri::InvalidUri),
UriShared(uri::InvalidUriBytes),
UriParts(uri::InvalidUriParts),
HeaderName(header::InvalidHeaderName),
HeaderNameShared(header::InvalidHeaderNameBytes),
HeaderValue(header::InvalidHeaderValue),
HeaderValueShared(header::InvalidHeaderValueBytes),
}

impl fmt::Debug for Error {
Expand Down Expand Up @@ -61,12 +58,9 @@ impl Error {
StatusCode(ref e) => e,
Method(ref e) => e,
Uri(ref e) => e,
UriShared(ref e) => e,
UriParts(ref e) => e,
HeaderName(ref e) => e,
HeaderNameShared(ref e) => e,
HeaderValue(ref e) => e,
HeaderValueShared(ref e) => e,
}
}
}
Expand All @@ -79,12 +73,9 @@ impl error::Error for Error {
StatusCode(ref e) => e.description(),
Method(ref e) => e.description(),
Uri(ref e) => e.description(),
UriShared(ref e) => e.description(),
UriParts(ref e) => e.description(),
HeaderName(ref e) => e.description(),
HeaderNameShared(ref e) => e.description(),
HeaderValue(ref e) => e.description(),
HeaderValueShared(ref e) => e.description(),
}
}

Expand Down Expand Up @@ -119,14 +110,6 @@ impl From<uri::InvalidUri> for Error {
}
}

impl From<uri::InvalidUriBytes> for Error {
fn from(err: uri::InvalidUriBytes) -> Error {
Error {
inner: ErrorKind::UriShared(err),
}
}
}

impl From<uri::InvalidUriParts> for Error {
fn from(err: uri::InvalidUriParts) -> Error {
Error {
Expand All @@ -143,14 +126,6 @@ impl From<header::InvalidHeaderName> for Error {
}
}

impl From<header::InvalidHeaderNameBytes> for Error {
fn from(err: header::InvalidHeaderNameBytes) -> Error {
Error {
inner: ErrorKind::HeaderNameShared(err),
}
}
}

impl From<header::InvalidHeaderValue> for Error {
fn from(err: header::InvalidHeaderValue) -> Error {
Error {
Expand All @@ -159,14 +134,6 @@ impl From<header::InvalidHeaderValue> for Error {
}
}

impl From<header::InvalidHeaderValueBytes> for Error {
fn from(err: header::InvalidHeaderValueBytes) -> Error {
Error {
inner: ErrorKind::HeaderValueShared(err),
}
}
}

impl From<std::convert::Infallible> for Error {
fn from(err: std::convert::Infallible) -> Error {
match err {}
Expand Down
4 changes: 2 additions & 2 deletions src/header/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,8 @@ pub use self::map::{
AsHeaderName, Drain, Entry, GetAll, HeaderMap, IntoHeaderName, IntoIter, Iter, IterMut, Keys,
OccupiedEntry, VacantEntry, ValueDrain, ValueIter, ValueIterMut, Values, ValuesMut,
};
pub use self::name::{HeaderName, InvalidHeaderName, InvalidHeaderNameBytes};
pub use self::value::{HeaderValue, InvalidHeaderValue, InvalidHeaderValueBytes, ToStrError};
pub use self::name::{HeaderName, InvalidHeaderName};
pub use self::value::{HeaderValue, InvalidHeaderValue, ToStrError};

// Use header name constants
pub use self::name::{
Expand Down
39 changes: 6 additions & 33 deletions src/header/name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ pub struct InvalidHeaderName {
_priv: (),
}

/// A possible error when converting a `HeaderName` from another type.
#[derive(Debug)]
pub struct InvalidHeaderNameBytes(InvalidHeaderName);

macro_rules! standard_headers {
(
$(
Expand Down Expand Up @@ -122,14 +118,14 @@ macro_rules! standard_headers {
// Test lower case
let name_bytes = name.as_bytes();
let bytes: Bytes =
HeaderName::from_bytes(name_bytes).unwrap().into();
HeaderName::from_bytes(name_bytes).unwrap().inner.into();
assert_eq!(bytes, name_bytes);
assert_eq!(HeaderName::from_bytes(name_bytes).unwrap(), std);

// Test upper case
let upper = name.to_uppercase().to_string();
let bytes: Bytes =
HeaderName::from_bytes(upper.as_bytes()).unwrap().into();
HeaderName::from_bytes(upper.as_bytes()).unwrap().inner.into();
assert_eq!(bytes, name.as_bytes());
assert_eq!(HeaderName::from_bytes(upper.as_bytes()).unwrap(),
std);
Expand Down Expand Up @@ -1809,6 +1805,10 @@ impl HeaderName {
Repr::Custom(ref v) => &*v.0,
}
}

pub(super) fn into_bytes(self) -> Bytes {
self.inner.into()
}
}

impl FromStr for HeaderName {
Expand Down Expand Up @@ -1881,13 +1881,6 @@ impl From<Custom> for Bytes {
}
}

impl From<HeaderName> for Bytes {
#[inline]
fn from(name: HeaderName) -> Bytes {
name.inner.into()
}
}

impl<'a> TryFrom<&'a str> for HeaderName {
type Error = InvalidHeaderName;
#[inline]
Expand All @@ -1912,14 +1905,6 @@ impl<'a> TryFrom<&'a [u8]> for HeaderName {
}
}

impl TryFrom<Bytes> for HeaderName {
type Error = InvalidHeaderNameBytes;
#[inline]
fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
Self::from_bytes(bytes.as_ref()).map_err(InvalidHeaderNameBytes)
}
}

#[doc(hidden)]
impl From<StandardHeader> for HeaderName {
fn from(src: StandardHeader) -> HeaderName {
Expand Down Expand Up @@ -2028,18 +2013,6 @@ impl Error for InvalidHeaderName {
}
}

impl fmt::Display for InvalidHeaderNameBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

impl Error for InvalidHeaderNameBytes {
fn description(&self) -> &str {
self.0.description()
}
}

// ===== HdrName =====

impl<'a> HdrName<'a> {
Expand Down
84 changes: 33 additions & 51 deletions src/header/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,6 @@ pub struct InvalidHeaderValue {
_priv: (),
}

/// A possible error when converting a `HeaderValue` from a string or byte
/// slice.
#[derive(Debug)]
pub struct InvalidHeaderValueBytes(InvalidHeaderValue);

/// A possible error when converting a `HeaderValue` to a string representation.
///
/// Header field values may contain opaque bytes, in which case it is not
Expand Down Expand Up @@ -154,40 +149,55 @@ impl HeaderValue {

/// Attempt to convert a `Bytes` buffer to a `HeaderValue`.
///
/// If the argument contains invalid header value bytes, an error is
/// returned. Only byte values between 32 and 255 (inclusive) are permitted,
/// excluding byte 127 (DEL).
///
/// This function is intended to be replaced in the future by a `TryFrom`
/// implementation once the trait is stabilized in std.
#[inline]
pub fn from_shared(src: Bytes) -> Result<HeaderValue, InvalidHeaderValueBytes> {
HeaderValue::try_from_generic(src, std::convert::identity).map_err(InvalidHeaderValueBytes)
/// This will try to prevent a copy if the type passed is the type used
/// internally, and will copy the data if it is not.
pub fn from_maybe_shared<T>(src: T) -> Result<HeaderValue, InvalidHeaderValue>
where
T: AsRef<[u8]> + 'static,
{
if_downcast_into!(T, Bytes, src, {
return HeaderValue::from_shared(src);
});

HeaderValue::from_bytes(src.as_ref())
}

/// Convert a `Bytes` directly into a `HeaderValue` without validating.
///
/// This function does NOT validate that illegal bytes are not contained
/// within the buffer.
#[inline]
pub unsafe fn from_shared_unchecked(src: Bytes) -> HeaderValue {
pub unsafe fn from_maybe_shared_unchecked<T>(src: T) -> HeaderValue
where
T: AsRef<[u8]> + 'static,
{
if cfg!(debug_assertions) {
match HeaderValue::from_shared(src) {
match HeaderValue::from_maybe_shared(src) {
Ok(val) => val,
Err(_err) => {
//TODO: if the Bytes were part of the InvalidHeaderValueBytes,
//this message could include the invalid bytes.
panic!("HeaderValue::from_shared_unchecked() with invalid bytes");
panic!("HeaderValue::from_maybe_shared_unchecked() with invalid bytes");
}
}
} else {

if_downcast_into!(T, Bytes, src, {
return HeaderValue {
inner: src,
is_sensitive: false,
};
});

let src = Bytes::copy_from_slice(src.as_ref());
HeaderValue {
inner: src,
is_sensitive: false,
}
}
}

fn from_shared(src: Bytes) -> Result<HeaderValue, InvalidHeaderValue> {
HeaderValue::try_from_generic(src, std::convert::identity)
}

fn try_from_generic<T: AsRef<[u8]>, F: FnOnce(T) -> Bytes>(src: T, into: F) -> Result<HeaderValue, InvalidHeaderValue> {
for &b in src.as_ref() {
if !is_valid(b) {
Expand Down Expand Up @@ -357,7 +367,7 @@ impl From<HeaderName> for HeaderValue {
#[inline]
fn from(h: HeaderName) -> HeaderValue {
HeaderValue {
inner: h.into(),
inner: h.into_bytes(),
is_sensitive: false,
}
}
Expand Down Expand Up @@ -475,13 +485,6 @@ impl FromStr for HeaderValue {
}
}

impl From<HeaderValue> for Bytes {
#[inline]
fn from(value: HeaderValue) -> Bytes {
value.inner
}
}

impl<'a> From<&'a HeaderValue> for HeaderValue {
#[inline]
fn from(t: &'a HeaderValue) -> Self {
Expand Down Expand Up @@ -516,7 +519,7 @@ impl<'a> TryFrom<&'a [u8]> for HeaderValue {
}

impl TryFrom<String> for HeaderValue {
type Error = InvalidHeaderValueBytes;
type Error = InvalidHeaderValue;

#[inline]
fn try_from(t: String) -> Result<Self, Self::Error> {
Expand All @@ -525,23 +528,14 @@ impl TryFrom<String> for HeaderValue {
}

impl TryFrom<Vec<u8>> for HeaderValue {
type Error = InvalidHeaderValueBytes;
type Error = InvalidHeaderValue;

#[inline]
fn try_from(vec: Vec<u8>) -> Result<Self, Self::Error> {
HeaderValue::from_shared(vec.into())
}
}

impl TryFrom<Bytes> for HeaderValue {
type Error = InvalidHeaderValueBytes;

#[inline]
fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
HeaderValue::from_shared(bytes)
}
}

#[cfg(test)]
mod try_from_header_name_tests {
use super::*;
Expand Down Expand Up @@ -585,18 +579,6 @@ impl Error for InvalidHeaderValue {
}
}

impl fmt::Display for InvalidHeaderValueBytes {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}

impl Error for InvalidHeaderValueBytes {
fn description(&self) -> &str {
self.0.description()
}
}

impl fmt::Display for ToStrError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.description().fmt(f)
Expand Down
Loading