{-# LANGUAGE BangPatterns, UnboxedTuples #-} module Network.CommSec.BitWindow ( BitWindow , zeroWindow , updateBitWindow ) where import Data.Bits import Network.CommSec.Types import Data.Word (Word64) -- | A Bit Window is just an unpacked tuple of base and mask type BitWindow = (Word64,Word64) zeroWindow :: BitWindow zeroWindow = (0,0) updateBitWindow :: BitWindow -> Word64 -> Either CommSecError BitWindow updateBitWindow !(!base,!mask) !sqn | base >= maxBound - 63 && mask == maxBound = Left OldContext | base <= sqn && base >= seqBase = let pos = fromIntegral $ sqn - base in if testBit mask pos then Left DuplicateSeq else let new = setBit mask pos in new `seq` Right (base, new) | base < seqBase = let newBase = seqBase newMask | seqBase - base > 63 = 0 | otherwise = mask `shiftR` fromIntegral (seqBase - base) shiftIt !b !m | testBit m 0 = shiftIt (b+1) (shiftR m 1) | otherwise = (b,m) (finalBase, finalMask) = shiftIt newBase newMask in updateBitWindow (finalBase,finalMask) sqn | base > sqn = Left DuplicateSeq where !seqBase | sqn < 64 = 0 | otherwise = sqn - 63 {-# INLINE updateBitWindow #-}