Skip to content

Commit

Permalink
Merge pull request #19 from tloncorp/eamsden/non_copying
Browse files Browse the repository at this point in the history
Add non-copying version of murmur3_32 that reads directly from a byte buffer
  • Loading branch information
stusmall authored Feb 16, 2023
2 parents 75a1128 + 7878a0f commit 07e7a1a
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 3 deletions.
12 changes: 11 additions & 1 deletion benches/bench.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#![feature(test)]

extern crate murmur3_sys;
extern crate test;

Expand All @@ -23,6 +22,17 @@ fn bench_32(b: &mut Bencher) {
});
}

#[bench]
fn bench_32_slice(b: &mut Bencher) {
let string: &[u8] =
test::black_box(b"Lorem ipsum dolor sit amet, consectetur adipisicing elit");
b.bytes = string.len() as u64;
b.iter(|| {
let tmp = &string[0..string.len()];
murmur3_32_of_slice(tmp, 0);
});
}

#[bench]
fn bench_c_32(b: &mut Bencher) {
let string: &[u8] =
Expand Down
53 changes: 52 additions & 1 deletion src/murmur3_32.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

use std::cmp::min;
use std::io::{Read, Result};

use crate::read_bytes;
Expand Down Expand Up @@ -60,9 +61,59 @@ pub fn murmur3_32<T: Read>(source: &mut T, seed: u32) -> Result<u32> {
}
}

/// Use the 32 bit variant of murmur3 to hash [u8] without copying the buffer.
///
/// # Example
///
/// ```
/// use murmur3::murmur3_32_of_slice;
/// let hash_result = murmur3_32_of_slice("hello world".as_bytes(), 0);
/// ```
pub fn murmur3_32_of_slice(source: &[u8], seed: u32) -> u32 {
let mut buffer = source;
let mut processed = 0;
let mut state = seed;
loop {
match min(buffer.len(), 4) {
0 => return finish(state, processed),
1 => {
processed += 1;
let k: u32 = buffer[0] as u32;
state ^= calc_k(k);
return finish(state, processed);
}
2 => {
processed += 2;
let k: u32 = ((buffer[1] as u32) << 8) | (buffer[0] as u32);
state ^= calc_k(k);
return finish(state, processed);
}
3 => {
processed += 3;
let k: u32 =
((buffer[2] as u32) << 16) | ((buffer[1] as u32) << 8) | (buffer[0] as u32);
state ^= calc_k(k);
return finish(state, processed);
}
4 => {
processed += 4;
let k: u32 = ((buffer[3] as u32) << 24)
| ((buffer[2] as u32) << 16)
| ((buffer[1] as u32) << 8)
| (buffer[0] as u32);
state ^= calc_k(k);
state = state.rotate_left(R2);
state = (state.wrapping_mul(M)).wrapping_add(N);
buffer = &buffer[4..];
}
_ => unreachable!(),
};
}
}

fn finish(state: u32, processed: u32) -> u32 {
let mut hash = state;
hash ^= processed as u32;
hash ^= processed;
hash ^= hash.wrapping_shr(R1);
hash = hash.wrapping_mul(C1);
hash ^= hash.wrapping_shr(R2);
Expand Down
16 changes: 15 additions & 1 deletion tests/quickcheck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ extern crate murmur3_sys;

use std::io::Cursor;

use murmur3::murmur3_32;
use murmur3::{murmur3_32, murmur3_32_of_slice};
use murmur3_sys::MurmurHash3_x86_32;

use murmur3::murmur3_x86_128;
Expand All @@ -36,6 +36,20 @@ quickcheck! {
}
}

quickcheck! {
fn quickcheck_32_slice(input:(u32, Vec<u8>)) -> bool{
let seed = input.0;
let xs = input.1;
let mut output: [u8; 4] = [0; 4];
unsafe {
MurmurHash3_x86_32(xs.as_ptr() as _, xs.len() as i32, seed, output.as_mut_ptr() as _)
};
let output = u32::from_le_bytes(output);
let output2 = murmur3_32_of_slice(&xs[..], seed);
output == output2
}
}

quickcheck! {
fn quickcheck_x86_128(input:(u32, Vec<u8>)) -> bool {
let seed = input.0;
Expand Down
7 changes: 7 additions & 0 deletions tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,13 @@ fn test_static_strings() {
test.string
);

assert_eq!(
murmur3::murmur3_32_of_slice(test.string.as_bytes(), 0),
test.hash_32,
"Failed 32_of_slice on string {}",
test.string,
);

let mut string = String::new();
str_as_chained_cursor(test.string)
.read_to_string(&mut string)
Expand Down

0 comments on commit 07e7a1a

Please sign in to comment.