module Database.Perdure.Digest (
Digest(..),
Skein512Digest,
MD5Digest,
module Cgm.Data.LongWord
) where
import Prelude ()
import Cgm.Prelude
import Cgm.Data.Word
import Cgm.Data.LongWord
import Cgm.Data.Array
import Cgm.System.Endian
import System.IO.Unsafe
import qualified Data.ByteString as B
import qualified Crypto.Hash.MD5 as MD5
import qualified Crypto.Hash.Skein512 as Skein512
import Cgm.Data.Structured
unsafeBSToWordHash :: (Allocation f, PinnedArray r, Prim (ArrayElem r)) => (B.ByteString -> B.ByteString) -> r -> PrimArray f (ArrayElem r)
unsafeBSToWordHash f input = unsafePrimArrayCast $ arrayFromByteString $ unsafePerformIO $ unsafeWithCastArrayByteString (evaluate . f) input
unsafeFixedEndianToWordHash :: forall r. (PinnedArray r, ImmArray r, Endian (ArrayElem r), Prim (ArrayElem r)) =>
Endianness -> (B.ByteString -> B.ByteString) -> r -> PrimArray Free (ArrayElem r)
unsafeFixedEndianToWordHash e f =
if platformWordEndianness == e
then unsafeBSToWordHash f
else mapImmArray unswapBytes . (id :: Id (PrimArray Free (ByteSwapped w))) .
unsafeBSToWordHash f . (id :: Id (PrimArray Pinned (ByteSwapped (ArrayElem r)))) .
mapImmArray swapBytes
word128FromArray32LE :: PrimArray f Word32 -> Word128
word128FromArray32LE a = word128BE (retract splitWord64LE (indexArray a 2, indexArray a 3)) (retract splitWord64LE (indexArray a 0, indexArray a 1))
word128FromArray64LE :: PrimArray f Word64 -> Word128
word128FromArray64LE a = word128BE (indexArray a 1) (indexArray a 0)
newtype Skein512Digest h = Skein512Digest h deriving (Eq, Show)
newtype MD5Digest = MD5Digest Word128 deriving (Eq, Show)
class Eq d => Digest d where
type DigestWord d
digest :: (ImmArray r, PinnedArray r, ArrayElem r ~ DigestWord d) => r -> d
instance Digest (Skein512Digest Word128) where
type DigestWord (Skein512Digest Word128) = Word64
digest = (Skein512Digest . word128FromArray64LE . unsafeFixedEndianToWordHash LittleEndian (Skein512.hash 128))
instance Digest MD5Digest where
type DigestWord MD5Digest = Word32
digest = (MD5Digest . word128FromArray32LE . unsafeFixedEndianToWordHash LittleEndian MD5.hash)
deriveStructured ''MD5Digest
deriveStructured ''Skein512Digest