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 (AckInfo -> AckInfo -> Bool
(AckInfo -> AckInfo -> Bool)
-> (AckInfo -> AckInfo -> Bool) -> Eq AckInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AckInfo -> AckInfo -> Bool
== :: AckInfo -> AckInfo -> Bool
$c/= :: AckInfo -> AckInfo -> Bool
/= :: AckInfo -> AckInfo -> Bool
Eq, PacketNumber -> AckInfo -> ShowS
[AckInfo] -> ShowS
AckInfo -> String
(PacketNumber -> AckInfo -> ShowS)
-> (AckInfo -> String) -> ([AckInfo] -> ShowS) -> Show AckInfo
forall a.
(PacketNumber -> a -> ShowS)
-> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: PacketNumber -> AckInfo -> ShowS
showsPrec :: PacketNumber -> AckInfo -> ShowS
$cshow :: AckInfo -> String
show :: AckInfo -> String
$cshowList :: [AckInfo] -> ShowS
showList :: [AckInfo] -> ShowS
Show)

ackInfo0 :: AckInfo
ackInfo0 :: AckInfo
ackInfo0 = PacketNumber
-> PacketNumber -> [(PacketNumber, PacketNumber)] -> AckInfo
AckInfo (-PacketNumber
1) PacketNumber
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 :: [PacketNumber] -> AckInfo
toAckInfo [] = String -> AckInfo
forall a. HasCallStack => String -> a
error String
"toAckInfo"
toAckInfo [PacketNumber
l] = PacketNumber
-> PacketNumber -> [(PacketNumber, PacketNumber)] -> AckInfo
AckInfo PacketNumber
l PacketNumber
0 []
toAckInfo (PacketNumber
l : [PacketNumber]
ls) = PacketNumber -> [PacketNumber] -> PacketNumber -> AckInfo
forall {a}. Integral a => a -> [a] -> PacketNumber -> AckInfo
ack PacketNumber
l [PacketNumber]
ls PacketNumber
0
  where
    ack :: a -> [a] -> PacketNumber -> AckInfo
ack a
_ [] PacketNumber
fr = PacketNumber
-> PacketNumber -> [(PacketNumber, PacketNumber)] -> AckInfo
AckInfo PacketNumber
l PacketNumber
fr []
    ack a
p (a
x : [a]
xs) PacketNumber
fr
        | a
p a -> a -> a
forall a. Num a => a -> a -> a
- a
1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x = a -> [a] -> PacketNumber -> AckInfo
ack a
x [a]
xs (PacketNumber
fr PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
+ PacketNumber
1)
        | Bool
otherwise = PacketNumber
-> PacketNumber -> [(PacketNumber, PacketNumber)] -> AckInfo
AckInfo PacketNumber
l PacketNumber
fr ([(PacketNumber, PacketNumber)] -> AckInfo)
-> [(PacketNumber, PacketNumber)] -> AckInfo
forall a b. (a -> b) -> a -> b
$ a
-> [a]
-> PacketNumber
-> PacketNumber
-> [(PacketNumber, PacketNumber)]
forall {a} {t} {t}.
(Integral a, Num t, Num t) =>
a -> [a] -> t -> t -> [(t, t)]
ranges a
x [a]
xs (a -> PacketNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
p a -> a -> a
forall a. Num a => a -> a -> a
- a
x) PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
- PacketNumber
2) PacketNumber
0
    ranges :: a -> [a] -> t -> t -> [(t, t)]
ranges a
_ [] t
g t
r = [(t
g, t
r)]
    ranges a
p (a
x : [a]
xs) t
g t
r
        | a
p a -> a -> a
forall a. Num a => a -> a -> a
- a
1 a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
x = a -> [a] -> t -> t -> [(t, t)]
ranges a
x [a]
xs t
g (t
r t -> t -> t
forall a. Num a => a -> a -> a
+ t
1)
        | Bool
