    {-|
    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
    $c== :: IncrHash -> IncrHash -> Bool
    == :: IncrHash -> IncrHash -> Bool
    $c/= :: IncrHash -> IncrHash -> Bool
    /= :: 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
    $ccompare :: IncrHash -> IncrHash -> Ordering
    compare :: IncrHash -> IncrHash -> Ordering
    $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
    >= :: IncrHash -> IncrHash -> Bool
    $cmax :: IncrHash -> IncrHash -> IncrHash
    max :: IncrHash -> IncrHash -> IncrHash
    $cmin :: IncrHash -> IncrHash -> IncrHash
    min :: IncrHash -> IncrHash -> 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 :: forall a. Hashable a => 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 :: forall a. Hashable a => 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