commit c8831e052173e6eb637b33d95d6dacd22f7d3e39
parent 8b4288f34ff7dcbde255cb417445bb09b58a5c33
Author: Antoine A <>
Date: Wed, 1 Dec 2021 19:21:50 +0100
Replace match with lookup table to help compiler optimize
+90% pack and unpack perf
Diffstat:
| M | uri-pack/src/lib.rs | | | 233 | +++++++++++++++++++++++++++++++++++++++++++------------------------------------ |
1 file changed, 128 insertions(+), 105 deletions(-)
diff --git a/uri-pack/src/lib.rs b/uri-pack/src/lib.rs
@@ -11,99 +11,122 @@ pub enum Packed {
/// Pack an URI ascii char
/// Panic if char not supported
fn pack_ascii(c: u8) -> Packed {
- let simple = match c {
- b'a'..=b'z' => c - b'a',
- b'.' => 26,
- b'/' => 27,
- b'-' => 28,
- b'_' => 29,
- b'%' => 30,
- c => {
- let extended = match c {
- b'A'..=b'Z' => c - b'A',
- b'0'..=b'9' => c - b'0' + 26,
- b'!' => 36,
- b'"' => 37,
- b'#' => 38,
- b'$' => 39,
- b'&' => 40,
- b'\'' => 41,
- b'(' => 42,
- b')' => 43,
- b'*' => 44,
- b'+' => 45,
- b',' => 46,
- b':' => 47,
- b';' => 48,
- b'<' => 49,
- b'=' => 50,
- b'>' => 51,
- b'?' => 52,
- b'@' => 53,
- b'[' => 54,
- b'\\' => 55,
- b']' => 56,
- b'^' => 57,
- b'`' => 58,
- b'{' => 59,
- b'|' => 60,
- b'}' => 61,
- b'~' => 62,
- b' ' => 63,
- _ => unreachable!(),
- };
- return Packed::Extended(extended);
- }
- };
- Packed::Simple(simple)
+ use Packed::{Extended as E, Simple as S};
+ [
+ E(63),
+ E(36),
+ E(37),
+ E(38),
+ E(39),
+ S(30),
+ E(40),
+ E(41),
+ E(42),
+ E(43),
+ E(44),
+ E(45),
+ E(46),
+ S(28),
+ S(26),
+ S(27),
+ E(26),
+ E(27),
+ E(28),
+ E(29),
+ E(30),
+ E(31),
+ E(32),
+ E(33),
+ E(34),
+ E(35),
+ E(47),
+ E(48),
+ E(49),
+ E(50),
+ E(51),
+ E(52),
+ E(53),
+ E(0),
+ E(1),
+ E(2),
+ E(3),
+ E(4),
+ E(5),
+ E(6),
+ E(7),
+ E(8),
+ E(9),
+ E(10),
+ E(11),
+ E(12),
+ E(13),
+ E(14),
+ E(15),
+ E(16),
+ E(17),
+ E(18),
+ E(19),
+ E(20),
+ E(21),
+ E(22),
+ E(23),
+ E(24),
+ E(25),
+ E(54),
+ E(55),
+ E(56),
+ E(57),
+ S(29),
+ E(58),
+ S(0),
+ S(1),
+ S(2),
+ S(3),
+ S(4),
+ S(5),
+ S(6),
+ S(7),
+ S(8),
+ S(9),
+ S(10),
+ S(11),
+ S(12),
+ S(13),
+ S(14),
+ S(15),
+ S(16),
+ S(17),
+ S(18),
+ S(19),
+ S(20),
+ S(21),
+ S(22),
+ S(23),
+ S(24),
+ S(25),
+ E(59),
+ E(60),
+ E(61),
+ E(62),
+ ][(c - b' ') as usize]
}
/// Unpack an URI ascii char
/// Panic if char not supported
fn unpack_ascii(c: Packed) -> u8 {
match c {
- Packed::Simple(c) => match c {
- 0..=25 => b'a' + c,
- 26 => b'.',
- 27 => b'/',
- 28 => b'-',
- 29 => b'_',
- 30 => b'%',
- _ => unreachable!(),
- },
- Packed::Extended(c) => match c {
- 0..=25 => b'A' + c,
- 26..=35 => b'0' + c - 26,
- 36 => b'!',
- 37 => b'"',
- 38 => b'#',
- 39 => b'$',
- 40 => b'&',
- 41 => b'\'',
- 42 => b'(',
- 43 => b')',
- 44 => b'*',
- 45 => b'+',
- 46 => b',',
- 47 => b':',
- 48 => b';',
- 49 => b'<',
- 50 => b'=',
- 51 => b'>',
- 52 => b'?',
- 53 => b'@',
- 54 => b'[',
- 55 => b'\\',
- 56 => b']',
- 57 => b'^',
- 58 => b'`',
- 59 => b'{',
- 60 => b'|',
- 61 => b'}',
- 62 => b'~',
- 63 => b' ',
- _ => unreachable!(),
- },
+ Packed::Simple(c) => [
+ b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n',
+ b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w', b'x', b'y', b'z', b'.', b'/',
+ b'-', b'_', b'%',
+ ][c as usize],
+ Packed::Extended(c) => [
+ b'A', b'B', b'C', b'D', b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N',
+ b'O', b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W', b'X', b'Y', b'Z', b'0', b'1',
+ b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'!', b'"', b'#', b'$', b'&', b'\'',
+ b'(', b')', b'*', b'+', b',', b':', b';', b'<', b'=', b'>', b'?', b'@', b'[', b'\\',
+ b']', b'^', b'`', b'{', b'|', b'}', b'~', b' ',
+ ][c as usize],
}
}
/// Check if an ascii char is packable
@@ -140,28 +163,28 @@ pub fn pack_uri(uri: &str) -> Result<(Vec<u8>, usize), EncodeErr> {
// Holds pending bits beginning from the most significant bits
// If buff contains 10110:
- // buff_bits ─────
+ // buff_bits _____
// buff 10110000
let (mut buff, mut buff_bits) = (0u8, 0u8);
let mut write_bits = |nb: u8, mut nb_bits: u8| {
- // buff_bits ─────
+ // buff_bits ____
// buff 10110000
- // nb_bits ────
+ // nb_bits ____
// nb 00011010
//
- // ───
+ // ___
// writable 00011010
- // ───
+ // ___
// rmv_right 00001101
- // ───
+ // ___
// rmv_left 10100000
- // ───
+ // ___
// align 00000101
//
- // buff_bits ────────
+ // buff_bits ________
// buff 10110101
- // nb_bits -
+ // nb_bits _
// nb 00011010
while nb_bits > 0 {
// Amount of bits we can write in buff
@@ -211,26 +234,26 @@ pub fn unpack_uri(bytes: &[u8], len: usize) -> Result<String, DecodeErr> {
// Holds pending bits beginning from the most significant bits
// If buff contains 10110:
- // buff_bits ─────
+ // buff_bits _____
// buff 10110000
let (mut buff, mut buff_bits) = (0u8, 0u8);
-
+
let mut read_nb = |mut nb_bits: u8| -> Result<u8, DecodeErr> {
- // buff_bits ─────
+ // buff_bits _____
// buff 10110000
- // nb_bits ───
+ // nb_bits ___
// nb 00000000
//
- // ───
+ // ___
// readable 10110000
- // ───
+ // ___
// rmv_left 01100000
- // ───
+ // ___
// align 00000011
//
- // buff_bits ─
+ // buff_bits _
// buff 10110000
- // nb_bits
+ // nb_bits
// nb 00000011
let mut nb = 8;