packages feed

quic-0.0.0: Network/QUIC/Types/Ack.hs

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