{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}

-- ----------------------------------------------------------------------------
--
--  (c) The University of Glasgow 2006
--
-- Fingerprints for recompilation checking and ABI versioning.
--
-- https://gitlab.haskell.org/ghc/ghc/wikis/commentary/compiler/recompilation-avoidance
--
-- ----------------------------------------------------------------------------

module GHC.Utils.Fingerprint (
        readHexFingerprint,
        fingerprintByteString,
        -- * Re-exported from GHC.Fingerprint
        Fingerprint(..), fingerprint0,
        fingerprintFingerprints,
        fingerprintData,
        fingerprintString,
        fingerprintStrings,
        getFileHash
   ) where

import GHC.Prelude.Basic

import Foreign
import GHC.IO
import Numeric          ( readHex )

import qualified Data.ByteString as BS
import qualified Data.ByteString.Unsafe as BS

import GHC.Fingerprint

-- useful for parsing the output of 'md5sum', should we want to do that.
readHexFingerprint :: String -> Fingerprint
readHexFingerprint :: String -> Fingerprint
readHexFingerprint String
s = Word64 -> Word64 -> Fingerprint
Fingerprint Word64
w1 Word64
w2
 where (String
s1,String
s2) = Int -> String -> (String, String)
forall a. Int -> [a] -> ([a], [a])
splitAt Int
16 String
s
       [(Word64
w1,String
"")] = ReadS Word64
forall a. (Eq a, Num a) => ReadS a
readHex String
s1
       [(Word64
w2,String
"")] = ReadS Word64
forall a. (Eq a, Num a) => ReadS a
readHex (Int -> String -> String
forall a. Int -> [a] -> [a]
take Int
16 String
s2)

fingerprintByteString :: BS.ByteString -> Fingerprint
fingerprintByteString :: ByteString -> Fingerprint
fingerprintByteString ByteString
bs = IO Fingerprint -> Fingerprint
forall a. IO a -> a
unsafeDupablePerformIO (IO Fingerprint -> Fingerprint) -> IO Fingerprint -> Fingerprint
forall a b. (a -> b) -> a -> b
$
  ByteString -> (CStringLen -> IO Fingerprint) -> IO Fingerprint
forall a. ByteString -> (CStringLen -> IO a) -> IO a
BS.unsafeUseAsCStringLen ByteString
bs ((CStringLen -> IO Fingerprint) -> IO Fingerprint)
-> (CStringLen -> IO Fingerprint) -> IO Fingerprint
forall a b. (a -> b) -> a -> b
$ \(Ptr CChar
ptr, Int
len) -> Ptr Word8 -> Int -> IO Fingerprint
fingerprintData (Ptr CChar -> Ptr Word8
forall a b. Ptr a -> Ptr b
castPtr Ptr CChar
ptr) Int
len

-- See Note [Repeated -optP hashing]
fingerprintStrings :: [String] -> Fingerprint
fingerprintStrings :: [String] -> Fingerprint
fingerprintStrings [String]
ss = [Fingerprint] -> Fingerprint
fingerprintFingerprints ([Fingerprint] -> Fingerprint) -> [Fingerprint] -> Fingerprint
forall a b. (a -> b) -> a -> b
$ (String -> Fingerprint) -> [String] -> [Fingerprint]
forall a b. (a -> b) -> [a] -> [b]
map String -> Fingerprint
fingerprintString [String]
ss