cuckoo 0.2.2 → 0.3.0
raw patch · 9 files changed
+257/−154 lines, 9 filesdep +blake2dep +hashesdep −cryptonitedep −memorydep ~basePVP ok
version bump matches the API change (PVP)
Dependencies added: blake2, hashes
Dependencies removed: cryptonite, memory
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.Cuckoo: fnv1a :: Storable a => Int -> a -> Word64
- Data.Cuckoo: fnv1a_bytes :: ByteArrayAccess a => Int -> a -> Word64
- Data.Cuckoo: sip :: Storable a => Int -> a -> Word64
- Data.Cuckoo: sip_bytes :: ByteArrayAccess a => Int -> a -> Word64
- Data.Cuckoo.Internal: fnv1a :: Storable a => Int -> a -> Word64
- Data.Cuckoo.Internal: fnv1a_bytes :: ByteArrayAccess a => Int -> a -> Word64
- Data.Cuckoo.Internal: sip :: Storable a => Int -> a -> Word64
- Data.Cuckoo.Internal: sip2 :: Storable a => Int -> a -> Word64
- Data.Cuckoo.Internal: sip_bytes :: ByteArrayAccess a => Int -> a -> Word64
+ Data.Cuckoo: saltedFnv1aByteString :: Int -> ByteString -> Word64
+ Data.Cuckoo: saltedFnv1aPtr :: Int -> Ptr Word8 -> Int -> Word64
+ Data.Cuckoo: saltedFnv1aStorable :: Storable a => Int -> a -> Word64
+ Data.Cuckoo: saltedSipHashByteString :: Int -> ByteString -> Word64
+ Data.Cuckoo: saltedSipHashPtr :: Int -> Ptr Word8 -> Int -> Word64
+ Data.Cuckoo: saltedSipHashStorable :: Storable a => Int -> a -> Word64
+ Data.Cuckoo.Internal.HashFunctions: saltedFnv1aByteString :: Int -> ByteString -> Word64
+ Data.Cuckoo.Internal.HashFunctions: saltedFnv1aPtr :: Int -> Ptr Word8 -> Int -> Word64
+ Data.Cuckoo.Internal.HashFunctions: saltedFnv1aStorable :: Storable a => Int -> a -> Word64
+ Data.Cuckoo.Internal.HashFunctions: saltedSipHashByteString :: Int -> ByteString -> Word64
+ Data.Cuckoo.Internal.HashFunctions: saltedSipHashPtr :: Int -> Ptr Word8 -> Int -> Word64
+ Data.Cuckoo.Internal.HashFunctions: saltedSipHashStorable :: Storable a => Int -> a -> Word64
+ Data.Cuckoo.Internal.HashFunctions: sipHashInternal :: Storable a => Int -> a -> Word64
Files
- CHANGELOG.md +21/−0
- LICENSE +1/−1
- bench/Internal.hs +5/−3
- bench/SpellChecker.hs +2/−3
- cuckoo.cabal +12/−16
- src/Data/Cuckoo.hs +32/−15
- src/Data/Cuckoo/Internal.hs +1/−94
- src/Data/Cuckoo/Internal/HashFunctions.hs +139/−0
- test/Main.hs +44/−22
CHANGELOG.md view
@@ -1,5 +1,26 @@ # Revision history for cuckoo +## 0.3.0 -- 2021-09-30++* Rename hash functions provided hash functions to++ * `saltedSipHashStorable`+ * `saltedSipHashByteString`+ * `saltedSipHashPtr`+ * `saltedFnv1aStorable`+ * `saltedFnv1aByteString`+ * `saltedFnv1aPtr`++* Use [hashes](https://hackage.haskell.org/package/hashes) package for hash+ functions and drop dependency on+ [memory](https://hackage.haskell.org/package/memory).++ The [bytestring](https://hackage.haskell.org/package/bytestring) package is+ is added as a new dependency.++* Move implementation of hash functions from+ `Data.Cuckoo.Internal` to `Data.Cuckoo.Internal.HashFunctions`.+ ## 0.2.2 -- 2021-06-24 * Support GHC-9
LICENSE view
@@ -1,4 +1,4 @@-Copyright (c) 2019, Lars Kuhtz <lakuhtz@gmail.com>+Copyright (c) 2019-2021, Lars Kuhtz <lakuhtz@gmail.com> All rights reserved.
bench/Internal.hs view
@@ -7,7 +7,7 @@ -- | -- Module: Main--- Copyright: Copyright © 2019 Lars Kuhtz <lakuhtz@gmail.com>+-- Copyright: Copyright © 2019-2021 Lars Kuhtz <lakuhtz@gmail.com> -- License: BSD3 -- Maintainer: Lars Kuhtz <lakuhtz@gmail.com> -- Stability: experimental@@ -36,7 +36,9 @@ main :: IO () main = do+ putStrLn "prop_fit" quickCheck prop_fit+ putStrLn "prop_p2" quickCheck prop_p2 defaultMain [ bgroup "fit"@@ -117,8 +119,8 @@ -- Ignore negative values ---prop_p2 :: NonNegative Int -> Property-prop_p2 (NonNegative x)+prop_p2 :: Positive Int -> Property+prop_p2 (Positive x) = floatingP2 x === integralP2_0 x .&&. floatingP2 x === integralP2_1 x .&&. floatingP2 x === integralP2_2 x
bench/SpellChecker.hs view
@@ -21,7 +21,6 @@ import Control.Monad (filterM, unless) import Control.StopWatch -import Data.ByteArray () import qualified Data.ByteString.Char8 as B import qualified Data.Cuckoo as C import Data.List ((\\))@@ -38,8 +37,8 @@ -- {-# INLINE cuckooFingerprint #-} instance C.CuckooFilterHash B.ByteString where- cuckooHash (C.Salt s) = C.fnv1a_bytes s- cuckooFingerprint (C.Salt s) = C.sip_bytes s+ cuckooHash (C.Salt s) = C.saltedFnv1aByteString s+ cuckooFingerprint (C.Salt s) = C.saltedSipHashByteString s {-# INLINE cuckooHash #-} {-# INLINE cuckooFingerprint #-}
cuckoo.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: cuckoo-version: 0.2.2+version: 0.3.0 synopsis: Haskell Implementation of Cuckoo Filters Description: Haskell implementation of Cuckoo filters as described in@@ -29,7 +29,7 @@ category: Data tested-with: GHC==9.0.1- GHC==8.10.5+ GHC==8.10.7 GHC==8.8.4 extra-source-files: README.md@@ -57,7 +57,7 @@ ghc-options: -Wall build-depends:- , base >=4.11 && <4.16+ , base >=4.11 && <5 , primitive >=0.6.4.0 if flag(pcg-random)@@ -81,14 +81,15 @@ exposed-modules: Data.Cuckoo Data.Cuckoo.Internal+ Data.Cuckoo.Internal.HashFunctions build-depends: , random-internal -- external- , base >=4.11 && <4.16- , memory >=0.14+ , base >=4.11 && <5+ , bytestring >=0.10+ , hashes >=0.1 , primitive >=0.6.4.0- , vector >=0.12 test-suite tests type: exitcode-stdio-1.0@@ -106,11 +107,10 @@ , random-internal -- external- , base >=4.11 && <4.16+ , base >=4.11 && <5+ , blake2 >=0.3 , bytestring >=0.10- , cryptonite >=0.26 , hashable >=1.3- , memory >=0.14 , stopwatch >=0.1 test-suite doctests@@ -123,11 +123,8 @@ -with-rtsopts=-N main-is: doctest.hs build-depends:- , cuckoo- , base >=4.11 && <4.16+ , base >=4.11 && <5 , doctest >= 0.18- , memory >=0.14- , primitive >=0.6.4.0 benchmark spellchecker type: exitcode-stdio-1.0@@ -144,9 +141,8 @@ , cuckoo -- external- , base >=4.11 && <4.16+ , base >=4.11 && <5 , bytestring >=0.10- , memory >=0.14 , stopwatch >=0.1 benchmark internal-benchmarks@@ -167,6 +163,6 @@ -- external , QuickCheck >= 2.13- , base >=4.10 && <4.16+ , base >=4.10 && <5 , criterion >= 1.5
src/Data/Cuckoo.hs view
@@ -10,7 +10,7 @@ -- | -- Module: Data.Cuckoo--- Copyright: Copyright © 2019 Lars Kuhtz <lakuhtz@gmail.com>+-- Copyright: Copyright © 2019-2021 Lars Kuhtz <lakuhtz@gmail.com> -- License: BSD3 -- Maintainer: Lars Kuhtz <lakuhtz@gmail.com> -- Stability: experimental@@ -83,10 +83,12 @@ , CuckooFilterHash(..) -- ** Hash functions-, sip-, sip_bytes-, fnv1a-, fnv1a_bytes+, saltedSipHashStorable+, saltedSipHashByteString+, saltedSipHashPtr+, saltedFnv1aStorable+, saltedFnv1aByteString+, saltedFnv1aPtr -- * Cuckoo Filter , CuckooFilter@@ -134,10 +136,18 @@ -- internal modules import Data.Cuckoo.Internal+import Data.Cuckoo.Internal.HashFunctions -- $setup -- >>> :set -XTypeApplications -XDataKinds -XTypeFamilies--- >>> instance CuckooFilterHash Int+-- >>> :{+-- instance CuckooFilterHash Int where+-- -- can't use default implementation with doctest because of a bug in GHC-9+-- cuckooHash (Salt s) a = saltedFnv1aStorable s a+-- cuckooFingerprint (Salt s) a = saltedSipHashStorable s a+-- {-# INLINE cuckooHash #-}+-- {-# INLINE cuckooFingerprint #-}+-- :} -- -------------------------------------------------------------------------- -- -- Hash Functions@@ -156,7 +166,7 @@ -- implementation of fnv. -- -- Because of the variying quality and properties of the functions, absence of--- any control over which function is use, and no guarantees with respect to+-- any control over which function is used, and no guarantees with respect to -- stability accross versions, we don't use that package altogether. -- @@ -174,7 +184,14 @@ -- The default implementations use sip hash for 'cuckooHash' and 'fnv1a' (64 -- bit) for 'cuckooFingerprint' and require an instance of 'Storable'. ----- >>> instance CuckooFilterHash Int+-- >>> :{+-- instance CuckooFilterHash Int where+-- -- can't use default implementation with doctest because of a bug in GHC-9+-- cuckooHash (Salt s) a = saltedFnv1aStorable s a+-- cuckooFingerprint (Salt s) a = saltedSipHashStorable s a+-- {-# INLINE cuckooHash #-}+-- {-# INLINE cuckooFingerprint #-}+-- :} -- -- The following example uses the hash functions that are provided in this -- module to define an instance for 'B.ByteString':@@ -182,8 +199,8 @@ -- >>> import qualified Data.ByteString as B -- >>> :{ -- instance CuckooFilterHash B.ByteString where--- cuckooHash (Salt s) a = fnv1a_bytes s a--- cuckooFingerprint (Salt s) a = sip_bytes s a+-- cuckooHash (Salt s) a = saltedFnv1aByteString s a+-- cuckooFingerprint (Salt s) a = saltedSipHashByteString s a -- {-# INLINE cuckooHash #-} -- {-# INLINE cuckooFingerprint #-} -- :}@@ -204,14 +221,14 @@ -- of 'Storable'. -- default cuckooHash :: Storable a => Salt -> a -> Word64- cuckooHash (Salt s) a = sip s a+ cuckooHash (Salt s) = saltedSipHashStorable s {-# INLINE cuckooHash #-} -- | Default implementation of 'cuckooFingerprint' for types that are an -- instance of 'Storable'. -- default cuckooFingerprint :: Storable a => Salt -> a -> Word64- cuckooFingerprint (Salt s) a = fnv1a s a+ cuckooFingerprint (Salt s) = saltedFnv1aStorable s {-# INLINE cuckooFingerprint #-} -- -------------------------------------------------------------------------- --@@ -494,7 +511,7 @@ -- isn't independent from this one. -- hashFingerprint :: Salt -> Fingerprint f -> Int-hashFingerprint (Salt s) (Fingerprint a) = int $! sip2 s a+hashFingerprint (Salt s) (Fingerprint a) = int $! sipHashInternal s a {-# INLINE hashFingerprint #-} mkFingerprint@@ -509,12 +526,12 @@ {-# INLINE mkFingerprint #-} bucket1 :: CuckooFilterHash a => CuckooFilter s b f a -> a -> Bucket-bucket1 f a = Bucket $! int $! cuckooHash (_cfSalt f) a .&. (int $ _cfBucketCount f - 1)+bucket1 f a = Bucket $! int $! cuckooHash (_cfSalt f) a .&. int (_cfBucketCount f - 1) {-# INLINE bucket1 #-} otherBucket :: CuckooFilter s b f a -> Bucket -> Fingerprint f -> Bucket otherBucket f (Bucket b) fp = Bucket $!- (b `xor` hashFingerprint (_cfSalt f) fp) .&. (int $ _cfBucketCount f - 1)+ (b `xor` hashFingerprint (_cfSalt f) fp) .&. int (_cfBucketCount f - 1) {-# INLINE otherBucket #-} ix :: Bucket -> Int
src/Data/Cuckoo/Internal.hs view
@@ -9,7 +9,7 @@ -- | -- Module: Data.Cuckoo.Internal--- Copyright: Copyright © 2019 Lars Kuhtz <lakuhtz@gmail.com>+-- Copyright: Copyright © 2019-2021 Lars Kuhtz <lakuhtz@gmail.com> -- License: BSD3 -- Maintainer: Lars Kuhtz <lakuhtz@gmail.com> -- Stability: experimental@@ -27,21 +27,11 @@ , intNextPowerOfTwo , set , get---- * Hash functions-, sip-, fnv1a-, fnv1a_bytes-, sip_bytes-, sip2 ) where import Control.Monad.Primitive import Data.Bits-import qualified Data.ByteArray as BA-import qualified Data.ByteArray.Hash as BA-import qualified Data.ByteArray.Pack as BA import Data.Primitive.ByteArray import Foreign@@ -105,89 +95,6 @@ intNextPowerOfTwo 0 = 1 intNextPowerOfTwo x = 1 `unsafeShiftL` (finiteBitSize x - countLeadingZeros (x - 1)) {-# INLINE intNextPowerOfTwo #-}---- | Computes a 64 bit Fnv1a hash for a value that has an 'Storable' instance.------ The first argument is use as a salt.----fnv1a- :: Storable a- => Int- -- ^ Salt- -> a- -- ^ Value that is hashes- -> Word64-fnv1a s x = r- where- Right (BA.FnvHash64 r) = BA.fnv1a_64Hash- <$> BA.fill @BA.Bytes (8 + sizeOf x) (BA.putStorable s >> BA.putStorable x)-{-# INLINE fnv1a #-}---- | Computes a 64 bit Fnv1a hash for a value that is an instance of--- 'BA.ByteArrayAccess'.------ The first argument is use as a salt.----fnv1a_bytes- :: BA.ByteArrayAccess a- => Int- -- ^ Salt- -> a- -- ^ Value that is hashes- -> Word64-fnv1a_bytes s x = r- where- Right (BA.FnvHash64 r) = BA.fnv1a_64Hash- <$> BA.fill @BA.Bytes (8 + BA.length x) (BA.putStorable s >> BA.putBytes x)-{-# INLINE fnv1a_bytes #-}---- | Computes a Sip hash for a value that has an 'Storable' instance.------ The first argument is a salt value that is used to derive the key for the--- hash computation.----sip- :: Storable a- => Int- -- ^ Salt- -> a- -- ^ Value that is hashes- -> Word64-sip s x = r- where- Right (BA.SipHash r) = BA.sipHash (BA.SipKey (int s) 914279)- <$> BA.fill @BA.Bytes (sizeOf x) (BA.putStorable x)-{-# INLINE sip #-}---- | Computes a Sip hash for a value that is an instance of--- 'BA.ByteArrayAccess'.------ The first argument is a salt value that is used to derive the key for the--- hash computation.----sip_bytes- :: BA.ByteArrayAccess a- => Int- -- ^ Salt- -> a- -- ^ Value that is hashes- -> Word64-sip_bytes s x = r- where- Right (BA.SipHash r) = BA.sipHash (BA.SipKey (int s) 1043639)- <$> BA.fill @BA.Bytes (BA.length x) (BA.putBytes x)-{-# INLINE sip_bytes #-}---- | An version of a Sip hash that is used internally. In order to avoid--- dependencies between different hash computations, it shouldn't be used in the--- implementation of instances of 'Data.Cuckoo.CuckooFilterHash'.----sip2 :: Storable a => Int -> a -> Word64-sip2 s x = r- where- Right (BA.SipHash r) = BA.sipHash (BA.SipKey 994559 (int s * 713243))- <$> BA.fill @BA.Bytes (sizeOf x) (BA.putStorable x)-{-# INLINE sip2 #-} -- | Write a 'Word64' value into a 'Word32' aligned 'MutableByteArray' --
+ src/Data/Cuckoo/Internal/HashFunctions.hs view
@@ -0,0 +1,139 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- |+-- Module: Data.Cuckoo.Internal.HashFunctions+-- Copyright: Copyright © 2021 Lars Kuhtz <lakuhtz@gmail.com>+-- License: BSD3+-- Maintainer: Lars Kuhtz <lakuhtz@gmail.com>+-- Stability: experimental+--+module Data.Cuckoo.Internal.HashFunctions+(+-- * Salted Hash Functions+ saltedFnv1aPtr+, saltedFnv1aStorable+, saltedFnv1aByteString++-- ** Salted Sip Hash+, saltedSipHashPtr+, saltedSipHashStorable+, saltedSipHashByteString++-- * Internal Use Only+, sipHashInternal+) where++import qualified Data.ByteString as B+import Data.Hash.FNV1+import Data.Hash.SipHash++import Foreign++import Data.Cuckoo.Internal++-- -------------------------------------------------------------------------- --+-- FNV1a++-- | Computes a 64 bit Fnv1a hash for a value that is an instance of+-- 'BA.ByteArrayAccess'.+--+-- The first argument is use as a salt.+--+saltedFnv1aPtr+ :: Int+ -- ^ Salt+ -> Ptr Word8+ -- ^ Bytes that are hashed+ -> Int+ -- ^ Number of bytes+ -> Word64+saltedFnv1aPtr s p ps = hashPtr_ fnv1a_64_ p ps+ $! hashStorable fnv1a_64 s+{-# INLINE saltedFnv1aPtr #-}++-- | Computes a 64 bit Fnv1a hash for a value that has an 'Storable' instance.+--+-- The first argument is use as a salt.+--+saltedFnv1aStorable+ :: Storable a+ => Int+ -- ^ Salt+ -> a+ -- ^ Value that is hashed+ -> Word64+saltedFnv1aStorable s x = hashStorable_ fnv1a_64_ x+ $! hashStorable fnv1a_64 s+{-# INLINE saltedFnv1aStorable #-}++saltedFnv1aByteString+ :: Int+ -- ^ Salt+ -> B.ByteString+ -- ^ Bytes that are hashed+ -> Word64+saltedFnv1aByteString s b = hashByteString_ fnv1a_64_ b+ $! hashStorable fnv1a_64 s+{-# INLINE saltedFnv1aByteString #-}++-- -------------------------------------------------------------------------- --+-- Sip Hash++-- | Computes a Sip hash for a value that is represented as byte pointer.+--+-- The first argument is a salt value that is used to derive the key for the+-- hash computation.+--+saltedSipHashPtr+ :: Int+ -- ^ Salt+ -> Ptr Word8+ -- ^ Bytes that is hashed+ -> Int+ -- ^ Number of bytes+ -> Word64+saltedSipHashPtr s ptr l = hashPtr (sipHash24 (int s) 1043639) ptr l+{-# INLINE saltedSipHashPtr #-}++-- | Computes a Sip hash for a value that has an 'Storable' instance.+--+-- The first argument is a salt value that is used to derive the key for the+-- hash computation.+--+saltedSipHashStorable+ :: Storable a+ => Int+ -- ^ Salt+ -> a+ -- ^ Value that is hashed+ -> Word64+saltedSipHashStorable s = hashStorable (sipHash24 (int s) 914279)+{-# INLINE saltedSipHashStorable #-}++-- | Computes a Sip hash for a value that has an 'Storable' instance.+--+-- The first argument is a salt value that is used to derive the key for the+-- hash computation.+--+saltedSipHashByteString+ :: Int+ -- ^ Salt+ -> B.ByteString+ -- ^ Value that is hashed+ -> Word64+saltedSipHashByteString s = hashByteString (sipHash24 (int s) 914279)+{-# INLINE saltedSipHashByteString #-}++-- -------------------------------------------------------------------------- --+-- Interal Use Only (Do Not Use)++-- | An version of a Sip hash that is used only internally. In order to avoid+-- dependencies between different hash computations, it shouldn't be used in the+-- implementation of instances of 'Data.Cuckoo.CuckooFilterHash'.+--+sipHashInternal :: Storable a => Int -> a -> Word64+sipHashInternal s = hashStorable (sipHash24 994559 (int s * 713243))+{-# INLINE sipHashInternal #-}+
test/Main.hs view
@@ -4,6 +4,7 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE PackageImports #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeApplications #-} @@ -11,7 +12,7 @@ -- | -- Module: Main--- Copyright: Copyright © 2019 Lars Kuhtz <lakuhtz@gmail.com>+-- Copyright: Copyright © 2019-2021 Lars Kuhtz <lakuhtz@gmail.com> -- License: BSD3 -- Maintainer: Lars Kuhtz <lakuhtz@gmail.com> -- Stability: experimental@@ -29,13 +30,13 @@ import Control.StopWatch -import qualified Crypto.Hash as C+import qualified Crypto.Hash.BLAKE2.BLAKE2b as C import Data.Bool-import qualified Data.ByteArray as BA-import qualified Data.ByteArray.Pack as BA hiding (pack) import qualified Data.ByteString as B-import Data.Either+import qualified Data.ByteString.Builder as BB+import qualified Data.ByteString.Lazy as LB+import qualified Data.ByteString.Unsafe as B import Data.Hashable import Foreign@@ -43,8 +44,9 @@ import Numeric.Natural import System.IO.Unsafe-import System.Random.Internal +import "cuckoo" System.Random.Internal+ -- internal modules import Data.Cuckoo@@ -67,13 +69,13 @@ putStrLn "[ByteString] fill up to first insert failure" stopWatch (test2 @HashablePkg n) >>= p "Hashable Package" stopWatch (test2 @Fnv1aSip n) >>= p "Fnv1a+Sip"- stopWatch (test2 @Crypto n) >>= p "Blake2b_256"+ stopWatch (test2 @Crypto n) >>= p "Blake2b_8" putStrLn "" putStrLn "[ByteString] fill to 95%" stopWatch (test3 @HashablePkg n) >>= p "Hashable Package" stopWatch (test3 @Fnv1aSip n) >>= p "Fnv1a+Sip"- stopWatch (test3 @Crypto n) >>= p "Blake2b_256"+ stopWatch (test3 @Crypto n) >>= p "Blake2b_8" where p l (r, t) = putStrLn $ show t <> " - " <> l <> " - " <> show r n = 500000@@ -85,11 +87,28 @@ instance CuckooFilterHash Double -- -------------------------------------------------------------------------- --+-- Hash Utils++integralBytes :: Integral a => a -> B.ByteString+integralBytes = LB.toStrict . BB.toLazyByteString . BB.int64LE . fromIntegral+{-# INLINE integralBytes #-}++class Pack a where+ pack :: [Word8] -> a+ unpack :: a -> [Word8]++instance Pack B.ByteString where+ pack = B.pack+ unpack = B.unpack+ {-# INLINE pack #-}+ {-# INLINE unpack #-}++-- -------------------------------------------------------------------------- -- -- Hashable (I think, this uses SIP hash) newtype HashablePkg = HashablePkg B.ByteString deriving (Show, Eq, Ord)- deriving newtype (BA.ByteArrayAccess, BA.ByteArray, Semigroup, Monoid, Hashable)+ deriving newtype (Semigroup, Monoid, Hashable, Pack) instance CuckooFilterHash HashablePkg where cuckooHash (Salt s) a = fromIntegral $! hashWithSalt s a@@ -102,11 +121,11 @@ newtype Fnv1aSip = Fnv1aSip B.ByteString deriving (Show, Eq, Ord)- deriving newtype (BA.ByteArrayAccess, BA.ByteArray, Semigroup, Monoid)+ deriving newtype (Semigroup, Monoid, Pack) instance CuckooFilterHash Fnv1aSip where- cuckooHash (Salt s) a = fnv1a_bytes s a- cuckooFingerprint (Salt s) a = sip_bytes s a+ cuckooHash (Salt s) (Fnv1aSip b) = saltedFnv1aByteString s b+ cuckooFingerprint (Salt s) (Fnv1aSip b) = saltedSipHashByteString s b {-# INLINE cuckooHash #-} {-# INLINE cuckooFingerprint #-} @@ -115,14 +134,17 @@ newtype Crypto = Crypto B.ByteString deriving (Show, Eq, Ord)- deriving newtype (BA.ByteArrayAccess, BA.ByteArray, Semigroup, Monoid)+ deriving newtype (Semigroup, Monoid, Pack) instance CuckooFilterHash Crypto where- -- cuckooHash _ a = unsafePerformIO $ BA.withByteArray (C.hash @_ @C.Blake2b_256 a) $ peek- cuckooHash (Salt s) a = unsafePerformIO $ flip BA.withByteArray peek- $ C.hash @BA.Bytes @C.Blake2b_256- $ fromRight (error "must not happen")- $ BA.fill (BA.length a + 8) (BA.putStorable s >> BA.putBytes a)+ cuckooHash (Salt s) (Crypto a) = unsafeDupablePerformIO $!+ B.unsafeUseAsCStringLen h $ \(ptr, _) -> peek (castPtr ptr)+ where+ h = C.finalize 8+ $! C.update a+ $! C.update (integralBytes s)+ $! C.initialize 8+ cuckooFingerprint s a = int $ cuckooHash (s + 23) a {-# INLINE cuckooHash #-} {-# INLINE cuckooFingerprint #-}@@ -170,13 +192,13 @@ -- | Fill up to first insert failure ---test2 :: forall a . CuckooFilterHash a => BA.ByteArray a => Natural -> IO TestResult+test2 :: forall a . Pack a => CuckooFilterHash a => Natural -> IO TestResult test2 n = do rng <- initialize 0 s <- Salt <$> uniform rng f <- newCuckooFilter @4 @10 @a s n let go i fp = do- let x = BA.pack (castEnum <$> show i)+ let x = pack (castEnum <$> show i) fp' <- bool fp (succ fp) <$> member f x insert f x >>= \case True -> go (succ i) fp'@@ -189,7 +211,7 @@ -- | Fill 90% of the filter ---test3 :: forall a . CuckooFilterHash a => BA.ByteArray a => Natural -> IO TestResult+test3 :: forall a . Pack a => CuckooFilterHash a => Natural -> IO TestResult test3 n = do rng <- initialize 0 s <- Salt <$> uniform rng@@ -197,7 +219,7 @@ let go i x fp | int i >= int @_ @Double n * 95 / 100 = return (i, x, fp) go i x fp = do- let bytes = BA.pack (castEnum <$> show i)+ let bytes = pack (castEnum <$> show i) fp' <- bool fp (succ fp) <$> member f bytes -- unless (fp == fp') $ do