diff --git a/src/path.rs b/src/path.rs index 5dcb52df..5980be6e 100644 --- a/src/path.rs +++ b/src/path.rs @@ -1,19 +1,30 @@ use crate::{decode::percent_decode, errors::decode::DecodeError}; +use std::borrow::Cow; -pub struct Path { - pub inner: Vec, +pub struct Path<'a> { + original: Cow<'a, [u8]>, + decoded: Option>, } -impl Path { +impl<'a> Path<'a> { #[must_use] - pub fn new(path: &str) -> Self { + pub const fn new(path: &'a str) -> Self { Self { - inner: path.as_bytes().to_vec(), + original: Cow::Borrowed(path.as_bytes()), + decoded: None, } } pub fn percent_decode(&mut self) -> Result<(), DecodeError> { - self.inner = percent_decode(&self.inner)?; + if self.decoded.is_none() { + self.decoded = Some(percent_decode(&self.original)?); + } + Ok(()) } + + #[must_use] + pub fn as_bytes(&self) -> &[u8] { + self.decoded.as_deref().unwrap_or(&self.original) + } } diff --git a/src/router.rs b/src/router.rs index 4b737574..881c7bc5 100644 --- a/src/router.rs +++ b/src/router.rs @@ -131,10 +131,6 @@ impl Router { self.root.delete(&mut parts) } - // FIXME: Let's try a 'Path' style approach to the returned value. - // Like what actix/ntex does. - // Maybe instead of returning anything, we just set something everything in Path? - // i.e. merge Match with Path? pub fn search<'k, 'v>( &'k self, path: &'v mut Path, @@ -146,7 +142,7 @@ impl Router { let mut parameters = smallvec![]; let Some(node) = self .root - .search(&path.inner, &mut parameters, &self.constraints) + .search(path.as_bytes(), &mut parameters, &self.constraints) else { return Ok(None); }; diff --git a/tests/poem.rs b/tests/poem.rs index c9d0d3ea..ae0820d4 100644 --- a/tests/poem.rs +++ b/tests/poem.rs @@ -512,7 +512,7 @@ fn test_percent_decoded() -> Result<(), Box> { "id" => "abc" } } - "/a/你好" => { + "/a/%E4%BD%A0%E5%A5%BD" => { path: "/a/{id}", value: 1, params: {