Skip to content

Commit

Permalink
refactor: remove internal from_shared functions
Browse files Browse the repository at this point in the history
  • Loading branch information
tesaguri committed Oct 26, 2024
1 parent 88b7b54 commit 835ca28
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 152 deletions.
6 changes: 1 addition & 5 deletions src/header/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,6 @@ impl HeaderValue {
HeaderValue::from_shared_unchecked(src)
}

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,
Expand Down Expand Up @@ -596,7 +592,7 @@ impl TryFrom<Bytes> for HeaderValue {

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

Expand Down
10 changes: 3 additions & 7 deletions src/uri/authority.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,6 @@ impl Authority {
}
}

fn from_shared(s: Bytes) -> Result<Self, InvalidUri> {
// Precondition on create_authority: trivially satisfied by the
// identity closure
create_authority(s, |s| s)
}

/// Attempt to convert an `Authority` from a static string.
///
/// This function will not perform any copying, and the string will be
Expand Down Expand Up @@ -282,7 +276,9 @@ impl TryFrom<Bytes> for Authority {
/// # }
/// ```
fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
Authority::from_shared(bytes)
// Precondition on create_authority: trivially satisfied by the
// identity closure
create_authority(bytes, |s| s)
}
}

Expand Down
98 changes: 47 additions & 51 deletions src/uri/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -286,56 +286,6 @@ impl Uri {
Uri::try_from(src.as_ref())
}

fn from_shared(s: Bytes) -> Result<Uri, InvalidUri> {
use self::ErrorKind::*;

if s.len() > MAX_LEN {
return Err(TooLong.into());
}

match s.len() {
0 => {
return Err(Empty.into());
}
1 => match s[0] {
b'/' => {
return Ok(Uri {
scheme: Scheme::empty(),
authority: Authority::empty(),
path_and_query: PathAndQuery::slash(),
});
}
b'*' => {
return Ok(Uri {
scheme: Scheme::empty(),
authority: Authority::empty(),
path_and_query: PathAndQuery::star(),
});
}
_ => {
let authority = Authority::try_from(s)?;

return Ok(Uri {
scheme: Scheme::empty(),
authority,
path_and_query: PathAndQuery::empty(),
});
}
},
_ => {}
}

if s[0] == b'/' {
return Ok(Uri {
scheme: Scheme::empty(),
authority: Authority::empty(),
path_and_query: PathAndQuery::try_from(s)?,
});
}

parse_full(s)
}

/// Convert a `Uri` from a static string.
///
/// This function will not perform any copying, however the string is
Expand Down Expand Up @@ -726,7 +676,53 @@ impl TryFrom<Bytes> for Uri {
/// # }
/// ```
fn try_from(t: Bytes) -> Result<Uri, Self::Error> {
Uri::from_shared(t)
use self::ErrorKind::*;

if t.len() > MAX_LEN {
return Err(TooLong.into());
}

match t.len() {
0 => {
return Err(Empty.into());
}
1 => match t[0] {
b'/' => {
return Ok(Uri {
scheme: Scheme::empty(),
authority: Authority::empty(),
path_and_query: PathAndQuery::slash(),
});
}
b'*' => {
return Ok(Uri {
scheme: Scheme::empty(),
authority: Authority::empty(),
path_and_query: PathAndQuery::star(),
});
}
_ => {
let authority = Authority::try_from(t)?;

return Ok(Uri {
scheme: Scheme::empty(),
authority,
path_and_query: PathAndQuery::empty(),
});
}
},
_ => {}
}

if t[0] == b'/' {
return Ok(Uri {
scheme: Scheme::empty(),
authority: Authority::empty(),
path_and_query: PathAndQuery::try_from(t)?,
});
}

parse_full(t)
}
}

