module Network.QUIC.Stream.Frag where

import Data.Sequence (Seq, viewl, viewr, ViewL(..), ViewR(..), (<|), dropWhileL)

class Frag a where
    currOff :: a -> Int
    nextOff :: a -> Int
    shrink  :: Int -> a -> a

instance Frag a => Frag (Seq a) where
    currOff :: Seq a -> Int
currOff Seq a
s = case Seq a -> ViewL a
forall a. Seq a -> ViewL a
viewl Seq a
s of
      ViewL a
EmptyL -> [Char] -> Int
forall a. HasCallStack => [Char] -> a
error [Char]
"Seq is empty (1)"
      a
x :< Seq a
_ -> a -> Int
forall a. Frag a => a -> Int
currOff a
x
    nextOff :: Seq a -> Int
nextOff Seq a
s = case Seq a -> ViewR a
forall a. Seq a -> ViewR a
viewr Seq a
s of
      ViewR a
EmptyR -> [Char] -> Int
forall a. HasCallStack => [Char] -> a
error [Char]
"Seq is empty (2)"
      Seq a
_ :> a
x -> a -> Int
forall a. Frag a => a -> Int
nextOff a
x
    shrink :: Int -> Seq a -> Seq a
shrink = Int -> Seq a -> Seq a
forall a. Frag a => Int -> Seq a -> Seq a
shrinkSeq

shrinkSeq :: Frag a => Int -> Seq a -> Seq a
shrinkSeq :: Int -> Seq a -> Seq a
shrinkSeq Int
n Seq a
s0 = case Seq a -> ViewL a
forall a. Seq a -> ViewL a
viewl Seq a
s of
  ViewL a
EmptyL -> [Char] -> Seq a
forall a. HasCallStack => [Char] -> a
error [Char]
"shrinkSeq"
  a
x :< Seq a
xs
    | a -> Int
forall a. Frag a => a -> Int
nextOff a
x Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
n -> Seq a
xs
    | Bool
otherwise      -> Int -> a -> a
forall a. Frag a => Int -> a -> a
shrink Int
n a
x a -> Seq a -> Seq a
forall a. a -> Seq a -> Seq a
<| Seq a
xs
  where
    s :: Seq a
s = (a -> Bool) -> Seq a -> Seq a
forall a. (a -> Bool) -> Seq a -> Seq a
dropWhileL (\a
y -> Bool -> Bool
not (a -> Int
forall a. Frag a => a -> Int
currOff a
y Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= a -> Int
forall a. Frag a => a -> Int
nextOff a
y)) Seq a
s0

data F = F Int Int deriving Int -> F -> ShowS
[F] -> ShowS
F -> [Char]
(Int -> F -> ShowS) -> (F -> [Char]) -> ([F] -> ShowS) -> Show F
forall a.
(Int -> a -> ShowS) -> (a -> [Char]) -> ([a] -> ShowS) -> Show a
showList :: [F] -> ShowS
$cshowList :: [F] -> ShowS
show :: F -> [Char]
$cshow :: F -> [Char]
showsPrec :: Int -> F -> ShowS
$cshowsPrec :: Int -> F -> ShowS
Show

instance Frag F where
    currOff :: F -> Int
currOff (F Int
s Int
_)   = Int
s
    nextOff :: F -> Int
nextOff (F Int
_ Int
e)   = Int
e
    shrink :: Int -> F -> F
shrink  Int
n (F Int
s Int
e) = if Int
s Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
n Bool -> Bool -> Bool
&& Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
e then Int -> Int -> F
F Int
n Int
e else [Char] -> F
forall a. HasCallStack => [Char] -> a
error [Char]
"shrink"