module Data.Generics.Fixplate.Util.Hash.Class where
import Data.Char
import Data.Word
import Data.Int
import Data.Bits
import Data.List
class (Eq hash, Ord hash, Hashable hash) => HashValue hash where
hashWord8 :: Word8 -> hash -> hash
hashWord16 :: Word16 -> hash -> hash
hashWord32 :: Word32 -> hash -> hash
hashWord64 :: Word64 -> hash -> hash
emptyHash :: hash
hashHash :: hash -> hash -> hash
showHex :: hash -> String
hashWord32 w = hashWord8 a . hashWord8 b . hashWord8 c . hashWord8 d where
a = fromIntegral (255 .&. ( w ))
b = fromIntegral (255 .&. (shiftR w 8))
c = fromIntegral (255 .&. (shiftR w 16))
d = fromIntegral (255 .&. (shiftR w 24))
hashWord16 w = hashWord8 a . hashWord8 b where
a = fromIntegral (255 .&. ( w ))
b = fromIntegral (255 .&. (shiftR w 8))
hashWord64 w = hashWord32 a . hashWord32 b where
a = fromIntegral (0xffffffff .&. ( w ))
b = fromIntegral (0xffffffff .&. (shiftR w 32))
class Hashable a where
hashDigest :: HashValue hash => a -> hash -> hash
computeHash :: HashValue hash => a -> hash
computeHash x = hashDigest x emptyHash
instance Hashable Word8 where hashDigest = hashWord8
instance Hashable Word16 where hashDigest = hashWord16
instance Hashable Word32 where hashDigest = hashWord32
instance Hashable Word64 where hashDigest = hashWord64
instance Hashable Int where hashDigest = hashInt
instance Hashable Word where hashDigest = hashWord
instance Hashable Bool where hashDigest = hashBool
instance Hashable Char where hashDigest = hashChar
instance Hashable a => Hashable [a] where
hashDigest xs h = foldl' (flip hashDigest) h xs
instance (Hashable a, Hashable b) => Hashable (a,b) where
hashDigest (x,y) = hashDigest y . hashDigest x
instance (Hashable a, Hashable b, Hashable c) => Hashable (a,b,c) where
hashDigest (x,y,z) = hashDigest z . hashDigest y . hashDigest x
instance (Hashable a, Hashable b, Hashable c, Hashable d) => Hashable (a,b,c,d) where
hashDigest (x,y,z,w) = hashDigest w . hashDigest z . hashDigest y . hashDigest x
instance (Hashable a, Hashable b, Hashable c, Hashable d, Hashable e) => Hashable (a,b,c,d,e) where
hashDigest (x,y,z,w,u) = hashDigest u . hashDigest w . hashDigest z . hashDigest y . hashDigest x
hashInt :: HashValue hash => Int -> hash -> hash
hashWord :: HashValue hash => Word -> hash -> hash
hashBool :: HashValue hash => Bool -> hash -> hash
hashChar :: HashValue hash => Char -> hash -> hash
hashInt k = hashWord64 (fromIntegral k)
hashWord k = hashWord64 (fromIntegral k)
hashBool b = hashWord8 (if b then 255 else 0)
hashChar c = hashWord16 (fromIntegral (ord c))