Expand Down
174 changes: 85 additions & 89 deletions src/uri/path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,93 +17,6 @@ pub struct PathAndQuery {
const NONE: u16 = u16::MAX;

impl PathAndQuery {
fn from_shared(mut src: Bytes) -> Result<Self, InvalidUri> {
let mut query = NONE;
let mut fragment = None;

// block for iterator borrow
{
let mut iter = src.as_ref().iter().enumerate();

// path ...
for (i, &b) in &mut iter {
// See https://url.spec.whatwg.org/#path-state
match b {
b'?' => {
debug_assert_eq!(query, NONE);
query = i as u16;
break;
}
b'#' => {
fragment = Some(i);
break;
}

// This is the range of bytes that don't need to be
// percent-encoded in the path. If it should have been
// percent-encoded, then error.
#[rustfmt::skip]
0x21 |
0x24..=0x3B |
0x3D |
0x40..=0x5F |
0x61..=0x7A |
0x7C |
0x7E => {}

// These are code points that are supposed to be
// percent-encoded in the path but there are clients
// out there sending them as is and httparse accepts
// to parse those requests, so they are allowed here
// for parity.
//
// For reference, those are code points that are used
// to send requests with JSON directly embedded in
// the URI path. Yes, those things happen for real.
#[rustfmt::skip]
b'"' |
b'{' | b'}' => {}

_ => return Err(ErrorKind::InvalidUriChar.into()),
}
}

// query ...
if query != NONE {
for (i, &b) in iter {
match b {
// While queries *should* be percent-encoded, most
// bytes are actually allowed...
// See https://url.spec.whatwg.org/#query-state
//
// Allowed: 0x21 / 0x24 - 0x3B / 0x3D / 0x3F - 0x7E
#[rustfmt::skip]
0x21 |
0x24..=0x3B |
0x3D |
0x3F..=0x7E => {}

b'#' => {
fragment = Some(i);
break;
}

_ => return Err(ErrorKind::InvalidUriChar.into()),
}
}
}
}

if let Some(i) = fragment {
src.truncate(i);
}

Ok(PathAndQuery {
data: unsafe { ByteStr::from_utf8_unchecked(src) },
query,
})
}

/// Convert a `PathAndQuery` from a static string.
///
/// This function will not perform any copying, however the string is
Expand Down Expand Up @@ -278,8 +191,91 @@ impl PathAndQuery {
impl TryFrom<Bytes> for PathAndQuery {
type Error = InvalidUri;
#[inline]
fn try_from(bytes: Bytes) -> Result<Self, Self::Error> {
PathAndQuery::from_shared(bytes)
fn try_from(mut bytes: Bytes) -> Result<Self, Self::Error> {
let mut query = NONE;
let mut fragment = None;

// block for iterator borrow
{
let mut iter = bytes.as_ref().iter().enumerate();

// path ...
for (i, &b) in &mut iter {
// See https://url.spec.whatwg.org/#path-state
match b {
b'?' => {
debug_assert_eq!(query, NONE);
query = i as u16;
break;
}
b'#' => {
fragment = Some(i);
break;
}

// This is the range of bytes that don't need to be
// percent-encoded in the path. If it should have been
// percent-encoded, then error.
#[rustfmt::skip]
0x21 |
0x24..=0x3B |
0x3D |
0x40..=0x5F |
0x61..=0x7A |
0x7C |
0x7E => {}

// These are code points that are supposed to be
// percent-encoded in the path but there are clients
// out there sending them as is and httparse accepts
// to parse those requests, so they are allowed here
// for parity.
//
// For reference, those are code points that are used
// to send requests with JSON directly embedded in
// the URI path. Yes, those things happen for real.
#[rustfmt::skip]
b'"' |
b'{' | b'}' => {}

_ => return Err(ErrorKind::InvalidUriChar.into()),
}
}

// query ...
if query != NONE {
for (i, &b) in iter {
match b {
// While queries *should* be percent-encoded, most
// bytes are actually allowed...
// See https://url.spec.whatwg.org/#query-state
//
// Allowed: 0x21 / 0x24 - 0x3B / 0x3D / 0x3F - 0x7E
#[rustfmt::skip]
0x21 |
0x24..=0x3B |
0x3D |
0x3F..=0x7E => {}

b'#' => {
fragment = Some(i);
break;
}

_ => return Err(ErrorKind::InvalidUriChar.into()),
}
}
}
}

if let Some(i) = fragment {
bytes.truncate(i);
}

Ok(PathAndQuery {
data: unsafe { ByteStr::from_utf8_unchecked(bytes) },
query,
})
}
}

Expand Down

0 comments on commit 835ca28

Please sign in to comment.