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

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

fromAckInfoToPred :: AckInfo -> (PacketNumber -> Bool)
fromAckInfoToPred :: AckInfo -> Int -> Bool
fromAckInfoToPred (AckInfo Int
lpn Int
fr [(Int, Int)]
grs) =
    \Int
x -> ((Int, Int) -> Bool) -> [(Int, Int)] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Int -> (Int, Int) -> Bool
forall a. Ord a => a -> (a, a) -> Bool
f Int
x) ([(Int, Int)] -> Bool) -> [(Int, Int)] -> Bool
forall a b. (a -> b) -> a -> b
$ [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
forall a b a.
(Integral a, Integral a, Num b) =>
[(a, a)] -> [(b, b)] -> [(b, b)]
loop [(Int, Int)]
grs [(Int
stt,Int
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 :: Int
stt = Int
lpn Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
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
/= :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
$c/= :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
== :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
$c== :: PeerPacketNumbers -> PeerPacketNumbers -> Bool
Eq, Int -> PeerPacketNumbers -> ShowS
[PeerPacketNumbers] -> ShowS
PeerPacketNumbers -> String
(Int -> PeerPacketNumbers -> ShowS)
-> (PeerPacketNumbers -> String)
-> ([PeerPacketNumbers] -> ShowS)
-> Show PeerPacketNumbers
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [PeerPacketNumbers] -> ShowS
$cshowList :: [PeerPacketNumbers] -> ShowS
show :: PeerPacketNumbers -> String
$cshow :: PeerPacketNumbers -> String
showsPrec :: Int -> PeerPacketNumbers -> ShowS
$cshowsPrec :: Int -> PeerPacketNumbers -> ShowS
Show)

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