glean-0.2.0.0: glean/angle/Glean/Angle/Hash.hs
{-
Copyright (c) Meta Platforms, Inc. and affiliates.
All rights reserved.
This source code is licensed under the BSD-style license found in the
LICENSE file in the root directory of this source tree.
-}
-- | Fingerprints for schema versioning.
--
-- Doesn't need to be cryptographically secure, but does need to be
-- robust against accidental collisions.
module Glean.Angle.Hash
( Hash
, hash0
, hashString
, hashByteString
, hashBinary
, hashFingerprint
) where
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as LB
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.Binary (Binary)
import qualified Data.Binary as Binary
import Data.Hashable
import Foreign (castPtr)
import GHC.Fingerprint as GHC
import System.IO.Unsafe ( unsafeDupablePerformIO )
-- efficient MD5 hash
type Hash = GHC.Fingerprint
hash0 :: Hash
hash0 = GHC.fingerprint0
hashString :: String -> Hash
hashString = GHC.fingerprintString
hashByteString :: B.ByteString -> Hash
hashByteString bs = unsafeDupablePerformIO $ do
unsafeUseAsCStringLen bs $ \(ptr, len) ->
GHC.fingerprintData (castPtr ptr) (fromIntegral len)
hashBinary :: Binary a => a -> Hash
hashBinary = hashByteString . LB.toStrict . Binary.encode
-- | For building Hashable instances. Avoiding an orphan instance by
-- making this a function instead.
hashFingerprint :: Int -> Hash -> Int
hashFingerprint salt (GHC.Fingerprint _ w) = hashWithSalt salt w