    {-# LANGUAGE CPP                        #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE TypeFamilies               #-}
    {-# LANGUAGE FlexibleInstances          #-}
    {-# LANGUAGE MultiParamTypeClasses      #-}
    {-# LANGUAGE DataKinds                  #-}
    {-# CFILES raaz/hash/sha1/portable.c    #-}

    -- | Internals of Sha512.
    module Raaz.Hash.Sha512.Internal (SHA512(..)) where

    import           Data.String
    import           Data.Word
    import           Foreign.Storable    ( Storable(..) )

    import           Raaz.Core

    import           Raaz.Hash.Internal

    ----------------------------- SHA512 ---------------------------------

    -- | The Sha512 hash value. Used in implementation of Sha384 as well.
    newtype SHA512 = SHA512 (Tuple 8 (BE Word64))
                   deriving (SHA512 -> SHA512 -> Bool
    (SHA512 -> SHA512 -> Bool)
    -> (SHA512 -> SHA512 -> Bool) -> Eq SHA512
    forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
    /= :: SHA512 -> SHA512 -> Bool
    $c/= :: SHA512 -> SHA512 -> Bool
    == :: SHA512 -> SHA512 -> Bool
    $c== :: SHA512 -> SHA512 -> Bool
    Eq, SHA512 -> SHA512 -> Result
    (SHA512 -> SHA512 -> Result) -> Equality SHA512
    forall a. (a -> a -> Result) -> Equality a
    eq :: SHA512 -> SHA512 -> Result
    $ceq :: SHA512 -> SHA512 -> Result
    Equality, Ptr b -> Int -> IO SHA512
    Ptr b -> Int -> SHA512 -> IO ()
    Ptr SHA512 -> IO SHA512
    Ptr SHA512 -> Int -> IO SHA512
    Ptr SHA512 -> Int -> SHA512 -> IO ()
    Ptr SHA512 -> SHA512 -> IO ()
    SHA512 -> Int
    (SHA512 -> Int)
    -> (SHA512 -> Int)
    -> (Ptr SHA512 -> Int -> IO SHA512)
    -> (Ptr SHA512 -> Int -> SHA512 -> IO ())
    -> (forall b. Ptr b -> Int -> IO SHA512)
    -> (forall b. Ptr b -> Int -> SHA512 -> IO ())
    -> (Ptr SHA512 -> IO SHA512)
    -> (Ptr SHA512 -> SHA512 -> IO ())
    -> Storable SHA512
    forall b. Ptr b -> Int -> IO SHA512
    forall b. Ptr b -> Int -> SHA512 -> IO ()
    forall a.
    (a -> Int)
    -> (a -> Int)
    -> (Ptr a -> Int -> IO a)
    -> (Ptr a -> Int -> a -> IO ())
    -> (forall b. Ptr b -> Int -> IO a)
    -> (forall b. Ptr b -> Int -> a -> IO ())
    -> (Ptr a -> IO a)
    -> (Ptr a -> a -> IO ())
    -> Storable a
    poke :: Ptr SHA512 -> SHA512 -> IO ()
    $cpoke :: Ptr SHA512 -> SHA512 -> IO ()
    peek :: Ptr SHA512 -> IO SHA512
    $cpeek :: Ptr SHA512 -> IO SHA512
    pokeByteOff :: Ptr b -> Int -> SHA512 -> IO ()
    $cpokeByteOff :: forall b. Ptr b -> Int -> SHA512 -> IO ()
    peekByteOff :: Ptr b -> Int -> IO SHA512
    $cpeekByteOff :: forall b. Ptr b -> Int -> IO SHA512
    pokeElemOff :: Ptr SHA512 -> Int -> SHA512 -> IO ()
    $cpokeElemOff :: Ptr SHA512 -> Int -> SHA512 -> IO ()
    peekElemOff :: Ptr SHA512 -> Int -> IO SHA512
    $cpeekElemOff :: Ptr SHA512 -> Int -> IO SHA512
    alignment :: SHA512 -> Int
    $calignment :: SHA512 -> Int
    sizeOf :: SHA512 -> Int
    $csizeOf :: SHA512 -> Int
    Storable, Storable SHA512
    Ptr SHA512 -> IO SHA512
    Ptr SHA512 -> Int -> IO ()
    Ptr SHA512 -> SHA512 -> IO ()
    Storable SHA512 =>
    (Ptr SHA512 -> SHA512 -> IO ())
    -> (Ptr SHA512 -> IO SHA512)
    -> (Ptr SHA512 -> Int -> IO ())
    -> EndianStore SHA512
    forall w.
    Storable w =>
    (Ptr w -> w -> IO ())
    -> (Ptr w -> IO w) -> (Ptr w -> Int -> IO ()) -> EndianStore w
    adjustEndian :: Ptr SHA512 -> Int -> IO ()
    $cadjustEndian :: Ptr SHA512 -> Int -> IO ()
    load :: Ptr SHA512 -> IO SHA512
    $cload :: Ptr SHA512 -> IO SHA512
    store :: Ptr SHA512 -> SHA512 -> IO ()
    $cstore :: Ptr SHA512 -> SHA512 -> IO ()
    $cp1EndianStore :: Storable SHA512
    EndianStore)

    instance Encodable SHA512

    instance IsString SHA512 where
      fromString :: String -> SHA512
    fromString = String -> SHA512
    forall a. Encodable a => String -> a
    fromBase16

    instance Show SHA512 where
      show :: SHA512 -> String
    show =  SHA512 -> String
    forall a. Encodable a => a -> String
    showBase16

    instance Primitive SHA512 where
      blockSize :: SHA512 -> BYTES Int
    blockSize _ = Int -> BYTES Int
    forall a. a -> BYTES a
    BYTES 128
      type Implementation SHA512 = SomeHashI SHA512

    instance Initialisable (HashMemory SHA512) () where
      initialise :: () -> MT (HashMemory SHA512) ()
    initialise _ = SHA512 -> MT (HashMemory SHA512) ()
    forall m v. Initialisable m v => v -> MT m ()
    initialise (SHA512 -> MT (HashMemory SHA512) ())
    -> SHA512 -> MT (HashMemory SHA512) ()
    forall a b. (a -> b) -> a -> b
    $ Tuple 8 (BE Word64) -> SHA512
    SHA512
                     (Tuple 8 (BE Word64) -> SHA512) -> Tuple 8 (BE Word64) -> SHA512
    forall a b. (a -> b) -> a -> b
    $ [BE Word64] -> Tuple 8 (BE Word64)
    forall a (dim :: Nat).
    (Unbox a, Dimension dim) =>
    [a] -> Tuple dim a
    unsafeFromList [ 0x6a09e667f3bcc908
                                      , 0xbb67ae8584caa73b
                                      , 0x3c6ef372fe94f82b
                                      , 0xa54ff53a5f1d36f1
                                      , 0x510e527fade682d1
                                      , 0x9b05688c2b3e6c1f
                                      , 0x1f83d9abfb41bd6b
                                      , 0x5be0cd19137e2179
                                      ]

    instance Hash SHA512 where
      additionalPadBlocks :: SHA512 -> BLOCKS SHA512
    additionalPadBlocks _ = Int -> BLOCKS SHA512
    forall a. Enum a => Int -> a
    toEnum 1