otherwise = (t
g, t
r) (t, t) -> [(t, t)] -> [(t, t)]
forall a. a -> [a] -> [a]
: a -> [a] -> t -> t -> [(t, t)]
ranges a
x [a]
xs (a -> t
forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
p a -> a -> a
forall a. Num a => a -> a -> a
- a
x) t -> t -> t
forall a. Num a => a -> a -> a
- t
2) t
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 -> [PacketNumber]
fromAckInfo (AckInfo PacketNumber
lpn PacketNumber
fr [(PacketNumber, PacketNumber)]
grs) = [(PacketNumber, PacketNumber)] -> [PacketNumber] -> [PacketNumber]
forall {a} {a} {a}.
(Integral a, Integral a, Num a, Enum a) =>
[(a, a)] -> [a] -> [a]
loop [(PacketNumber, PacketNumber)]
grs [PacketNumber
stt .. PacketNumber
lpn]
  where
    stt :: PacketNumber
stt = PacketNumber
lpn PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
- PacketNumber -> PacketNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral PacketNumber
fr
    loop :: [(a, a)] -> [a] -> [a]
loop [(a, a)]
_ [] = String -> [a]
forall a. HasCallStack => String -> a
error String
"loop"
    loop [] [a]
acc = [a]
acc
    loop ((a
g, a
r) : [(a, a)]
xs) acc :: [a]
acc@(a
s : [a]
_) = [(a, a)] -> [a] -> [a]
loop [(a, a)]
xs ([a
z a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
r .. a
z] [a] -> [a] -> [a]
forall a. [a] -> [a] -> [a]
++ [a]
acc)
      where
        z :: a
z = a
s a -> a -> a
forall a. Num a => a -> a -> a
- a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
g a -> a -> a
forall a. Num a => a -> a -> a
- a
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 -> PacketNumber -> [PacketNumber]
fromAckInfoWithMin (AckInfo PacketNumber
lpn PacketNumber
fr [(PacketNumber, PacketNumber)]
grs) PacketNumber
lim
    | PacketNumber
stt PacketNumber -> PacketNumber -> Bool
forall a. Ord a => a -> a -> Bool
< PacketNumber
lim = [PacketNumber
lim .. PacketNumber
lpn]
    | Bool
otherwise = [(PacketNumber, PacketNumber)] -> [PacketNumber] -> [PacketNumber]
forall {a} {b}.
(Integral a, Integral b) =>
[(a, b)] -> [PacketNumber] -> [PacketNumber]
loop [(PacketNumber, PacketNumber)]
grs [PacketNumber
stt .. PacketNumber
lpn]
  where
    stt :: PacketNumber
stt = PacketNumber
lpn PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
- PacketNumber -> PacketNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral PacketNumber
fr
    loop :: [(a, b)] -> [PacketNumber] -> [PacketNumber]
loop [(a, b)]
_ [] = String -> [PacketNumber]
forall a. HasCallStack => String -> a
error String
"loop"
    loop [] [PacketNumber]
acc = [PacketNumber]
acc
    loop ((a
g, b
r) : [(a, b)]
xs) acc :: [PacketNumber]
acc@(PacketNumber
s : [PacketNumber]
_)
        | PacketNumber
z PacketNumber -> PacketNumber -> Bool
forall a. Ord a => a -> a -> Bool
< PacketNumber
lim = [PacketNumber]
acc
        | Bool
otherwise = [(a, b)] -> [PacketNumber] -> [PacketNumber]
loop [(a, b)]
xs ([PacketNumber
r' .. PacketNumber
z] [PacketNumber] -> [PacketNumber] -> [PacketNumber]
forall a. [a] -> [a] -> [a]
++ [PacketNumber]
acc)
      where
        z :: PacketNumber
z = PacketNumber
s PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
- a -> PacketNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
g PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
- PacketNumber
2
        r' :: PacketNumber
r' = PacketNumber -> PacketNumber -> PacketNumber
forall a. Ord a => a -> a -> a
max PacketNumber
lim (PacketNumber
z PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
- b -> PacketNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral b
r)

fromAckInfoToPred :: AckInfo -> (PacketNumber -> Bool)
fromAckInfoToPred :: AckInfo -> PacketNumber -> Bool
fromAckInfoToPred (AckInfo PacketNumber
lpn PacketNumber
fr [(PacketNumber, PacketNumber)]
grs) =
    \PacketNumber
