hash.fnv1a: add fnv1a.sum64_bytes and fnv1a.sum32_bytes, add doc comments and tests

pull/12995/head
Delyan Angelov 2021-12-29 11:27:26 +02:00
parent 9b8cf1ad37
commit 7c78bf9466
No known key found for this signature in database
GPG Key ID: 66886C0F12D595ED
2 changed files with 55 additions and 7 deletions

View File

@ -1,5 +1,8 @@
module fnv1a module fnv1a
// This module implements a FNV-1a hash.
// (see https://en.wikipedia.org/wiki/FowlerNollVo_hash_function)
const ( const (
fnv64_prime = u64(1099511628211) fnv64_prime = u64(1099511628211)
fnv64_offset_basis = u64(14695981039346656037) fnv64_offset_basis = u64(14695981039346656037)
@ -7,7 +10,8 @@ const (
fnv32_prime = u32(16777619) fnv32_prime = u32(16777619)
) )
[inline] // sum32 returns a fnv1a hash of the string, described by `data`
[direct_array_access; inline]
pub fn sum32_string(data string) u32 { pub fn sum32_string(data string) u32 {
mut hash := fnv1a.fnv32_offset_basis mut hash := fnv1a.fnv32_offset_basis
for i in 0 .. data.len { for i in 0 .. data.len {
@ -16,7 +20,9 @@ pub fn sum32_string(data string) u32 {
return hash return hash
} }
[inline] // sum32 returns a fnv1a hash of the memory block, described by the dynamic
// byte array `data`.
[direct_array_access; inline]
pub fn sum32(data []byte) u32 { pub fn sum32(data []byte) u32 {
mut hash := fnv1a.fnv32_offset_basis mut hash := fnv1a.fnv32_offset_basis
for i in 0 .. data.len { for i in 0 .. data.len {
@ -25,7 +31,19 @@ pub fn sum32(data []byte) u32 {
return hash return hash
} }
[inline] // sum32_bytes returns a fnv1a hash of `data_len` bytes starting at
// the address in the given &byte pointer `data`.
[direct_array_access; inline; unsafe]
pub fn sum32_bytes(data &byte, data_len int) u32 {
mut hash := fnv1a.fnv32_offset_basis
for i in 0 .. data_len {
hash = unsafe { (hash ^ u32(data[i])) * fnv1a.fnv32_prime }
}
return hash
}
// sum64 returns a fnv1a hash of the string, described by `data`
[direct_array_access; inline]
pub fn sum64_string(data string) u64 { pub fn sum64_string(data string) u64 {
mut hash := fnv1a.fnv64_offset_basis mut hash := fnv1a.fnv64_offset_basis
for i in 0 .. data.len { for i in 0 .. data.len {
@ -34,7 +52,9 @@ pub fn sum64_string(data string) u64 {
return hash return hash
} }
[inline] // sum64 returns a fnv1a hash of the memory block, described by the dynamic
// byte array `data`.
[direct_array_access; inline]
pub fn sum64(data []byte) u64 { pub fn sum64(data []byte) u64 {
mut hash := fnv1a.fnv64_offset_basis mut hash := fnv1a.fnv64_offset_basis
for i in 0 .. data.len { for i in 0 .. data.len {
@ -42,3 +62,14 @@ pub fn sum64(data []byte) u64 {
} }
return hash return hash
} }
// sum64_bytes returns a fnv1a hash of `data_len` bytes starting at
// the address in the given &byte pointer `data`.
[direct_array_access; inline; unsafe]
pub fn sum64_bytes(data &byte, data_len int) u64 {
mut hash := fnv1a.fnv64_offset_basis
for i in 0 .. data_len {
hash = unsafe { (hash ^ u64(data[i])) * fnv1a.fnv64_prime }
}
return hash
}

View File

@ -1,12 +1,29 @@
import hash.fnv1a import hash.fnv1a
fn test_fnv1a() { fn test_fnv1a_sum32() {
$if windows {
return
}
ahash := '10bc2abf'
a := 'apple'
b := fnv1a.sum32_string(a)
c := fnv1a.sum32(a.bytes())
d := unsafe { fnv1a.sum32_bytes(a.str, a.len) }
assert b.hex() == ahash
assert c.hex() == ahash
assert d.hex() == ahash
}
fn test_fnv1a_sum64() {
$if windows { $if windows {
return return
} }
a := 'apple' a := 'apple'
ahash := 'f74a62a458befdbf'
b := fnv1a.sum64_string(a) b := fnv1a.sum64_string(a)
c := fnv1a.sum64(a.bytes()) c := fnv1a.sum64(a.bytes())
assert b.hex() == 'f74a62a458befdbf' d := unsafe { fnv1a.sum64_bytes(a.str, a.len) }
assert c.hex() == 'f74a62a458befdbf' assert b.hex() == ahash
assert c.hex() == ahash
assert d.hex() == ahash
} }