    -- |
    -- Module      :  Cryptol.ModuleSystem.Fingerprint
    -- Copyright   :  (c) 2019 Galois, Inc.
    -- License     :  BSD3
    -- Maintainer  :  cryptol@galois.com
    -- Stability   :  provisional
    -- Portability :  portable

    module Cryptol.ModuleSystem.Fingerprint
      ( Fingerprint
      , fingerprint
      , fingerprintFile
      ) where

    import Control.DeepSeq          (NFData (rnf))
    import Crypto.Hash.SHA1         (hash)
    import Data.ByteString          (ByteString)
    import System.IO.Error          (IOError)
    import Control.Exception        (try)
    import qualified Data.ByteString as B

    newtype Fingerprint = Fingerprint ByteString
      deriving (Fingerprint -> Fingerprint -> Bool
    (Fingerprint -> Fingerprint -> Bool)
    -> (Fingerprint -> Fingerprint -> Bool) -> Eq Fingerprint
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: Fingerprint -> Fingerprint -> Bool
    $c/= :: Fingerprint -> Fingerprint -> Bool
    == :: Fingerprint -> Fingerprint -> Bool
    $c== :: Fingerprint -> Fingerprint -> Bool
    Eq, Int -> Fingerprint -> ShowS
    [Fingerprint] -> ShowS
    Fingerprint -> String
    (Int -> Fingerprint -> ShowS)
    -> (Fingerprint -> String)
    -> ([Fingerprint] -> ShowS)
    -> Show Fingerprint
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    showList :: [Fingerprint] -> ShowS
    $cshowList :: [Fingerprint] -> ShowS
    show :: Fingerprint -> String
    $cshow :: Fingerprint -> String
    showsPrec :: Int -> Fingerprint -> ShowS
    $cshowsPrec :: Int -> Fingerprint -> ShowS
    Show)

    instance NFData Fingerprint where
      rnf :: Fingerprint -> ()
    rnf (Fingerprint fp :: ByteString
    fp) = ByteString -> ()
    forall a. NFData a => a -> ()
    rnf ByteString
    fp

    -- | Compute a fingerprint for a bytestring.
    fingerprint :: ByteString -> Fingerprint
    fingerprint :: ByteString -> Fingerprint
    fingerprint = ByteString -> Fingerprint
    Fingerprint (ByteString -> Fingerprint)
    -> (ByteString -> ByteString) -> ByteString -> Fingerprint
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> ByteString
    hash

    -- | Attempt to compute the fingerprint of the file at the given path.
    -- Returns 'Nothing' in the case of an error.
    fingerprintFile :: FilePath -> IO (Maybe Fingerprint)
    fingerprintFile :: String -> IO (Maybe Fingerprint)
    fingerprintFile path :: String
    path =
      do Either IOError ByteString
    res <- IO ByteString -> IO (Either IOError ByteString)
    forall e a. Exception e => IO a -> IO (Either e a)
    try (String -> IO ByteString
    B.readFile String
    path)
         Maybe Fingerprint -> IO (Maybe Fingerprint)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Fingerprint -> IO (Maybe Fingerprint))
    -> Maybe Fingerprint -> IO (Maybe Fingerprint)
    forall a b. (a -> b) -> a -> b
    $!
           case Either IOError ByteString
    res :: Either IOError ByteString of
             Left{}  -> Maybe Fingerprint
    forall a. Maybe a
    Nothing
             Right b :: ByteString
    b -> Fingerprint -> Maybe Fingerprint
    forall a. a -> Maybe a
    Just (Fingerprint -> Maybe Fingerprint)
    -> Fingerprint -> Maybe Fingerprint
    forall a b. (a -> b) -> a -> b
    $! ByteString -> Fingerprint
    fingerprint ByteString
    b