module Network.QUIC.Packet.Number ( encodePacketNumber, decodePacketNumber, ) where import Network.QUIC.Imports import Network.QUIC.Types ---------------------------------------------------------------- -- | -- -- >>> encodePacketNumber 0xabe8bc 0xac5c02 == (0x5c02,2) -- True -- >>> encodePacketNumber 0xa82f30ea 0xa82f9b32 == (0x9b32,2) -- True -- >>> encodePacketNumber 0xabe8bc 0xace8fe == (0xace8fe, 3) -- True {- FOURMOLU_DISABLE -} encodePacketNumber :: PacketNumber -> PacketNumber -> (EncodedPacketNumber, Int) encodePacketNumber largestPN pn = (diff, bytes) where enoughRange = (pn - largestPN) * 2 (pnMask, bytes) -- | enoughRange < 256 = (0x000000ff, 1) | enoughRange < 65536 = (0x0000ffff, 2) | enoughRange < 16777216 = (0x00ffffff, 3) | otherwise = (0xffffffff, 4) diff = fromIntegral (pn .&. pnMask) {- FOURMOLU_ENABLE -} ---------------------------------------------------------------- -- | -- -- >>> decodePacketNumber 0xabe8bc 0x5c02 2 == 0xac5c02 -- True -- >>> decodePacketNumber 0xa82f30ea 0x9b32 2 == 0xa82f9b32 -- True -- >>> decodePacketNumber 0xabe8bc 0xace8fe 3 == 0xace8fe -- True {- FOURMOLU_DISABLE -} decodePacketNumber :: PacketNumber -> EncodedPacketNumber -> Int -> PacketNumber decodePacketNumber largestPN truncatedPN bytes | candidatePN <= expectedPN - pnHwin && candidatePN < mx - pnWin = candidatePN + pnWin | candidatePN > expectedPN + pnHwin && candidatePN >= pnWin = candidatePN - pnWin | otherwise = candidatePN where mx = 1 !<<. 62 pnNbits = bytes * 8 expectedPN = largestPN + 1 pnWin = 1 !<<. pnNbits pnHwin = pnWin !>>. 1 pnMask = pnWin - 1 candidatePN = (expectedPN .&. complement pnMask) .|. fromIntegral truncatedPN {- FOURMOLU_ENABLE -}