From f15729646c65ccd8abe161038b02aeeaa04bc6c9 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 4 Dec 2023 16:56:56 -0600 Subject: [PATCH 1/5] refactor(stream): Remove redundant code --- src/stream/mod.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/stream/mod.rs b/src/stream/mod.rs index cddd2913..fb43dc17 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -1739,21 +1739,7 @@ impl<'a, 'b> Compare<&'b str> for &'a str { impl<'a, 'b> Compare> for &'a str { #[inline(always)] fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult { - let pos = self - .chars() - .zip(t.0.chars()) - .position(|(a, b)| a.to_lowercase().ne(b.to_lowercase())); - - match pos { - Some(_) => CompareResult::Error, - None => { - if self.len() >= t.0.len() { - CompareResult::Ok - } else { - CompareResult::Incomplete - } - } - } + self.as_bytes().compare(AsciiCaseless(t.0.as_bytes())) } #[inline(always)] From 80cfe8c24bc2304a01435c49ef0389d558478b0e Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 4 Dec 2023 16:59:01 -0600 Subject: [PATCH 2/5] feat(ascii): Add Caseless::as_bytes --- src/ascii/mod.rs | 8 ++++++++ src/stream/mod.rs | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/ascii/mod.rs b/src/ascii/mod.rs index a026b1bc..6221efc2 100644 --- a/src/ascii/mod.rs +++ b/src/ascii/mod.rs @@ -42,6 +42,14 @@ use crate::Parser; #[derive(Copy, Clone, Debug)] pub struct Caseless(pub T); +impl Caseless<&str> { + /// Get the byte-representation of this case-insensitive value + #[inline(always)] + pub fn as_bytes(&self) -> Caseless<&[u8]> { + Caseless(self.0.as_bytes()) + } +} + /// Recognizes the string `"\r\n"`. /// /// *Complete version*: Will return an error if there's not enough input data. diff --git a/src/stream/mod.rs b/src/stream/mod.rs index fb43dc17..5bb7ceec 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -1739,7 +1739,7 @@ impl<'a, 'b> Compare<&'b str> for &'a str { impl<'a, 'b> Compare> for &'a str { #[inline(always)] fn compare(&self, t: AsciiCaseless<&'b str>) -> CompareResult { - self.as_bytes().compare(AsciiCaseless(t.0.as_bytes())) + self.as_bytes().compare(t.as_bytes()) } #[inline(always)] From 45236a479f3bc2262ec1c844defb027285c5c687 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 4 Dec 2023 17:02:01 -0600 Subject: [PATCH 3/5] refactor(ascii): Reuse std's caseless logic --- src/stream/mod.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 5bb7ceec..5d103272 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -1593,13 +1593,6 @@ pub trait Compare { fn compare_no_case(&self, t: T) -> CompareResult; } -fn lowercase_byte(c: u8) -> u8 { - match c { - b'A'..=b'Z' => c - b'A' + b'a', - _ => c, - } -} - impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { #[inline] fn compare(&self, t: &'b [u8]) -> CompareResult { @@ -1630,7 +1623,7 @@ impl<'a, 'b> Compare> for &'a [u8] { if self .iter() .zip(t.0) - .any(|(a, b)| lowercase_byte(*a) != lowercase_byte(*b)) + .any(|(a, b)| !a.eq_ignore_ascii_case(b)) { CompareResult::Error } else if self.len() < t.0.len() { From 43d101fe51e2441f0e77abf7cfffe4466228784a Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 4 Dec 2023 20:28:01 -0600 Subject: [PATCH 4/5] refactor(token): Align cased/caseless compare logic --- src/stream/mod.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 5d103272..1eb3db64 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -1596,17 +1596,12 @@ pub trait Compare { impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { #[inline] fn compare(&self, t: &'b [u8]) -> CompareResult { - let pos = self.iter().zip(t.iter()).position(|(a, b)| a != b); - - match pos { - Some(_) => CompareResult::Error, - None => { - if self.len() >= t.len() { - CompareResult::Ok - } else { - CompareResult::Incomplete - } - } + if self.iter().zip(t).any(|(a, b)| a != b) { + CompareResult::Error + } else if self.len() < t.slice_len() { + CompareResult::Incomplete + } else { + CompareResult::Ok } } @@ -1626,7 +1621,7 @@ impl<'a, 'b> Compare> for &'a [u8] { .any(|(a, b)| !a.eq_ignore_ascii_case(b)) { CompareResult::Error - } else if self.len() < t.0.len() { + } else if self.len() < t.slice_len() { CompareResult::Incomplete } else { CompareResult::Ok From 9c76be51962e9a24a691a2153631e0eba3a6764b Mon Sep 17 00:00:00 2001 From: Ed Page Date: Mon, 4 Dec 2023 20:39:53 -0600 Subject: [PATCH 5/5] refactor(token): Make tag trait clearer its a prefix check --- src/stream/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stream/mod.rs b/src/stream/mod.rs index 1eb3db64..c5d38a2b 100644 --- a/src/stream/mod.rs +++ b/src/stream/mod.rs @@ -1596,7 +1596,7 @@ pub trait Compare { impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { #[inline] fn compare(&self, t: &'b [u8]) -> CompareResult { - if self.iter().zip(t).any(|(a, b)| a != b) { + if t.iter().zip(*self).any(|(a, b)| a != b) { CompareResult::Error } else if self.len() < t.slice_len() { CompareResult::Incomplete @@ -1615,9 +1615,9 @@ impl<'a, 'b> Compare<&'b [u8]> for &'a [u8] { impl<'a, 'b> Compare> for &'a [u8] { #[inline] fn compare(&self, t: AsciiCaseless<&'b [u8]>) -> CompareResult { - if self + if t.0 .iter() - .zip(t.0) + .zip(*self) .any(|(a, b)| !a.eq_ignore_ascii_case(b)) { CompareResult::Error