depolymerization

wire gateway for Bitcoin/Ethereum
Log | Files | Refs | Submodules | README | LICENSE

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:
Muri-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;