module Foundation.Hashing.Hasher
    ( Hasher(..)
    ) where
import           Basement.Compat.Base
import           Basement.IntegralConv
import           Foundation.Array (UArray)
import qualified Basement.UArray as A
import           Data.Bits
class Hasher st where
    {-# MINIMAL hashNew, hashNewParam, hashMix8, hashEnd #-}
    
    type HashResult st
    
    type HashInitParam st
    
    hashNew :: st
    
    hashNewParam :: HashInitParam st -> st
    
    hashEnd :: st -> HashResult st
    
    hashMix8  :: Word8  -> st -> st
    
    hashMix16 :: Word16 -> st -> st
    hashMix16 Word16
w st
st = Word8 -> st -> st
forall st. Hasher st => Word8 -> st -> st
hashMix8 Word8
w2 (st -> st) -> st -> st
forall a b. (a -> b) -> a -> b
$ Word8 -> st -> st
forall st. Hasher st => Word8 -> st -> st
hashMix8 Word8
w1 st
st
      where
        !w1 :: Word8
w1 = Word16 -> Word8
forall a b. IntegralDownsize a b => a -> b
integralDownsize (Word16
w Word16 -> Int -> Word16
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8)
        !w2 :: Word8
w2 = Word16 -> Word8
forall a b. IntegralDownsize a b => a -> b
integralDownsize Word16
w
    
    hashMix32 :: Word32 -> st -> st
    hashMix32 Word32
w st
st = Word8 -> st -> st
forall st. Hasher st => Word8 -> st -> st
hashMix8 Word8
w4 (st -> st) -> st -> st
forall a b. (a -> b) -> a -> b
$ Word8 -> st -> st
forall st. Hasher st => Word8 -> st -> st
hashMix8 Word8
w3 (st -> st) -> st -> st
forall a b. (a -> b) -> a -> b
$ Word8 -> st -> st
forall st. Hasher st => Word8 -> st -> st
hashMix8 Word8
w2 (st -> st) -> st -> st
forall a b. (a -> b) -> a -> b
$ Word8 -> st -> st
forall st. Hasher st => Word8 -> st -> st
hashMix8 Word8
w1 st
st
      where
        !w1 :: Word8
w1 = Word32 -> Word8
forall a b. IntegralDownsize a b => a -> b
integralDownsize (Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
24)
        !w2 :: Word8
w2 = Word32 -> Word8
forall a b. IntegralDownsize a b => a -> b
integralDownsize (Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
16)
        !w3 :: Word8
w3 = Word32 -> Word8
forall a b. IntegralDownsize a b => a -> b
integralDownsize (Word32
w Word32 -> Int -> Word32
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
8)
        !w4 :: Word8
w4 = Word32 -> Word8
forall a b. IntegralDownsize a b => a -> b
integralDownsize Word32
w
    
    hashMix64 :: Word64 -> st -> st
    hashMix64 Word64
w st
st = Word32 -> st -> st
forall st. Hasher st => Word32 -> st -> st
hashMix32 Word32
w2 (st -> st) -> st -> st
forall a b. (a -> b) -> a -> b
$ Word32 -> st -> st
forall st. Hasher st => Word32 -> st -> st
hashMix32 Word32
w1 st
st
      where
        !w1 :: Word32
w1 = Word64 -> Word32
forall a b. IntegralDownsize a b => a -> b
integralDownsize (Word64
w Word64 -> Int -> Word64
forall a. Bits a => a -> Int -> a
`unsafeShiftR` Int
32)
        !w2 :: Word32
w2 = Word64 -> Word32
forall a b. IntegralDownsize a b => a -> b
integralDownsize Word64
w
    
    hashMixBytes :: A.PrimType e => UArray e -> st -> st
    hashMixBytes UArray e
ba st
st = (st -> Word8 -> st) -> st -> UArray Word8 -> st
forall ty a. PrimType ty => (a -> ty -> a) -> a -> UArray ty -> a
A.foldl' ((Word8 -> st -> st) -> st -> Word8 -> st
forall a b c. (a -> b -> c) -> b -> a -> c
flip Word8 -> st -> st
forall st. Hasher st => Word8 -> st -> st
hashMix8) st
st (UArray e -> UArray Word8
forall a b. (PrimType a, PrimType b) => UArray a -> UArray b
A.unsafeRecast UArray e
ba)