x -> ((PacketNumber, PacketNumber) -> Bool)
-> [(PacketNumber, PacketNumber)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (PacketNumber -> (PacketNumber, PacketNumber) -> Bool
forall {a}. Ord a => a -> (a, a) -> Bool
f PacketNumber
x) ([(PacketNumber, PacketNumber)] -> Bool)
-> [(PacketNumber, PacketNumber)] -> Bool
forall a b. (a -> b) -> a -> b
$ [(PacketNumber, PacketNumber)]
-> [(PacketNumber, PacketNumber)] -> [(PacketNumber, PacketNumber)]
forall {a} {a} {b}.
(Integral a, Integral a, Num b) =>
[(a, a)] -> [(b, b)] -> [(b, b)]
loop [(PacketNumber, PacketNumber)]
grs [(PacketNumber
stt, PacketNumber
lpn)]
  where
    f :: a -> (a, a) -> Bool
f a
x (a
l, a
u) = a
l a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
x Bool -> Bool -> Bool
&& a
x a -> a -> Bool
forall a. Ord a => a -> a -> Bool
<= a
u
    stt :: PacketNumber
stt = PacketNumber
lpn PacketNumber -> PacketNumber -> PacketNumber
forall a. Num a => a -> a -> a
- PacketNumber -> PacketNumber
forall a b. (Integral a, Num b) => a -> b
fromIntegral PacketNumber
fr
    loop :: [(a, a)] -> [(b, b)] -> [(b, b)]
loop [(a, a)]
_ [] = String -> [(b, b)]
forall a. HasCallStack => String -> a
error String
"loop"
    loop [] [(b, b)]
acc = [(b, b)]
acc
    loop ((a
g, a
r) : [(a, a)]
xs) acc :: [(b, b)]
acc@((b
s, b
_) : [(b, b)]
_) = [(a, a)] -> [(b, b)] -> [(b, b)]
loop [(a, a)]
xs ([(b, b)] -> [(b, b)]) -> [(b, b)] -> [(b, b)]
forall a b. (a -> b) -> a -> b
$ (b
z b -> b -> b
forall a. Num a => a -> a -> a
- a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
r, b
z) (b, b) -> [(b, b)] -> [(b, b)]
forall a. a -> [a] -> [a]
: [(b, b)]
acc
      where
        z :: b
z = b
s b -> b -> b
forall a. Num a => a -> a -> a
- a -> b
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
g b -> b -> b
forall a. Num a => a -> a -> a
- b
2

----------------------------------------------------------------

newtype PeerPacketNumbers = PeerPacketNumbers IntSet
    deriving (PeerPacketNumbers -> PeerPacketNumbers -> Bool
(PeerPacketNumbers -> PeerPacketNumbers -> Bool)
-> (PeerPacketNumbers -> PeerPacketNumbers -> Bool)
-> Eq PeerPacketNumbers
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
== :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
$c/= :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
/= :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
Eq, PacketNumber -> PeerPacketNumbers -> ShowS
[PeerPacketNumbers] -> ShowS
PeerPacketNumbers -> String
(PacketNumber -> PeerPacketNumbers -> ShowS)
-> (PeerPacketNumbers -> String)
-> ([PeerPacketNumbers] -> ShowS)
-> Show PeerPacketNumbers
forall a.
(PacketNumber -> a -> ShowS)
-> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: PacketNumber -> PeerPacketNumbers -> ShowS
showsPrec :: PacketNumber -> PeerPacketNumbers -> ShowS
$cshow :: PeerPacketNumbers -> String
show :: PeerPacketNumbers -> String
$cshowList :: [PeerPacketNumbers] -> ShowS
showList :: [PeerPacketNumbers] -> ShowS
Show)

emptyPeerPacketNumbers :: PeerPacketNumbers
emptyPeerPacketNumbers :: PeerPacketNumbers
emptyPeerPacketNumbers = IntSet -> PeerPacketNumbers
PeerPacketNumbers IntSet
IntSet.empty