Distribution/Utils/MD5.hs

    module Distribution.Utils.MD5 (
        MD5,
        showMD5,
        md5,
        -- * Binary
        binaryPutMD5,
        binaryGetMD5,
        ) where

    import Data.Binary      (Get, Put)
    import Data.Binary.Get  (getWord64le)
    import Data.Binary.Put  (putWord64le)
    import Foreign.Ptr      (castPtr)
    import GHC.Fingerprint  (Fingerprint (..), fingerprintData)
    import Numeric          (showHex)
    import System.IO.Unsafe (unsafeDupablePerformIO)

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

    type MD5 = Fingerprint

    -- | Show 'MD5' in human readable form
    --
    -- >>> showMD5 (Fingerprint 123 456)
    -- "000000000000007b00000000000001c8"
    --
    -- >>> showMD5 $ md5 $ BS.pack [0..127]
    -- "37eff01866ba3f538421b30b7cbefcac"
    --
    -- @since  3.2.0.0
    showMD5 :: MD5 -> String
    showMD5 (Fingerprint a b) = pad a' ++ pad b' where
        a' = showHex a ""
        b' = showHex b ""
        pad s = replicate (16 - length s) '0' ++ s

    -- | @since  3.2.0.0
    md5 :: BS.ByteString -> MD5
    md5 bs = unsafeDupablePerformIO $ BS.unsafeUseAsCStringLen bs $ \(ptr, len) ->
        fingerprintData (castPtr ptr) len

    -- | @since  3.2.0.0
    binaryPutMD5 :: MD5 -> Put
    binaryPutMD5 (Fingerprint a b) = do
        putWord64le a
        putWord64le b

    -- | @since  3.2.0.0
    binaryGetMD5 :: Get MD5
    binaryGetMD5 = do
        a <- getWord64le
        b <- getWord64le
        return (Fingerprint a b)