web3-crypto-1.0.0.0: src/Data/Digest/XXHash.hsc
{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
-- |
-- Module : Data.Digest.XXHash
-- Copyright : Aleksandr Krupenkin 2016-2021
-- License : Apache-2.0
--
-- Maintainer : mail@akru.me
-- Stability : experimental
-- Portability : unportable
--
-- xxHash C library bindings.
--
-- Variable bitLength implementation corresponds to polkadot-util:
-- https://github.com/polkadot-js/common/tree/master/packages/util-crypto/src/xxhash
--
module Data.Digest.XXHash (xxhash) where
import Data.ByteString (ByteString, useAsCStringLen)
import Data.ByteString.Builder (toLazyByteString, word64LE)
import Data.ByteString.Lazy (toStrict)
import Foreign
import Foreign.C.String
import Foreign.C.Types
import System.IO.Unsafe (unsafePerformIO)
#include <xxhash.h>
foreign import ccall unsafe "xxhash.h XXH64"
c_XXH64 :: CString -> CSize -> CUInt -> IO Word64
xxhash_64 :: CUInt -> ByteString -> Word64
xxhash_64 seed = unsafePerformIO . flip useAsCStringLen
(\(str, len) -> c_XXH64 str (fromIntegral len) seed)
-- | Create the xxhash64 and return the result with the specified 'bitLength'.
xxhash :: Integral bitLength
=> bitLength
-- ^ Bit lenght of output, will be ceiling to 64 bit.
-> ByteString
-- ^ Input data.
-> ByteString
-- ^ Output hash.
xxhash bitLength input = toStrict . toLazyByteString $ mconcat
[ word64LE (xxhash_64 seed input) | seed <- [0 .. (iterations - 1)]]
where
iterations = ceiling (fromIntegral bitLength / 64)