From bace0576347e999f8a8352384ebcf3db9af75b7f Mon Sep 17 00:00:00 2001 From: Michal Nazarewicz Date: Wed, 19 Jul 2023 18:05:43 +0200 Subject: [PATCH] Simplify encode_to_slice by using chunks_exact_mut MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rather than using generate_iter to iterate over each 2-element chunks of output buffer, use chunks_exact_mut. This removes the need for the custom generate_iter function and makes the code shorter. Criterian shows improvement but to be honest I don’t trust those results (partially because also decoding showed improvements even though I didn’t touch it): hex_encode time: [79.268 µs 81.856 µs 84.279 µs] change: [-15.070% -12.678% -10.255%] (p = 0.00 < 0.05) Performance has improved. rustc_hex_encode time: [36.926 µs 36.949 µs 36.971 µs] change: [-3.3521% -3.2536% -3.1583%] (p = 0.00 < 0.05) Performance has improved. faster_hex_encode time: [820.07 ns 821.16 ns 822.52 ns] change: [-3.7706% -3.4712% -3.1944%] (p = 0.00 < 0.05) Performance has improved. faster_hex_encode_fallback time: [11.554 µs 11.557 µs 11.562 µs] change: [-2.8788% -2.8220% -2.7676%] (p = 0.00 < 0.05) Performance has improved. hex_decode time: [100.90 µs 100.98 µs 101.08 µs] change: [-3.9865% -3.5655% -3.2365%] (p = 0.00 < 0.05) Performance has improved. rustc_hex_decode time: [65.759 µs 65.788 µs 65.819 µs] change: [-2.1181% -1.9775% -1.8495%] (p = 0.00 < 0.05) Performance has improved. faster_hex_decode time: [2.2675 µs 2.2684 µs 2.2693 µs] change: [-2.9682% -2.8188% -2.6234%] (p = 0.00 < 0.05) Performance has improved. faster_hex_decode_unchecked time: [928.35 ns 929.18 ns 930.05 ns] change: [-0.5734% -0.4510% -0.3314%] (p = 0.00 < 0.05) Change within noise threshold. faster_hex_decode_fallback time: [11.416 µs 11.426 µs 11.438 µs] change: [-3.8020% -3.6669% -3.5267%] (p = 0.00 < 0.05) Performance has improved. --- src/lib.rs | 43 +++++++++---------------------------------- 1 file changed, 9 insertions(+), 34 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5a2b93f..dac968e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -292,17 +292,6 @@ pub fn decode_to_slice>(data: T, out: &mut [u8]) -> Result<(), Fr Ok(()) } -// generates an iterator like this -// (0, 1) -// (2, 3) -// (4, 5) -// (6, 7) -// ... -#[inline] -fn generate_iter(len: usize) -> impl Iterator { - (0..len).step_by(2).zip((0..len).skip(1).step_by(2)) -} - // the inverse of `val`. #[inline] #[must_use] @@ -347,18 +336,16 @@ const fn byte2hex(byte: u8, table: &[u8; 16]) -> (u8, u8) { /// # } /// ``` pub fn encode_to_slice>(input: T, output: &mut [u8]) -> Result<(), FromHexError> { - if input.as_ref().len() * 2 != output.len() { + let input = input.as_ref(); + if input.len() * 2 != output.len() { return Err(FromHexError::InvalidStringLength); } - for (byte, (i, j)) in input - .as_ref() - .iter() - .zip(generate_iter(input.as_ref().len() * 2)) - { - let (high, low) = byte2hex(*byte, HEX_CHARS_LOWER); - output[i] = high; - output[j] = low; + // TODO: use array_chunks_mut instead of chunks_exact_mut once it stabilises + for (out, &byte) in output.chunks_exact_mut(2).zip(input.iter()) { + let (high, low) = byte2hex(byte, HEX_CHARS_LOWER); + out[0] = high; + out[1] = low; } Ok(()) @@ -367,20 +354,8 @@ pub fn encode_to_slice>(input: T, output: &mut [u8]) -> Result<() #[cfg(test)] mod test { use super::*; - #[cfg(feature = "alloc")] - use alloc::string::ToString; - #[cfg(feature = "alloc")] - use alloc::vec; use pretty_assertions::assert_eq; - #[test] - #[cfg(feature = "alloc")] - fn test_gen_iter() { - let result = vec![(0, 1), (2, 3)]; - - assert_eq!(generate_iter(5).collect::>(), result); - } - #[test] fn test_encode_to_slice() { let mut output_1 = [0; 4 * 2]; @@ -498,12 +473,12 @@ mod test { fn test_to_hex() { assert_eq!( [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex::(), - "666f6f626172".to_string(), + "666f6f626172", ); assert_eq!( [0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex_upper::(), - "666F6F626172".to_string(), + "666F6F626172", ); } }