diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml index a83b2c3aa5..1037a501d2 100644 --- a/core/http/Cargo.toml +++ b/core/http/Cargo.toml @@ -21,7 +21,7 @@ private-cookies = ["cookie/secure"] [dependencies] smallvec = "1.0" -percent-encoding = "1" +percent-encoding = "2" hyper = { version = "0.13.0", default-features = false } http = "0.2" mime = "0.3.13" diff --git a/core/http/src/lib.rs b/core/http/src/lib.rs index fe951fa40f..c28379ffa1 100644 --- a/core/http/src/lib.rs +++ b/core/http/src/lib.rs @@ -1,3 +1,5 @@ +#![feature(const_if_match)] +#![feature(const_loop)] #![feature(proc_macro_hygiene)] #![recursion_limit="512"] diff --git a/core/http/src/parse/uri/tables.rs b/core/http/src/parse/uri/tables.rs index 7258e9e4a7..ad78cf6541 100644 --- a/core/http/src/parse/uri/tables.rs +++ b/core/http/src/parse/uri/tables.rs @@ -30,7 +30,7 @@ const PATH_CHARS: [u8; 256] = [ ]; #[inline(always)] -pub fn is_pchar(c: u8) -> bool { +pub const fn is_pchar(c: u8) -> bool { PATH_CHARS[c as usize] == c } diff --git a/core/http/src/uri/encoding.rs b/core/http/src/uri/encoding.rs index 3b989eb6c7..625afdd069 100644 --- a/core/http/src/uri/encoding.rs +++ b/core/http/src/uri/encoding.rs @@ -1,7 +1,7 @@ use std::marker::PhantomData; use std::borrow::Cow; -use percent_encoding::{EncodeSet, utf8_percent_encode}; +use percent_encoding::{AsciiSet, utf8_percent_encode}; use crate::uri::{UriPart, Path, Query}; use crate::parse::uri::is_pchar; @@ -9,6 +9,25 @@ use crate::parse::uri::is_pchar; #[derive(Clone, Copy)] #[allow(non_camel_case_types)] pub struct UNSAFE_ENCODE_SET(PhantomData

); +pub trait EncodeSet { + const SET: AsciiSet; +} + +const fn build_set_from_table() -> AsciiSet { + const ASCII_RANGE_LEN: u8 = 0x80; + + let mut set = percent_encoding::CONTROLS.remove(0); + let mut b: u8 = 0; + while b < ASCII_RANGE_LEN { + if !is_pchar(b) { + set = set.add(b); + } + b += 1; + } + set +} + +const PATH_SET: AsciiSet = build_set_from_table(); impl Default for UNSAFE_ENCODE_SET

{ #[inline(always)] @@ -16,17 +35,15 @@ impl Default for UNSAFE_ENCODE_SET

{ } impl EncodeSet for UNSAFE_ENCODE_SET { - #[inline(always)] - fn contains(&self, byte: u8) -> bool { - !is_pchar(byte) || byte == b'%' - } + const SET: AsciiSet = PATH_SET + .add(b'%'); } impl EncodeSet for UNSAFE_ENCODE_SET { - #[inline(always)] - fn contains(&self, byte: u8) -> bool { - (!is_pchar(byte) && (byte != b'?')) || byte == b'%' || byte == b'+' - } + const SET: AsciiSet = PATH_SET + .remove(b'?') + .add(b'%') + .add(b'+'); } #[derive(Clone, Copy)] @@ -34,20 +51,14 @@ impl EncodeSet for UNSAFE_ENCODE_SET { pub struct ENCODE_SET(PhantomData

); impl EncodeSet for ENCODE_SET { - #[inline(always)] - fn contains(&self, byte: u8) -> bool { - >::default().contains(byte) || byte == b'/' - } + const SET: AsciiSet = >::SET + .add(b'/'); } impl EncodeSet for ENCODE_SET { - #[inline(always)] - fn contains(&self, byte: u8) -> bool { - >::default().contains(byte) || match byte { - b'&' | b'=' => true, - _ => false - } - } + const SET: AsciiSet = >::SET + .add(b'&') + .add(b'='); } #[derive(Default, Clone, Copy)] @@ -55,11 +66,11 @@ impl EncodeSet for ENCODE_SET { pub struct DEFAULT_ENCODE_SET; impl EncodeSet for DEFAULT_ENCODE_SET { - #[inline(always)] - fn contains(&self, byte: u8) -> bool { - ENCODE_SET::(PhantomData).contains(byte) || - ENCODE_SET::(PhantomData).contains(byte) - } + const SET: AsciiSet = >::SET + .add(b'%') + .add(b'+') + .add(b'&') + .add(b'='); } pub fn unsafe_percent_encode(string: &str) -> Cow<'_, str> { @@ -71,5 +82,5 @@ pub fn unsafe_percent_encode(string: &str) -> Cow<'_, str> { } pub fn percent_encode(string: &str) -> Cow<'_, str> { - utf8_percent_encode(string, S::default()).into() + utf8_percent_encode(string, &S::SET).into() } diff --git a/core/lib/Cargo.toml b/core/lib/Cargo.toml index 5c7a29bc05..f316510259 100644 --- a/core/lib/Cargo.toml +++ b/core/lib/Cargo.toml @@ -36,7 +36,7 @@ num_cpus = "1.0" state = "0.4.1" time = "0.1" memchr = "2" # TODO: Use pear instead. -base64 = "0.11" +base64 = "0.12" base16 = "0.2" pear = "0.1" atty = "0.2"