module Network.CommSec.BitWindow
( BitWindow
, zeroWindow
, updateBitWindow
) where
import Data.Bits
import Network.CommSec.Types
import Data.Word (Word64)
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