From 69c90ef50d71f6ab65f18721ee8b68627ab2548a Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Wed, 29 Dec 2021 12:03:24 +0200 Subject: [PATCH] hash.fnv1a: add generic fnv1a.sum64_struct/1 and fnv1a.sum32_struct/1 + tests --- vlib/hash/fnv1a/fnv1a.v | 24 +++++++++++++++++++++++ vlib/hash/fnv1a/fnv1a_test.v | 38 ++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/vlib/hash/fnv1a/fnv1a.v b/vlib/hash/fnv1a/fnv1a.v index 73d0899ac6..ffe1384350 100644 --- a/vlib/hash/fnv1a/fnv1a.v +++ b/vlib/hash/fnv1a/fnv1a.v @@ -31,6 +31,18 @@ pub fn sum32(data []byte) u32 { return hash } +// sum32_bytes returns a fnv1a hash of the struct `s`. +[direct_array_access; inline] +pub fn sum32_struct(s &T) u32 { + bp := unsafe { &byte(s) } + sz := int(sizeof(T)) + mut hash := fnv1a.fnv32_offset_basis + for i in 0 .. sz { + hash = unsafe { (hash ^ u32(bp[i])) * fnv1a.fnv32_prime } + } + return hash +} + // 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] @@ -73,3 +85,15 @@ pub fn sum64_bytes(data &byte, data_len int) u64 { } return hash } + +// sum64_bytes returns a fnv1a hash of the struct `s`. +[direct_array_access; inline] +pub fn sum64_struct(s &T) u64 { + bp := unsafe { &byte(s) } + sz := int(sizeof(T)) + mut hash := fnv1a.fnv64_offset_basis + for i in 0 .. sz { + hash = unsafe { (hash ^ u64(bp[i])) * fnv1a.fnv64_prime } + } + return hash +} diff --git a/vlib/hash/fnv1a/fnv1a_test.v b/vlib/hash/fnv1a/fnv1a_test.v index 9a979b6737..4c5dc762ac 100644 --- a/vlib/hash/fnv1a/fnv1a_test.v +++ b/vlib/hash/fnv1a/fnv1a_test.v @@ -1,5 +1,17 @@ import hash.fnv1a +struct MyStruct { +mut: + x int + y int + z int +} + +struct Abc { +mut: + a [5]u64 +} + fn test_fnv1a_sum32() { $if windows { return @@ -12,6 +24,19 @@ fn test_fnv1a_sum32() { assert b.hex() == ahash assert c.hex() == ahash assert d.hex() == ahash + // + mut aa := Abc{} + x := fnv1a.sum32_struct(aa) + aa.a[3] = 5 + y := fnv1a.sum32_struct(aa) + assert x != y + mut ms := MyStruct{} + xx := fnv1a.sum32_struct(ms) + ms.x = 77 + yy := fnv1a.sum32_struct(ms) + assert xx != yy + assert x != xx + assert y != yy } fn test_fnv1a_sum64() { @@ -26,4 +51,17 @@ fn test_fnv1a_sum64() { assert b.hex() == ahash assert c.hex() == ahash assert d.hex() == ahash + // + mut aa := Abc{} + x := fnv1a.sum64_struct(aa) + aa.a[3] = 5 + y := fnv1a.sum64_struct(aa) + assert x != y + mut ms := MyStruct{} + xx := fnv1a.sum64_struct(ms) + ms.x = 77 + yy := fnv1a.sum64_struct(ms) + assert xx != yy + assert x != xx + assert y != yy }