packages feed

bloomfilter-blocked 0.1.0.0 → 0.1.0.1

raw patch · 11 files changed

+250/−228 lines, 11 filesdep ~randomPVP ok

version bump matches the API change (PVP)

Dependency ranges changed: random

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,11 @@ # Revision history for bloomfilter-blocked +## 0.1.0.1 -- 2025-11-25++* PATCH: Change source code repository to a new location.+* PATCH: Update copyright information.+* PATCH: Update the package synopsis and package description.+ ## 0.1.0.0 -- 2025-08-06  * First version. Released on an unsuspecting world.
NOTICE view
@@ -1,4 +1,5 @@ Copyright (c) 2023-2025 Cardano Development Foundation+Copyright (c) 2025 Well-Typed LLP     Licensed under the Apache License, Version 2.0 (the "License");    you may not use this file except in compliance with the License.
README.md view
@@ -1,5 +1,9 @@ # bloomfilter-blocked +[![Hackage](https://img.shields.io/hackage/v/bloomfilter-blocked?label=Hackage)](https://hackage.haskell.org/package/bloomfilter-blocked)+[![Build](https://img.shields.io/github/actions/workflow/status/well-typed/bloomfilter-blocked/ci.yml?label=Build)](https://github.com/well-typed/bloomfilter-blocked/actions/workflows/ci.yml)+[![Haddocks](https://img.shields.io/badge/documentation-Haddocks-purple)](https://well-typed.github.io/bloomfilter-blocked/)+ `bloomfilter-blocked` is a Haskell library providing multiple fast and efficient implementations of [bloom filters](https://en.wikipedia.org/wiki/Bloom_filter). It is a full rewrite of the
bloomfilter-blocked.cabal view
@@ -1,35 +1,55 @@ cabal-version:      3.4 name:               bloomfilter-blocked-version:            0.1.0.0-synopsis:           Classic and block-style bloom filters+version:            0.1.0.1+synopsis:           Fast, compact Bloom filters description:-  @bloomfilter-blocked@ is a Haskell library providing multiple fast and efficient-  implementations of [bloom filters](https://en.wikipedia.org/wiki/Bloom_filter).-  It is a full rewrite of the-  [bloomfilter](https://hackage.haskell.org/package/bloomfilter) package,-  originally authored by Bryan O'Sullivan <bos@serpentine.com>.+  This library provides [Bloom filters](https://en.wikipedia.org/wiki/Bloom_filter).+  A Bloom filter is a compact but probabilistic set-like data structure,+  supporting fast insert and membership operations. -  The library includes two implementations of bloom filters: classic, and blocked.+  Bloom filters are probabilistic in the sense that when querying for set+  membership, they can (with some probability) falsely report that an element+  is present when it is not present. On the other hand it will /never/ falsely+  report that an element is not present when in fact it is present. That is, it+  can have false positives but not false negatives. The false positive rate+  (FPR) can be adjusted. -  * /Classic/ bloom filters, found in the "Data.BloomFilter.Classic" module: a-    default implementation that is faithful to the canonical description of a-    bloom filter data structure.+  Bloom filters are compact, needing only a few /bits/ per element. For example+  10 bits per element is enough for a false positive rate (FPR) of 1%, and 15+  bits for 0.1%. -  * /Blocked/ floom filters, found in the "Data.BloomFilter.Blocked" module: an-    implementation that optimises the memory layout of a classic bloom filter for-    speed (cheaper CPU cache reads), at the cost of a slightly higher FPR for the-    same amount of assigned memory.+  The library includes two implementations of Bloom filters: +  [classic]: in "Data.BloomFilter.Classic":+    a default implementation that is faithful to the classical description of a+    Bloom filter data structure.++  [block-structured]: in "Data.BloomFilter.Blocked":+    a cache optimised representation that is faster, at the cost of needing a+    few more bits per element to achieve a target FPR.++  Features of the library:++   * Fast. See the benchmark results.+   * Compact. It uses optimal sized bit arrays: no bigger than necessary.+   * Faster still: the block-structured Bloom filters are even faster, at the+     expense of needing more bits per entry.+   * Supports very large Bloom filters, bigger than 2^32 bits.+   * Simple API for specifying the size of Bloom filters.+   * Support for hash salting, for using Bloom filters with untrusted inputs.+   * Serialisation support with format version tracking.+ license:            Apache-2.0 license-files:   LICENSE   NOTICE -author:-  Duncan Coutts, Joris Dral, Matthias Heinzel, Wolfgang Jeltsch, Wen Kokke, and Alex Washburn-+author:             Duncan Coutts, Joris Dral, Matthias Heinzel, Wen Kokke maintainer:         duncan@well-typed.com, joris@well-typed.com-copyright:          (c) 2023-2025 Cardano Development Foundation+copyright:+  (c) 2023-2025 Cardano Development Foundation+  (c) 2025 Well-Typed LLP+ category:           Data build-type:         Simple tested-with:@@ -47,14 +67,12 @@  source-repository head   type:     git-  location: https://github.com/IntersectMBO/lsm-tree-  subdir:   bloomfilter-blocked+  location: https://github.com/well-typed/bloomfilter-blocked  source-repository this   type:     git-  location: https://github.com/IntersectMBO/lsm-tree-  subdir:   bloomfilter-blocked-  tag:      bloomfilter-blocked-0.1.0.0+  location: https://github.com/well-typed/bloomfilter-blocked+  tag:      bloomfilter-blocked-0.1.0.1  common warnings   ghc-options:@@ -68,15 +86,9 @@ common language   default-language:   GHC2021   default-extensions:-    DeriveAnyClass     DerivingStrategies-    DerivingVia-    ExplicitNamespaces-    GADTs-    LambdaCase     RecordWildCards     RoleAnnotations-    ViewPatterns  library   import:          language, warnings@@ -142,10 +154,10 @@     , bloomfilter-blocked     , containers     , parallel-    , random+    , random               >=1.3     , regression-simple -  ghc-options:    -threaded+  ghc-options:    -threaded -rtsopts  -- It's not really a test suite, but if we make it an executable then its -- dependencies will be included for dependency resolution when building the@@ -161,7 +173,6 @@     , bloomfilter-blocked     , directory --- this exists due to windows library xxhash   import:          language, warnings   visibility:      private@@ -170,14 +181,14 @@     HsXXHash.h     xxhash.h -  exposed-modules: XXH3+  exposed-modules: Data.Digest.XXH3    if (arch(x86_64) && !os(osx))     -- Cabal doesn't pass cc-options to "ordinary" Haskell source compilation     -- https://github.com/haskell/cabal/issues/9801     ghc-options: -optc=-mavx2 -optc=-O3 -  other-modules:   FFI+  other-modules:   Data.Digest.XXH3.FFI   hs-source-dirs:  xxhash/src   build-depends:     , base        <5
src/Data/BloomFilter/Hash.hs view
@@ -23,9 +23,9 @@ import qualified Data.ByteString as BS import qualified Data.ByteString.Lazy as LBS import           Data.Char (ord)+import qualified Data.Digest.XXH3 as XXH3 import qualified Data.Primitive.ByteArray as P import           Data.Word (Word32, Word64)-import qualified XXH3  -- | A hash value is 64 bits wide. type Hash = Word64
tests/fpr-calc.hs view
@@ -27,12 +27,12 @@       ["Generate"] -> main_generateData       ["Regression"] -> main_regression       _   -> do-        putStrLn "Usage: bloomfilter-fpr-calc [Generate|Regression]"+        putStrLn "Usage: fpr-calc [Generate|Regression]"         exitSuccess  main_regression :: IO () main_regression = do-    s <- readFile "bloomfilter/fpr.blocked.gnuplot.data"+    s <- readFile "plots/fpr.blocked.gnuplot.data"     let parseLine l = case words l of           [w_xs_blocked, _, w_ys_blocked_actual] ->             ( read w_xs_blocked, read w_ys_blocked_actual )@@ -55,7 +55,7 @@  main_generateData :: IO () main_generateData = do-    withFile "bloomfilter/fpr.classic.gnuplot.data" WriteMode $ \h -> do+    withFile "plots/fpr.classic.gnuplot.data" WriteMode $ \h -> do       hSetBuffering h LineBuffering --for incremental output       mapM_ (\l -> hPutStrLn h l >> putChar '.') $         [ unwords [show bitsperkey, show y1, show y2]@@ -63,9 +63,9 @@         | y1              <- ys_classic_calc         | y2              <- ys_classic_actual         ]-    putStrLn "Wrote bloomfilter/fpr.classic.gnuplot.data"+    putStrLn "Wrote plots/fpr.classic.gnuplot.data" -    withFile "bloomfilter/fpr.blocked.gnuplot.data" WriteMode $ \h -> do+    withFile "plots/fpr.blocked.gnuplot.data" WriteMode $ \h -> do       hSetBuffering h LineBuffering --for incremental output       mapM_ (\l -> hPutStrLn h l >> putChar '.') $         [ unwords [show bitsperkey, show y1, show y2]@@ -73,7 +73,7 @@         | y1              <- ys_blocked_calc         | y2              <- ys_blocked_actual         ]-    putStrLn "Wrote bloomfilter/fpr.blocked.gnuplot.data"+    putStrLn "Wrote plots/fpr.blocked.gnuplot.data"   where     -- x axis values     xs_classic =
+ xxhash/src/Data/Digest/XXH3.hs view
@@ -0,0 +1,110 @@+{-# LANGUAGE CPP       #-}+{-# LANGUAGE MagicHash #-}++module Data.Digest.XXH3 (+    -- * One shot+    xxh3_64bit_withSeed_bs,+    xxh3_64bit_withSeed_ba,+    xxh3_64bit_withSeed_w64,+    xxh3_64bit_withSeed_w32,+    -- * Incremental+    XXH3_State,+    xxh3_64bit_createState,+    xxh3_64bit_reset_withSeed,+    xxh3_64bit_digest,+    xxh3_64bit_update_bs,+    xxh3_64bit_update_ba,+    xxh3_64bit_update_w64,+    xxh3_64bit_update_w32,+) where++import           Control.Monad.ST (ST)+import           Control.Monad.ST.Unsafe (unsafeIOToST)+import           Data.ByteString.Internal (ByteString (..),+                     accursedUnutterablePerformIO)+import qualified Data.Primitive as P+import           Data.Primitive.ByteArray (ByteArray (..))+import           Data.Word (Word32, Word64)+import           Foreign.ForeignPtr+import           GHC.Exts (MutableByteArray#)+import           GHC.ForeignPtr++import           Data.Digest.XXH3.FFI++{-# INLINE withFP #-}+withFP :: ForeignPtr a -> (P.Ptr a -> IO b) -> IO b+withFP = unsafeWithForeignPtr++-------------------------------------------------------------------------------+-- OneShot+-------------------------------------------------------------------------------++-- | Hash 'ByteString'.+xxh3_64bit_withSeed_bs :: ByteString -> Word64 -> Word64+xxh3_64bit_withSeed_bs (BS fptr len) !salt = accursedUnutterablePerformIO $+    withFP fptr $ \ptr ->+    unsafe_xxh3_64bit_withSeed_ptr ptr (fromIntegral len) salt++-- | Hash (part of) 'ByteArray'.+xxh3_64bit_withSeed_ba :: ByteArray -> Int -> Int -> Word64 -> Word64+xxh3_64bit_withSeed_ba (ByteArray ba) !off !len !salt =+    unsafe_xxh3_64bit_withSeed_ba ba (fromIntegral off) (fromIntegral len) salt++-- | Hash 'Word64'.+xxh3_64bit_withSeed_w64 :: Word64 -> Word64 -> Word64+xxh3_64bit_withSeed_w64 !x !salt =+    unsafe_xxh3_64bit_withSeed_u64 x salt++-- | Hash 'Word32'.+xxh3_64bit_withSeed_w32 :: Word32 -> Word64 -> Word64+xxh3_64bit_withSeed_w32 !x !salt =+    unsafe_xxh3_64bit_withSeed_u32 x salt++-------------------------------------------------------------------------------+-- Incremental+-------------------------------------------------------------------------------++-- | Mutable XXH3 state.+data XXH3_State s = XXH3 (MutableByteArray# s)++-- | Create 'XXH3_State'.+xxh3_64bit_createState :: forall s. ST s (XXH3_State s)+xxh3_64bit_createState = do+    -- aligned alloc, otherwise we get segfaults.+    -- see XXH3_createState implementation+    P.MutableByteArray ba <- P.newAlignedPinnedByteArray unsafe_xxh3_sizeof_state 64+    unsafeIOToST (unsafe_xxh3_initState ba)+    pure (XXH3 ba)++-- | Reset 'XXH3_State' with a seed.+xxh3_64bit_reset_withSeed :: XXH3_State s -> Word64 -> ST s ()+xxh3_64bit_reset_withSeed (XXH3 s) seed = do+    unsafeIOToST (unsafe_xxh3_64bit_reset_withSeed s seed)++-- | Return a hash value from a 'XXH3_State'.+--+-- Doesn't mutate given state, so you can update, digest and update again.+xxh3_64bit_digest :: XXH3_State s -> ST s Word64+xxh3_64bit_digest (XXH3 s) =+    unsafeIOToST (unsafe_xxh3_64bit_digest s)++-- | Update 'XXH3_State' with 'ByteString'.+xxh3_64bit_update_bs :: XXH3_State s -> ByteString -> ST s ()+xxh3_64bit_update_bs (XXH3 s) (BS fptr len) = unsafeIOToST $+    withFP fptr $ \ptr ->+    unsafe_xxh3_64bit_update_ptr s ptr (fromIntegral len)++-- | Update 'XXH3_State' with (part of) 'ByteArray'+xxh3_64bit_update_ba :: XXH3_State s -> ByteArray -> Int -> Int -> ST s ()+xxh3_64bit_update_ba (XXH3 s) (ByteArray ba) !off !len = unsafeIOToST $+    unsafe_xxh3_64bit_update_ba s ba (fromIntegral off) (fromIntegral len)++-- | Update 'XXH3_State' with 'Word64'.+xxh3_64bit_update_w64 :: XXH3_State s -> Word64 -> ST s ()+xxh3_64bit_update_w64 (XXH3 s) w64 = unsafeIOToST $+    unsafe_xxh3_64bit_update_u64 s w64++-- | Update 'XXH3_State' with 'Word32'.+xxh3_64bit_update_w32 :: XXH3_State s -> Word32 -> ST s ()+xxh3_64bit_update_w32 (XXH3 s) w32 = unsafeIOToST $+    unsafe_xxh3_64bit_update_u32 s w32
+ xxhash/src/Data/Digest/XXH3/FFI.hs view
@@ -0,0 +1,75 @@+{-# LANGUAGE CApiFFI          #-}+{-# LANGUAGE MagicHash        #-}+{-# LANGUAGE UnliftedFFITypes #-}+module Data.Digest.XXH3.FFI (+    -- * One shot+    unsafe_xxh3_64bit_withSeed_ptr,+    unsafe_xxh3_64bit_withSeed_ba,+    unsafe_xxh3_64bit_withSeed_u64,+    unsafe_xxh3_64bit_withSeed_u32,+    -- * Incremental+    unsafe_xxh3_sizeof_state,+    unsafe_xxh3_initState,+    unsafe_xxh3_64bit_reset_withSeed,+    unsafe_xxh3_64bit_digest,+    unsafe_xxh3_64bit_update_ptr,+    unsafe_xxh3_64bit_update_ba,+    unsafe_xxh3_64bit_update_u64,+    unsafe_xxh3_64bit_update_u32,+) where++import           Data.Word (Word32, Word64, Word8)+import           Foreign.C.Types (CSize (..))+import           Foreign.Ptr (Ptr)+import           GHC.Exts (ByteArray#, MutableByteArray#)++-- Note: we use unsafe FFI calls, as we expect our use case to be hashing only small data (<1kb, at most 4k).++-------------------------------------------------------------------------------+-- OneShot+-------------------------------------------------------------------------------++foreign import capi unsafe "HsXXHash.h XXH3_64bits_withSeed"+    unsafe_xxh3_64bit_withSeed_ptr :: Ptr Word8 -> CSize -> Word64 -> IO Word64++foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_offset"+    unsafe_xxh3_64bit_withSeed_ba :: ByteArray# -> CSize -> CSize -> Word64 -> Word64++foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_u64"+    unsafe_xxh3_64bit_withSeed_u64 :: Word64 -> Word64 -> Word64++foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_u32"+    unsafe_xxh3_64bit_withSeed_u32 :: Word32 -> Word64 -> Word64++-------------------------------------------------------------------------------+-- Incremental+-------------------------------------------------------------------------------++-- reset and update functions return OK/Error+-- we ignore that:+-- * reset errors only on NULL state+-- * update cannot even error++foreign import capi unsafe "HsXXHash.h value hs_XXH3_sizeof_state_s"+    unsafe_xxh3_sizeof_state :: Int++foreign import capi unsafe "HsXXHash.h XXH3_INITSTATE"+    unsafe_xxh3_initState :: MutableByteArray# s -> IO ()++foreign import capi unsafe "HsXXHash.h XXH3_64bits_reset_withSeed"+    unsafe_xxh3_64bit_reset_withSeed :: MutableByteArray# s -> Word64 -> IO ()++foreign import capi unsafe "HsXXHash.h XXH3_64bits_digest"+    unsafe_xxh3_64bit_digest :: MutableByteArray# s -> IO Word64++foreign import capi unsafe "HsXXHash.h XXH3_64bits_update"+    unsafe_xxh3_64bit_update_ptr :: MutableByteArray# s -> Ptr Word8 -> CSize -> IO ()++foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_offset"+    unsafe_xxh3_64bit_update_ba :: MutableByteArray# s -> ByteArray# -> CSize -> CSize -> IO ()++foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_u64"+    unsafe_xxh3_64bit_update_u64 :: MutableByteArray# s -> Word64 -> IO ()++foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_u32"+    unsafe_xxh3_64bit_update_u32 :: MutableByteArray# s -> Word32 -> IO ()
− xxhash/src/FFI.hs
@@ -1,75 +0,0 @@-{-# LANGUAGE CApiFFI          #-}-{-# LANGUAGE MagicHash        #-}-{-# LANGUAGE UnliftedFFITypes #-}-module FFI (-    -- * One shot-    unsafe_xxh3_64bit_withSeed_ptr,-    unsafe_xxh3_64bit_withSeed_ba,-    unsafe_xxh3_64bit_withSeed_u64,-    unsafe_xxh3_64bit_withSeed_u32,-    -- * Incremental-    unsafe_xxh3_sizeof_state,-    unsafe_xxh3_initState,-    unsafe_xxh3_64bit_reset_withSeed,-    unsafe_xxh3_64bit_digest,-    unsafe_xxh3_64bit_update_ptr,-    unsafe_xxh3_64bit_update_ba,-    unsafe_xxh3_64bit_update_u64,-    unsafe_xxh3_64bit_update_u32,-) where--import           Data.Word (Word32, Word64, Word8)-import           Foreign.C.Types (CSize (..))-import           Foreign.Ptr (Ptr)-import           GHC.Exts (ByteArray#, MutableByteArray#)---- Note: we use unsafe FFI calls, as we expect our use case to be hashing only small data (<1kb, at most 4k).------------------------------------------------------------------------------------ OneShot----------------------------------------------------------------------------------foreign import capi unsafe "HsXXHash.h XXH3_64bits_withSeed"-    unsafe_xxh3_64bit_withSeed_ptr :: Ptr Word8 -> CSize -> Word64 -> IO Word64--foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_offset"-    unsafe_xxh3_64bit_withSeed_ba :: ByteArray# -> CSize -> CSize -> Word64 -> Word64--foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_u64"-    unsafe_xxh3_64bit_withSeed_u64 :: Word64 -> Word64 -> Word64--foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_withSeed_u32"-    unsafe_xxh3_64bit_withSeed_u32 :: Word32 -> Word64 -> Word64------------------------------------------------------------------------------------ Incremental------------------------------------------------------------------------------------ reset and update functions return OK/Error--- we ignore that:--- * reset errors only on NULL state--- * update cannot even error--foreign import capi unsafe "HsXXHash.h value hs_XXH3_sizeof_state_s"-    unsafe_xxh3_sizeof_state :: Int--foreign import capi unsafe "HsXXHash.h XXH3_INITSTATE"-    unsafe_xxh3_initState :: MutableByteArray# s -> IO ()--foreign import capi unsafe "HsXXHash.h XXH3_64bits_reset_withSeed"-    unsafe_xxh3_64bit_reset_withSeed :: MutableByteArray# s -> Word64 -> IO ()--foreign import capi unsafe "HsXXHash.h XXH3_64bits_digest"-    unsafe_xxh3_64bit_digest :: MutableByteArray# s -> IO Word64--foreign import capi unsafe "HsXXHash.h XXH3_64bits_update"-    unsafe_xxh3_64bit_update_ptr :: MutableByteArray# s -> Ptr Word8 -> CSize -> IO ()--foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_offset"-    unsafe_xxh3_64bit_update_ba :: MutableByteArray# s -> ByteArray# -> CSize -> CSize -> IO ()--foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_u64"-    unsafe_xxh3_64bit_update_u64 :: MutableByteArray# s -> Word64 -> IO ()--foreign import capi unsafe "HsXXHash.h hs_XXH3_64bits_update_u32"-    unsafe_xxh3_64bit_update_u32 :: MutableByteArray# s -> Word32 -> IO ()
− xxhash/src/XXH3.hs
@@ -1,110 +0,0 @@-{-# LANGUAGE CPP       #-}-{-# LANGUAGE MagicHash #-}--module XXH3 (-    -- * One shot-    xxh3_64bit_withSeed_bs,-    xxh3_64bit_withSeed_ba,-    xxh3_64bit_withSeed_w64,-    xxh3_64bit_withSeed_w32,-    -- * Incremental-    XXH3_State,-    xxh3_64bit_createState,-    xxh3_64bit_reset_withSeed,-    xxh3_64bit_digest,-    xxh3_64bit_update_bs,-    xxh3_64bit_update_ba,-    xxh3_64bit_update_w64,-    xxh3_64bit_update_w32,-) where--import           Control.Monad.ST (ST)-import           Control.Monad.ST.Unsafe (unsafeIOToST)-import           Data.ByteString.Internal (ByteString (..),-                     accursedUnutterablePerformIO)-import qualified Data.Primitive as P-import           Data.Primitive.ByteArray (ByteArray (..))-import           Data.Word (Word32, Word64)-import           Foreign.ForeignPtr-import           GHC.Exts (MutableByteArray#)-import           GHC.ForeignPtr--import           FFI--{-# INLINE withFP #-}-withFP :: ForeignPtr a -> (P.Ptr a -> IO b) -> IO b-withFP = unsafeWithForeignPtr------------------------------------------------------------------------------------ OneShot------------------------------------------------------------------------------------ | Hash 'ByteString'.-xxh3_64bit_withSeed_bs :: ByteString -> Word64 -> Word64-xxh3_64bit_withSeed_bs (BS fptr len) !salt = accursedUnutterablePerformIO $-    withFP fptr $ \ptr ->-    unsafe_xxh3_64bit_withSeed_ptr ptr (fromIntegral len) salt---- | Hash (part of) 'ByteArray'.-xxh3_64bit_withSeed_ba :: ByteArray -> Int -> Int -> Word64 -> Word64-xxh3_64bit_withSeed_ba (ByteArray ba) !off !len !salt =-    unsafe_xxh3_64bit_withSeed_ba ba (fromIntegral off) (fromIntegral len) salt---- | Hash 'Word64'.-xxh3_64bit_withSeed_w64 :: Word64 -> Word64 -> Word64-xxh3_64bit_withSeed_w64 !x !salt =-    unsafe_xxh3_64bit_withSeed_u64 x salt---- | Hash 'Word32'.-xxh3_64bit_withSeed_w32 :: Word32 -> Word64 -> Word64-xxh3_64bit_withSeed_w32 !x !salt =-    unsafe_xxh3_64bit_withSeed_u32 x salt------------------------------------------------------------------------------------ Incremental------------------------------------------------------------------------------------ | Mutable XXH3 state.-data XXH3_State s = XXH3 (MutableByteArray# s)---- | Create 'XXH3_State'.-xxh3_64bit_createState :: forall s. ST s (XXH3_State s)-xxh3_64bit_createState = do-    -- aligned alloc, otherwise we get segfaults.-    -- see XXH3_createState implementation-    P.MutableByteArray ba <- P.newAlignedPinnedByteArray unsafe_xxh3_sizeof_state 64-    unsafeIOToST (unsafe_xxh3_initState ba)-    pure (XXH3 ba)---- | Reset 'XXH3_State' with a seed.-xxh3_64bit_reset_withSeed :: XXH3_State s -> Word64 -> ST s ()-xxh3_64bit_reset_withSeed (XXH3 s) seed = do-    unsafeIOToST (unsafe_xxh3_64bit_reset_withSeed s seed)---- | Return a hash value from a 'XXH3_State'.------ Doesn't mutate given state, so you can update, digest and update again.-xxh3_64bit_digest :: XXH3_State s -> ST s Word64-xxh3_64bit_digest (XXH3 s) =-    unsafeIOToST (unsafe_xxh3_64bit_digest s)---- | Update 'XXH3_State' with 'ByteString'.-xxh3_64bit_update_bs :: XXH3_State s -> ByteString -> ST s ()-xxh3_64bit_update_bs (XXH3 s) (BS fptr len) = unsafeIOToST $-    withFP fptr $ \ptr ->-    unsafe_xxh3_64bit_update_ptr s ptr (fromIntegral len)---- | Update 'XXH3_State' with (part of) 'ByteArray'-xxh3_64bit_update_ba :: XXH3_State s -> ByteArray -> Int -> Int -> ST s ()-xxh3_64bit_update_ba (XXH3 s) (ByteArray ba) !off !len = unsafeIOToST $-    unsafe_xxh3_64bit_update_ba s ba (fromIntegral off) (fromIntegral len)---- | Update 'XXH3_State' with 'Word64'.-xxh3_64bit_update_w64 :: XXH3_State s -> Word64 -> ST s ()-xxh3_64bit_update_w64 (XXH3 s) w64 = unsafeIOToST $-    unsafe_xxh3_64bit_update_u64 s w64---- | Update 'XXH3_State' with 'Word32'.-xxh3_64bit_update_w32 :: XXH3_State s -> Word32 -> ST s ()-xxh3_64bit_update_w32 (XXH3 s) w32 = unsafeIOToST $-    unsafe_xxh3_64bit_update_u32 s w32
xxhash/tests/xxhash-tests.hs view
@@ -9,7 +9,7 @@ import           Test.Tasty.HUnit (testCase, (@=?)) import           Test.Tasty.QuickCheck (testProperty, (===)) -import           XXH3+import           Data.Digest.XXH3  main :: IO () main = defaultMain $ testGroup "xxhash"