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
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: AckInfo -> AckInfo -> Bool
$c/= :: AckInfo -> AckInfo -> Bool
== :: AckInfo -> AckInfo -> Bool
$c== :: AckInfo -> AckInfo -> Bool
Eq, PacketNumber -> AckInfo -> ShowS
[AckInfo] -> ShowS
AckInfo -> String
forall a.
(PacketNumber -> a -> ShowS)
-> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [AckInfo] -> ShowS
$cshowList :: [AckInfo] -> ShowS
show :: AckInfo -> String
$cshow :: AckInfo -> String
showsPrec :: PacketNumber -> AckInfo -> ShowS
$cshowsPrec :: PacketNumber -> 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 [] = 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) = 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 forall a. Num a => a -> a -> a
- a
1 forall a. Eq a => a -> a -> Bool
== a
x = a -> [a] -> PacketNumber -> AckInfo
ack a
x [a]
xs (PacketNumber
fr forall a. Num a => a -> a -> a
+ PacketNumber
1)
        | Bool
otherwise = PacketNumber
-> PacketNumber -> [(PacketNumber, PacketNumber)] -> AckInfo
AckInfo PacketNumber
l PacketNumber
fr forall a b. (a -> b) -> a -> b
$ forall {a} {t} {t}.
(Num t, Num t, Integral a) =>
a -> [a] -> t -> t -> [(t, t)]
ranges a
x [a]
xs (forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
p forall a. Num a => a -> a -> a
- a
x) 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 forall a. Num a => a -> a -> a
- a
1 forall a. Eq a => a -> a -> Bool
== a
x = a -> [a] -> t -> t -> [(t, t)]
ranges a
x [a]
xs t
g (t
r forall a. Num a => a -> a -> a
+ t
1)
        | Bool
otherwise = (t
g, t
r) forall a. a -> [a] -> [a]
: a -> [a] -> t -> t -> [(t, t)]
ranges a
x [a]
xs (forall a b. (Integral a, Num b) => a -> b
fromIntegral (a
p forall a. Num a => a -> a -> a
- a
x) 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) = forall {a} {a} {a}.
(Integral a, Enum a, Integral a, Num a) =>
[(a, a)] -> [a] -> [a]
loop [(PacketNumber, PacketNumber)]
grs [PacketNumber
stt .. PacketNumber
lpn]
  where
    stt :: PacketNumber
stt = PacketNumber
lpn forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral PacketNumber
fr
    loop :: [(a, a)] -> [a] -> [a]
loop [(a, 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 forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral a
r .. a
z] forall a. [a] -> [a] -> [a]
++ [a]
acc)
      where
        z :: a
z = a
s forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral a
g 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 forall a. Ord a => a -> a -> Bool
< PacketNumber
lim = [PacketNumber
lim .. PacketNumber
lpn]
    | Bool
otherwise = 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 forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral PacketNumber
fr
    loop :: [(a, b)] -> [PacketNumber] -> [PacketNumber]
loop [(a, b)]
_ [] = 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 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] forall a. [a] -> [a] -> [a]
++ [PacketNumber]
acc)
      where
        z :: PacketNumber
z = PacketNumber
s forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral a
g forall a. Num a => a -> a -> a
- PacketNumber
2
        r' :: PacketNumber
r' = forall a. Ord a => a -> a -> a
max PacketNumber
lim (PacketNumber
z forall a. Num a => a -> a -> a
- 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 -> forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (forall {a}. Ord a => a -> (a, a) -> Bool
f PacketNumber
x) forall a b. (a -> b) -> a -> b
$ forall {a} {b} {a}.
(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 forall a. Ord a => a -> a -> Bool
<= a
x Bool -> Bool -> Bool
&& a
x forall a. Ord a => a -> a -> Bool
<= a
u
    stt :: PacketNumber
stt = PacketNumber
lpn forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral PacketNumber
fr
    loop :: [(a, a)] -> [(b, b)] -> [(b, b)]
loop [(a, a)]
_ [] = 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 forall a b. (a -> b) -> a -> b
$ (b
z forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral a
r, b
z) forall a. a -> [a] -> [a]
: [(b, b)]
acc
      where
        z :: b
z = b
s forall a. Num a => a -> a -> a
- forall a b. (Integral a, Num b) => a -> b
fromIntegral a
g forall a. Num a => a -> a -> a
- b
2

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

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

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