Skip to content
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
6 changes: 3 additions & 3 deletions ohkami/src/request/_test_parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ use ohkami_lib::{Slice, CowSlice};
fn parse_path() {
let mut path = Path::uninit();
path.init_with_request_bytes(b"/abc").unwrap();
assert_eq!(&*path, "/abc");
assert_eq!(path.str(), "/abc");

let mut path = Path::uninit();
path.init_with_request_bytes(b"/abc/").unwrap();
assert_eq!(&*path, "/abc");
assert_eq!(path.str(), "/abc");

let mut path = Path::uninit();
path.init_with_request_bytes(b"/").unwrap();
assert_eq!(&*path, "/");
assert_eq!(path.str(), "/");
}

macro_rules! assert_parse {
Expand Down
21 changes: 10 additions & 11 deletions ohkami/src/request/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ macro_rules! Header {
let standard = Header::from_bytes(name.as_bytes())?;
unsafe {self.standard.get(standard as usize)}
})?;
Some(std::str::from_utf8(unsafe {value.as_bytes()}).expect("Header value is not UTF-8"))
std::str::from_utf8(unsafe {value.as_bytes()}).ok()
}
}

Expand Down Expand Up @@ -279,16 +279,15 @@ impl Headers {

pub(crate) fn iter(&self) -> impl Iterator<Item = (&str, &str)> {
self.standard.iter()
.map(|(i, v)| (
.filter_map(|(i, v)| Some((
unsafe {std::mem::transmute::<_, Header>(i as u8).as_str()},
std::str::from_utf8(v).expect("Non UTF-8 header value")
))
.chain(self.custom.as_ref()
.into_iter()
.flat_map(|hm| hm.iter().map(|(k, v)| (
std::str::from_utf8(unsafe {k.as_bytes()}).expect("Header value is not UTF-8"),
std::str::from_utf8(unsafe {v.as_bytes()}).expect("Header value is not UTF-8"),
)))
std::str::from_utf8(v).ok()?
)))
.chain(self.custom.as_ref().into_iter()
.flat_map(|hm| hm.iter().filter_map(|(k, v)| Some((
std::str::from_utf8(unsafe {k.as_bytes()}).ok()?,
std::str::from_utf8(unsafe {v.as_bytes()}).ok()?,
))))
)
.chain(self.cookie().map(|c| ("Cookie", c)))
}
Expand All @@ -309,7 +308,7 @@ impl Headers {

#[inline] pub(crate) fn get_standard(&self, name: Header) -> Option<&str> {
unsafe {match self.standard.get(name as usize) {
Some(cs) => Some(std::str::from_utf8(&cs).expect("non UTF-8 header value")),
Some(cs) => std::str::from_utf8(&cs).ok(),
None => None
}}
}
Expand Down
41 changes: 18 additions & 23 deletions ohkami/src/request/path.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::{borrow::Cow, mem::MaybeUninit};
use ohkami_lib::{percent_decode_utf8, Slice};


pub struct Path(
MaybeUninit<PathInner>
);
Expand Down Expand Up @@ -30,48 +29,44 @@ const _: () = {

impl Path {
pub fn params(&self) -> impl Iterator<Item = Cow<'_, str>> {
unsafe {self.0.assume_init_ref()}
.params.iter()
(unsafe {self.0.assume_init_ref()})
.params
.iter()
.map(|slice| percent_decode_utf8(unsafe {slice.as_bytes()})
.expect("Non UTF-8 path params"))
.unwrap_or_else(|_| String::from_utf8_lossy(unsafe {slice.as_bytes()}))
)
}

#[inline]
pub fn as_bytes(&self) -> &[u8] {
let bytes = unsafe {self.0.assume_init_ref().raw.as_bytes()};
if bytes.is_empty() {b"/"} else {bytes}
}
/// Get request path as `Cow::Borrowed(&str)` if it's not percent-encoded, or,
/// decode it into `Cow::Owned(String)` if encoded in the original request.
///
/// Or if the path is not valid UTF-8, it returns `Cow::Owned(String)` with
/// lossy conversion.
#[inline]
pub fn str(&self) -> Cow<'_, str> {
let bytes = unsafe {self.0.assume_init_ref().raw.as_bytes()};
if bytes.is_empty() {return Cow::Borrowed("/")}
percent_decode_utf8(bytes).expect("Non UTF-8 path params")
percent_decode_utf8(bytes).unwrap_or_else(|_| String::from_utf8_lossy(bytes))
}

#[inline] pub(crate) unsafe fn assume_one_param<'p>(&self) -> &'p [u8] {
#[inline]
pub(crate) unsafe fn assume_one_param<'p>(&self) -> &'p [u8] {
unsafe {self.0.assume_init_ref().params.list.get_unchecked(0).assume_init_ref().as_bytes()}
}
#[inline] pub(crate) unsafe fn assume_two_params<'p>(&self) -> (&'p [u8], &'p [u8]) {
#[inline]
pub(crate) unsafe fn assume_two_params<'p>(&self) -> (&'p [u8], &'p [u8]) {
unsafe {(
self.0.assume_init_ref().params.list.get_unchecked(0).assume_init_ref().as_bytes(),
self.0.assume_init_ref().params.list.get_unchecked(1).assume_init_ref().as_bytes()
)}
}
}

impl std::ops::Deref for Path {
type Target = str;
#[inline]
fn deref(&self) -> &Self::Target {
self.as_ref()
}
}
impl AsRef<str> for Path {
#[inline]
fn as_ref(&self) -> &str {
let bytes = &unsafe {self.0.assume_init_ref().raw.as_bytes()};
if bytes.is_empty() {return "/"}
std::str::from_utf8(bytes).expect("Non UTF-8 path params")
}
}

impl std::fmt::Debug for Path {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
<Cow<str> as std::fmt::Debug>::fmt(&self.str(), f)
Expand Down
20 changes: 4 additions & 16 deletions ohkami/src/request/query.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
use std::borrow::Cow;
use ohkami_lib::percent_decode;
use super::Slice;

use ohkami_lib::{percent_decode_utf8, Slice};

#[derive(PartialEq)]
pub struct QueryParams(
Expand All @@ -23,17 +21,7 @@ impl QueryParams {
ohkami_lib::serde_urlencoded::from_bytes(unsafe {self.0.as_bytes()})
}

pub fn iter(&self) -> impl Iterator<
Item = (Cow<'_, str>, Cow<'_, str>)
> {
#[inline(always)]
fn decoded_utf8(maybe_encoded: &[u8]) -> Cow<'_, str> {
match percent_decode(maybe_encoded) {
Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
Cow::Owned(vec) => String::from_utf8_lossy(&vec).into_owned().into(),
}
}

pub fn iter(&self) -> impl Iterator<Item = (Cow<'_, str>, Cow<'_, str>)> {
let bytes = unsafe {self.0.as_bytes()};
(if bytes.is_empty() {None} else {Some(
bytes
Expand All @@ -57,8 +45,8 @@ impl QueryParams {
None
}
Some(n) => Some((
decoded_utf8(unsafe {kv.get_unchecked(..n)}),
decoded_utf8(unsafe {kv.get_unchecked(n+1..)})
percent_decode_utf8(unsafe {kv.get_unchecked(..n)}).ok()?,
percent_decode_utf8(unsafe {kv.get_unchecked(n+1..)}).ok()?
))
}
})
Expand Down