module Network.QUIC.Stream.Frag where

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

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 :: forall a. Frag a => 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
$cshowsPrec :: Int -> F -> ShowS
showsPrec :: Int -> F -> ShowS
$cshow :: F -> [Char]
show :: F -> [Char]
$cshowList :: [F] -> ShowS
showList :: [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"