Skip to content

Commit

Permalink
Simplify encode_to_slice by using chunks_exact_mut
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
mina86 committed Dec 31, 2024
1 parent 98b1ee3 commit bace057
Showing 1 changed file with 9 additions and 34 deletions.
43 changes: 9 additions & 34 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,17 +292,6 @@ pub fn decode_to_slice<T: AsRef<[u8]>>(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<Item = (usize, usize)> {
(0..len).step_by(2).zip((0..len).skip(1).step_by(2))
}

// the inverse of `val`.
#[inline]
#[must_use]
Expand Down Expand Up @@ -347,18 +336,16 @@ const fn byte2hex(byte: u8, table: &[u8; 16]) -> (u8, u8) {
/// # }
/// ```
pub fn encode_to_slice<T: AsRef<[u8]>>(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(())
Expand All @@ -367,20 +354,8 @@ pub fn encode_to_slice<T: AsRef<[u8]>>(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::<Vec<_>>(), result);
}

#[test]
fn test_encode_to_slice() {
let mut output_1 = [0; 4 * 2];
Expand Down Expand Up @@ -498,12 +473,12 @@ mod test {
fn test_to_hex() {
assert_eq!(
[0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex::<String>(),
"666f6f626172".to_string(),
"666f6f626172",
);

assert_eq!(
[0x66, 0x6f, 0x6f, 0x62, 0x61, 0x72].encode_hex_upper::<String>(),
"666F6F626172".to_string(),
"666F6F626172",
);
}
}

0 comments on commit bace057

Please sign in to comment.