    {-# LANGUAGE DeriveGeneric #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}

    {-| This module provides implementations of cryptographic utilities that only
        work for GHC (as opposed to GHCJS)
    -}

    module Dhall.Crypto (
          SHA256Digest(..)
        , sha256DigestFromByteString
        , sha256Hash
        ) where

    import Control.DeepSeq (NFData)
    import Crypto.Hash (SHA256)
    import Data.ByteArray (ByteArrayAccess, convert)
    import Data.ByteArray.Encoding (Base(Base16), convertToBase)
    import Data.ByteString (ByteString)
    import GHC.Generics (Generic)

    import qualified Crypto.Hash
    import qualified Data.ByteString.Char8 as ByteString.Char8

    -- | A SHA256 digest
    newtype SHA256Digest = SHA256Digest { SHA256Digest -> ByteString
    unSHA256Digest :: ByteString }
      deriving (SHA256Digest -> SHA256Digest -> Bool
    (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool) -> Eq SHA256Digest
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: SHA256Digest -> SHA256Digest -> Bool
    $c/= :: SHA256Digest -> SHA256Digest -> Bool
    == :: SHA256Digest -> SHA256Digest -> Bool
    $c== :: SHA256Digest -> SHA256Digest -> Bool
    Eq, (forall x. SHA256Digest -> Rep SHA256Digest x)
    -> (forall x. Rep SHA256Digest x -> SHA256Digest)
    -> Generic SHA256Digest
    forall x. Rep SHA256Digest x -> SHA256Digest
    forall x. SHA256Digest -> Rep SHA256Digest x
    forall a.
    (forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
    $cto :: forall x. Rep SHA256Digest x -> SHA256Digest
    $cfrom :: forall x. SHA256Digest -> Rep SHA256Digest x
    Generic, Eq SHA256Digest
    Eq SHA256Digest =>
    (SHA256Digest -> SHA256Digest -> Ordering)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> Bool)
    -> (SHA256Digest -> SHA256Digest -> SHA256Digest)
    -> (SHA256Digest -> SHA256Digest -> SHA256Digest)
    -> Ord SHA256Digest
    SHA256Digest -> SHA256Digest -> Bool
    SHA256Digest -> SHA256Digest -> Ordering
    SHA256Digest -> SHA256Digest -> SHA256Digest
    forall a.
    Eq a =>
    (a -> a -> Ordering)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> Bool)
    -> (a -> a -> a)
    -> (a -> a -> a)
    -> Ord a
    min :: SHA256Digest -> SHA256Digest -> SHA256Digest
    $cmin :: SHA256Digest -> SHA256Digest -> SHA256Digest
    max :: SHA256Digest -> SHA256Digest -> SHA256Digest
    $cmax :: SHA256Digest -> SHA256Digest -> SHA256Digest
    >= :: SHA256Digest -> SHA256Digest -> Bool
    $c>= :: SHA256Digest -> SHA256Digest -> Bool
    > :: SHA256Digest -> SHA256Digest -> Bool
    $c> :: SHA256Digest -> SHA256Digest -> Bool
    <= :: SHA256Digest -> SHA256Digest -> Bool
    $c<= :: SHA256Digest -> SHA256Digest -> Bool
    < :: SHA256Digest -> SHA256Digest -> Bool
    $c< :: SHA256Digest -> SHA256Digest -> Bool
    compare :: SHA256Digest -> SHA256Digest -> Ordering
    $ccompare :: SHA256Digest -> SHA256Digest -> Ordering
    $cp1Ord :: Eq SHA256Digest
    Ord, SHA256Digest -> ()
    (SHA256Digest -> ()) -> NFData SHA256Digest
    forall a. (a -> ()) -> NFData a
    rnf :: SHA256Digest -> ()
    $crnf :: SHA256Digest -> ()
    NFData, SHA256Digest -> Int
    SHA256Digest -> Ptr p -> IO ()
    SHA256Digest -> (Ptr p -> IO a) -> IO a
    (SHA256Digest -> Int)
    -> (forall p a. SHA256Digest -> (Ptr p -> IO a) -> IO a)
    -> (forall p. SHA256Digest -> Ptr p -> IO ())
    -> ByteArrayAccess SHA256Digest
    forall p. SHA256Digest -> Ptr p -> IO ()
    forall ba.
    (ba -> Int)
    -> (forall p a. ba -> (Ptr p -> IO a) -> IO a)
    -> (forall p. ba -> Ptr p -> IO ())
    -> ByteArrayAccess ba
    forall p a. SHA256Digest -> (Ptr p -> IO a) -> IO a
    copyByteArrayToPtr :: SHA256Digest -> Ptr p -> IO ()
    $ccopyByteArrayToPtr :: forall p. SHA256Digest -> Ptr p -> IO ()
    withByteArray :: SHA256Digest -> (Ptr p -> IO a) -> IO a
    $cwithByteArray :: forall p a. SHA256Digest -> (Ptr p -> IO a) -> IO a
    length :: SHA256Digest -> Int
    $clength :: SHA256Digest -> Int
    ByteArrayAccess)

    instance Show SHA256Digest where
      show :: SHA256Digest -> String
    show (SHA256Digest bytes :: ByteString
    bytes) = ByteString -> String
    ByteString.Char8.unpack (ByteString -> String) -> ByteString -> String
    forall a b. (a -> b) -> a -> b
    $ Base -> ByteString -> ByteString
    forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    Base -> bin -> bout
    convertToBase Base
    Base16 ByteString
    bytes

    {-| Attempt to interpret a `ByteString` as a `SHA256Digest`, returning
        `Nothing` if the conversion fails
    -}
    sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest
    sha256DigestFromByteString :: ByteString -> Maybe SHA256Digest
    sha256DigestFromByteString bytes :: ByteString
    bytes = ByteString -> SHA256Digest
    SHA256Digest (ByteString -> SHA256Digest)
    -> (Digest SHA256 -> ByteString) -> Digest SHA256 -> SHA256Digest
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Digest SHA256 -> ByteString
    forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    bin -> bout
    convert (Digest SHA256 -> SHA256Digest)
    -> Maybe (Digest SHA256) -> Maybe SHA256Digest
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Maybe (Digest SHA256)
    mh
      where
        mh :: Maybe (Digest SHA256)
    mh = ByteString -> Maybe (Digest SHA256)
    forall a ba.
    (HashAlgorithm a, ByteArrayAccess ba) =>
    ba -> Maybe (Digest a)
    Crypto.Hash.digestFromByteString ByteString
    bytes :: Maybe (Crypto.Hash.Digest SHA256)

    -- | Hash a `ByteString` and return the hash as a `SHA256Digest`
    sha256Hash :: ByteString -> SHA256Digest
    sha256Hash :: ByteString -> SHA256Digest
    sha256Hash bytes :: ByteString
    bytes = ByteString -> SHA256Digest
    SHA256Digest (ByteString -> SHA256Digest) -> ByteString -> SHA256Digest
    forall a b. (a -> b) -> a -> b
    $ Digest SHA256 -> ByteString
    forall bin bout.
    (ByteArrayAccess bin, ByteArray bout) =>
    bin -> bout
    convert Digest SHA256
    h
      where
        h :: Digest SHA256
    h = ByteString -> Digest SHA256
    forall ba a.
    (ByteArrayAccess ba, HashAlgorithm a) =>
    ba -> Digest a
    Crypto.Hash.hash ByteString
    bytes :: Crypto.Hash.Digest SHA256