{-|
Module      : What4.Utils.IncrHash
Copyright   : (c) Galois Inc, 2019-2020
License     : BSD3
Maintainer  : rdockins@galois.com

A basic datatype for incremental hashing which
supports a monoid instance.  Currently this is
simply implemented as bitwise xor for simplicity.

If we later wish to experiment with other incremenal hash
algorithms, this module abstracts over the implementation
details.
-}

module What4.Utils.IncrHash
( IncrHash
, mkIncrHash
, toIncrHash
, toIncrHashWithSalt
) where

import Data.Bits
import Data.Hashable

newtype IncrHash = IncrHash Int
 deriving (IncrHash -> IncrHash -> Bool
(IncrHash -> IncrHash -> Bool)
-> (IncrHash -> IncrHash -> Bool) -> Eq IncrHash
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: IncrHash -> IncrHash -> Bool
$c/= :: IncrHash -> IncrHash -> Bool
== :: IncrHash -> IncrHash -> Bool
$c== :: IncrHash -> IncrHash -> Bool
Eq,Eq IncrHash
Eq IncrHash
-> (IncrHash -> IncrHash -> Ordering)
-> (IncrHash -> IncrHash -> Bool)
-> (IncrHash -> IncrHash -> Bool)
-> (IncrHash -> IncrHash -> Bool)
-> (IncrHash -> IncrHash -> Bool)
-> (IncrHash -> IncrHash -> IncrHash)
-> (IncrHash -> IncrHash -> IncrHash)
-> Ord IncrHash
IncrHash -> IncrHash -> Bool
IncrHash -> IncrHash -> Ordering
IncrHash -> IncrHash -> IncrHash
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 :: IncrHash -> IncrHash -> IncrHash
$cmin :: IncrHash -> IncrHash -> IncrHash
max :: IncrHash -> IncrHash -> IncrHash
$cmax :: IncrHash -> IncrHash -> IncrHash
>= :: IncrHash -> IncrHash -> Bool
$c>= :: IncrHash -> IncrHash -> Bool
> :: IncrHash -> IncrHash -> Bool
$c> :: IncrHash -> IncrHash -> Bool
<= :: IncrHash -> IncrHash -> Bool
$c<= :: IncrHash -> IncrHash -> Bool
< :: IncrHash -> IncrHash -> Bool
$c< :: IncrHash -> IncrHash -> Bool
compare :: IncrHash -> IncrHash -> Ordering
$ccompare :: IncrHash -> IncrHash -> Ordering
$cp1Ord :: Eq IncrHash
Ord)

instance Semigroup IncrHash where
  IncrHash Int
x <> :: IncrHash -> IncrHash -> IncrHash
<> IncrHash Int
y = Int -> IncrHash
IncrHash (Int
x Int -> Int -> Int
forall a. Bits a => a -> a -> a
`xor` Int
y)

instance Monoid IncrHash where
  mempty :: IncrHash
mempty = Int -> IncrHash
IncrHash Int
0
  mappend :: IncrHash -> IncrHash -> IncrHash
mappend = IncrHash -> IncrHash -> IncrHash
forall a. Semigroup a => a -> a -> a
(<>)

mkIncrHash :: Int -> IncrHash
mkIncrHash :: Int -> IncrHash
mkIncrHash = Int -> IncrHash
IncrHash

toIncrHash :: Hashable a => a -> IncrHash
toIncrHash :: a -> IncrHash
toIncrHash = Int -> IncrHash
IncrHash (Int -> IncrHash) -> (a -> Int) -> a -> IncrHash
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Int
forall a. Hashable a => a -> Int
hash

toIncrHashWithSalt :: Hashable a => Int -> a -> IncrHash
toIncrHashWithSalt :: Int -> a -> IncrHash
toIncrHashWithSalt Int
s a
a = Int -> IncrHash
IncrHash (Int -> a -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
s a
a)

instance Hashable IncrHash where
  hashWithSalt :: Int -> IncrHash -> Int
hashWithSalt Int
s (IncrHash Int
h) = Int -> Int -> Int
forall a. Hashable a => Int -> a -> Int
hashWithSalt Int
s Int
h