module Network.QUIC.Types.Ack where import Data.IntSet (IntSet) import qualified Data.IntSet as IntSet type PacketNumber = Int type Range = Int type Gap = Int data AckInfo = AckInfo PacketNumber Range [(Gap, Range)] deriving (Eq, Show) ackInfo0 :: AckInfo ackInfo0 = AckInfo (-1) 0 [] -- | -- >>> toAckInfo [9] -- AckInfo 9 0 [] -- >>> toAckInfo [9,8,7] -- AckInfo 9 2 [] -- >>> toAckInfo [8,7,3,2] -- AckInfo 8 1 [(2,1)] -- >>> toAckInfo [9,8,7,5,4] -- AckInfo 9 2 [(0,1)] toAckInfo :: [PacketNumber] -> AckInfo toAckInfo [] = error "toAckInfo" toAckInfo [l] = AckInfo l 0 [] toAckInfo (l : ls) = ack l ls 0 where ack _ [] fr = AckInfo l fr [] ack p (x : xs) fr | p - 1 == x = ack x xs (fr + 1) | otherwise = AckInfo l fr $ ranges x xs (fromIntegral (p - x) - 2) 0 ranges _ [] g r = [(g, r)] ranges p (x : xs) g r | p - 1 == x = ranges x xs g (r + 1) | otherwise = (g, r) : ranges x xs (fromIntegral (p - x) - 2) 0 -- | -- >>> fromAckInfo $ AckInfo 9 0 [] -- [9] -- >>> fromAckInfo $ AckInfo 9 2 [] -- [7,8,9] -- >>> fromAckInfo $ AckInfo 8 1 [(2,1)] -- [2,3,7,8] -- >>> fromAckInfo $ AckInfo 9 2 [(0,1)] -- [4,5,7,8,9] fromAckInfo :: AckInfo -> [PacketNumber] fromAckInfo (AckInfo lpn fr grs) = loop grs [stt .. lpn] where stt = lpn - fromIntegral fr loop _ [] = error "loop" loop [] acc = acc loop ((g, r) : xs) acc@(s : _) = loop xs ([z - fromIntegral r .. z] ++ acc) where z = s - fromIntegral g - 2 -- | -- >>> fromAckInfoWithMin (AckInfo 9 0 []) 1 -- [9] -- >>> fromAckInfoWithMin (AckInfo 9 2 []) 8 -- [8,9] -- >>> fromAckInfoWithMin (AckInfo 8 1 [(2,1)]) 3 -- [3,7,8] -- >>> fromAckInfoWithMin (AckInfo 9 2 [(0,1)]) 8 -- [8,9] fromAckInfoWithMin :: AckInfo -> PacketNumber -> [PacketNumber] fromAckInfoWithMin (AckInfo lpn fr grs) lim | stt < lim = [lim .. lpn] | otherwise = loop grs [stt .. lpn] where stt = lpn - fromIntegral fr loop _ [] = error "loop" loop [] acc = acc loop ((g, r) : xs) acc@(s : _) | z < lim = acc | otherwise = loop xs ([r' .. z] ++ acc) where z = s - fromIntegral g - 2 r' = max lim (z - fromIntegral r) fromAckInfoToPred :: AckInfo -> (PacketNumber -> Bool) fromAckInfoToPred (AckInfo lpn fr grs) = \x -> any (f x) $ loop grs [(stt, lpn)] where f x (l, u) = l <= x && x <= u stt = lpn - fromIntegral fr loop _ [] = error "loop" loop [] acc = acc loop ((g, r) : xs) acc@((s, _) : _) = loop xs $ (z - fromIntegral r, z) : acc where z = s - fromIntegral g - 2 ---------------------------------------------------------------- newtype PeerPacketNumbers = PeerPacketNumbers IntSet deriving (Eq, Show) emptyPeerPacketNumbers :: PeerPacketNumbers emptyPeerPacketNumbers = PeerPacketNumbers IntSet.empty