{-# LANGUAGE RecordWildCards #-}

module Network.QPACK.Table.Dynamic where

import Control.Concurrent.STM
import Data.Array.Base (unsafeWrite, unsafeRead)
import Data.Array.MArray (newArray)
import Data.IORef
import Network.ByteOrder
import Network.HPACK.Internal
import qualified UnliftIO.Exception as E

import Imports
import Network.QPACK.Table.RevIndex
import Network.QPACK.Types

data CodeInfo =
    EncodeInfo RevIndex -- Reverse index
               (IORef InsertionPoint)
  | DecodeInfo HuffmanDecoder

-- | Dynamic table for QPACK.
data DynamicTable = DynamicTable {
    DynamicTable -> CodeInfo
codeInfo          :: CodeInfo
  , DynamicTable -> IORef AbsoluteIndex
droppingPoint     :: IORef AbsoluteIndex
  , DynamicTable -> IORef AbsoluteIndex
drainingPoint     :: IORef AbsoluteIndex
  , DynamicTable -> TVar InsertionPoint
insertionPoint    :: TVar InsertionPoint
  , DynamicTable -> IORef BasePoint
basePoint         :: IORef BasePoint
  , DynamicTable -> TVar Int
maxNumOfEntries   :: TVar Int
  , DynamicTable -> TVar Table
circularTable     :: TVar Table
  , DynamicTable -> IORef Bool
debugQPACK        :: IORef Bool
  }

type Table = TArray Index Entry

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

getBasePoint :: DynamicTable -> IO BasePoint
getBasePoint :: DynamicTable -> IO BasePoint
getBasePoint DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = IORef BasePoint -> IO BasePoint
forall a. IORef a -> IO a
readIORef IORef BasePoint
basePoint

setBasePointToInsersionPoint :: DynamicTable -> IO ()
setBasePointToInsersionPoint :: DynamicTable -> IO ()
setBasePointToInsersionPoint DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = do
    InsertionPoint Int
ip <- TVar InsertionPoint -> IO InsertionPoint
forall a. TVar a -> IO a
readTVarIO TVar InsertionPoint
insertionPoint
    IORef BasePoint -> BasePoint -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef BasePoint
basePoint (BasePoint -> IO ()) -> BasePoint -> IO ()
forall a b. (a -> b) -> a -> b
$ Int -> BasePoint
BasePoint Int
ip

getInsertionPoint :: DynamicTable -> IO InsertionPoint
getInsertionPoint :: DynamicTable -> IO InsertionPoint
getInsertionPoint DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = TVar InsertionPoint -> IO InsertionPoint
forall a. TVar a -> IO a
readTVarIO TVar InsertionPoint
insertionPoint

getInsertionPointSTM :: DynamicTable -> STM InsertionPoint
getInsertionPointSTM :: DynamicTable -> STM InsertionPoint
getInsertionPointSTM DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = TVar InsertionPoint -> STM InsertionPoint
forall a. TVar a -> STM a
readTVar TVar InsertionPoint
insertionPoint

checkInsertionPoint :: DynamicTable -> InsertionPoint -> IO ()
checkInsertionPoint :: DynamicTable -> InsertionPoint -> IO ()
checkInsertionPoint DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} InsertionPoint
reqip = STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
    InsertionPoint
ip <- TVar InsertionPoint -> STM InsertionPoint
forall a. TVar a -> STM a
readTVar TVar InsertionPoint
insertionPoint
    Bool -> STM ()
check (InsertionPoint
reqip InsertionPoint -> InsertionPoint -> Bool
forall a. Ord a => a -> a -> Bool
<= InsertionPoint
ip)

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

-- | Creating 'DynamicTable' for encoding.
newDynamicTableForEncoding :: Size -- ^ The dynamic table size
                           -> IO DynamicTable
newDynamicTableForEncoding :: Int -> IO DynamicTable
newDynamicTableForEncoding Int
maxsiz = do
    RevIndex
rev <- IO RevIndex
newRevIndex
    IORef InsertionPoint
ref <- InsertionPoint -> IO (IORef InsertionPoint)
forall a. a -> IO (IORef a)
newIORef InsertionPoint
0
    let info :: CodeInfo
info = RevIndex -> IORef InsertionPoint -> CodeInfo
EncodeInfo RevIndex
rev IORef InsertionPoint
ref
    Int -> CodeInfo -> IO DynamicTable
newDynamicTable Int
maxsiz CodeInfo
info

-- | Creating 'DynamicTable' for decoding.
newDynamicTableForDecoding :: Size -- ^ The dynamic table size
                           -> Size -- ^ The size of temporary buffer for Huffman decoding
                           -> IO DynamicTable
newDynamicTableForDecoding :: Int -> Int -> IO DynamicTable
newDynamicTableForDecoding Int
maxsiz Int
huftmpsiz = do
    ForeignPtr Word8
gcbuf <- Int -> IO (ForeignPtr Word8)
forall a. Int -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes Int
huftmpsiz
    TVar (Maybe (ForeignPtr Word8, Int))
tvar <- Maybe (ForeignPtr Word8, Int)
-> IO (TVar (Maybe (ForeignPtr Word8, Int)))
forall a. a -> IO (TVar a)
newTVarIO (Maybe (ForeignPtr Word8, Int)
 -> IO (TVar (Maybe (ForeignPtr Word8, Int))))
-> Maybe (ForeignPtr Word8, Int)
-> IO (TVar (Maybe (ForeignPtr Word8, Int)))
forall a b. (a -> b) -> a -> b
$ (ForeignPtr Word8, Int) -> Maybe (ForeignPtr Word8, Int)
forall a. a -> Maybe a
Just (ForeignPtr Word8
gcbuf,Int
huftmpsiz)
    let decoder :: ReadBuffer -> Int -> IO ByteString
decoder = TVar (Maybe (ForeignPtr Word8, Int))
-> ReadBuffer -> Int -> IO ByteString
decodeHLock TVar (Maybe (ForeignPtr Word8, Int))
tvar
        info :: CodeInfo
info = (ReadBuffer -> Int -> IO ByteString) -> CodeInfo
DecodeInfo ReadBuffer -> Int -> IO ByteString
decoder
    Int -> CodeInfo -> IO DynamicTable
newDynamicTable Int
maxsiz CodeInfo
info

decodeHLock :: TVar (Maybe (GCBuffer,Int)) -> ReadBuffer -> Int -> IO ByteString
decodeHLock :: TVar (Maybe (ForeignPtr Word8, Int))
-> ReadBuffer -> Int -> IO ByteString
decodeHLock TVar (Maybe (ForeignPtr Word8, Int))
tvar ReadBuffer
rbuf Int
len = IO (ForeignPtr Word8, Int)
-> ((ForeignPtr Word8, Int) -> IO ())
-> ((ForeignPtr Word8, Int) -> IO ByteString)
-> IO ByteString
forall (m :: * -> *) a b c.
MonadUnliftIO m =>
m a -> (a -> m b) -> (a -> m c) -> m c
E.bracket IO (ForeignPtr Word8, Int)
lock (ForeignPtr Word8, Int) -> IO ()
unlock (((ForeignPtr Word8, Int) -> IO ByteString) -> IO ByteString)
-> ((ForeignPtr Word8, Int) -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \(ForeignPtr Word8
gcbuf,Int
bufsiz) ->
  ForeignPtr Word8 -> (Ptr Word8 -> IO ByteString) -> IO ByteString
forall a b. ForeignPtr a -> (Ptr a -> IO b) -> IO b
withForeignPtr ForeignPtr Word8
gcbuf ((Ptr Word8 -> IO ByteString) -> IO ByteString)
-> (Ptr Word8 -> IO ByteString) -> IO ByteString
forall a b. (a -> b) -> a -> b
$ \Ptr Word8
buf -> do
    WriteBuffer
wbuf <- Ptr Word8 -> Int -> IO WriteBuffer
newWriteBuffer Ptr Word8
buf Int
bufsiz
    WriteBuffer -> ReadBuffer -> Int -> IO ()
decH WriteBuffer
wbuf ReadBuffer
rbuf Int
len
    WriteBuffer -> IO ByteString
toByteString WriteBuffer
wbuf
  where
    lock :: IO (ForeignPtr Word8, Int)
lock = STM (ForeignPtr Word8, Int) -> IO (ForeignPtr Word8, Int)
forall a. STM a -> IO a
atomically (STM (ForeignPtr Word8, Int) -> IO (ForeignPtr Word8, Int))
-> STM (ForeignPtr Word8, Int) -> IO (ForeignPtr Word8, Int)
forall a b. (a -> b) -> a -> b
$ do
        Maybe (ForeignPtr Word8, Int)
mx <- TVar (Maybe (ForeignPtr Word8, Int))
-> STM (Maybe (ForeignPtr Word8, Int))
forall a. TVar a -> STM a
readTVar TVar (Maybe (ForeignPtr Word8, Int))
tvar
        case Maybe (ForeignPtr Word8, Int)
mx of
          Maybe (ForeignPtr Word8, Int)
Nothing -> STM (ForeignPtr Word8, Int)
forall a. STM a
retry
          Just (ForeignPtr Word8, Int)
x   -> do
              TVar (Maybe (ForeignPtr Word8, Int))
-> Maybe (ForeignPtr Word8, Int) -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe (ForeignPtr Word8, Int))
tvar Maybe (ForeignPtr Word8, Int)
forall a. Maybe a
Nothing
              (ForeignPtr Word8, Int) -> STM (ForeignPtr Word8, Int)
forall (m :: * -> *) a. Monad m => a -> m a
return (ForeignPtr Word8, Int)
x
    unlock :: (ForeignPtr Word8, Int) -> IO ()
unlock (ForeignPtr Word8, Int)
x = STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ TVar (Maybe (ForeignPtr Word8, Int))
-> Maybe (ForeignPtr Word8, Int) -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar (Maybe (ForeignPtr Word8, Int))
tvar (Maybe (ForeignPtr Word8, Int) -> STM ())
-> Maybe (ForeignPtr Word8, Int) -> STM ()
forall a b. (a -> b) -> a -> b
$ (ForeignPtr Word8, Int) -> Maybe (ForeignPtr Word8, Int)
forall a. a -> Maybe a
Just (ForeignPtr Word8, Int)
x

newDynamicTable :: Size -> CodeInfo -> IO DynamicTable
newDynamicTable :: Int -> CodeInfo -> IO DynamicTable
newDynamicTable Int
maxsiz CodeInfo
info = do
    Table
tbl <- STM Table -> IO Table
forall a. STM a -> IO a
atomically (STM Table -> IO Table) -> STM Table -> IO Table
forall a b. (a -> b) -> a -> b
$ (Int, Int) -> Entry -> STM Table
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> e -> m (a i e)
newArray (Int
0,Int
end) Entry
dummyEntry
    CodeInfo
-> IORef AbsoluteIndex
-> IORef AbsoluteIndex
-> TVar InsertionPoint
-> IORef BasePoint
-> TVar Int
-> TVar Table
-> IORef Bool
-> DynamicTable
DynamicTable CodeInfo
info (IORef AbsoluteIndex
 -> IORef AbsoluteIndex
 -> TVar InsertionPoint
 -> IORef BasePoint
 -> TVar Int
 -> TVar Table
 -> IORef Bool
 -> DynamicTable)
-> IO (IORef AbsoluteIndex)
-> IO
     (IORef AbsoluteIndex
      -> TVar InsertionPoint
      -> IORef BasePoint
      -> TVar Int
      -> TVar Table
      -> IORef Bool
      -> DynamicTable)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AbsoluteIndex -> IO (IORef AbsoluteIndex)
forall a. a -> IO (IORef a)
newIORef AbsoluteIndex
0       -- droppingPoint
                      IO
  (IORef AbsoluteIndex
   -> TVar InsertionPoint
   -> IORef BasePoint
   -> TVar Int
   -> TVar Table
   -> IORef Bool
   -> DynamicTable)
-> IO (IORef AbsoluteIndex)
-> IO
     (TVar InsertionPoint
      -> IORef BasePoint
      -> TVar Int
      -> TVar Table
      -> IORef Bool
      -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> AbsoluteIndex -> IO (IORef AbsoluteIndex)
forall a. a -> IO (IORef a)
newIORef AbsoluteIndex
0       -- drainingPoint
                      IO
  (TVar InsertionPoint
   -> IORef BasePoint
   -> TVar Int
   -> TVar Table
   -> IORef Bool
   -> DynamicTable)
-> IO (TVar InsertionPoint)
-> IO
     (IORef BasePoint
      -> TVar Int -> TVar Table -> IORef Bool -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> InsertionPoint -> IO (TVar InsertionPoint)
forall a. a -> IO (TVar a)
newTVarIO InsertionPoint
0      -- insertionPoint
                      IO
  (IORef BasePoint
   -> TVar Int -> TVar Table -> IORef Bool -> DynamicTable)
-> IO (IORef BasePoint)
-> IO (TVar Int -> TVar Table -> IORef Bool -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> BasePoint -> IO (IORef BasePoint)
forall a. a -> IO (IORef a)
newIORef BasePoint
0       -- basePoint
                      IO (TVar Int -> TVar Table -> IORef Bool -> DynamicTable)
-> IO (TVar Int) -> IO (TVar Table -> IORef Bool -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Int -> IO (TVar Int)
forall a. a -> IO (TVar a)
newTVarIO Int
maxN   -- maxNumOfEntries
                      IO (TVar Table -> IORef Bool -> DynamicTable)
-> IO (TVar Table) -> IO (IORef Bool -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Table -> IO (TVar Table)
forall a. a -> IO (TVar a)
newTVarIO Table
tbl    -- maxDynamicTableSize
                      IO (IORef Bool -> DynamicTable)
-> IO (IORef Bool) -> IO DynamicTable
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False   -- debugQPACK
  where
    maxN :: Int
maxN = Int -> Int
maxNumbers Int
maxsiz
    end :: Int
end = Int
maxN Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1

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

setDebugQPACK :: DynamicTable -> IO ()
setDebugQPACK :: DynamicTable -> IO ()
setDebugQPACK DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = IORef Bool -> Bool -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Bool
debugQPACK Bool
True

getDebugQPACK :: DynamicTable -> IO Bool
getDebugQPACK :: DynamicTable -> IO Bool
getDebugQPACK DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = IORef Bool -> IO Bool
forall a. IORef a -> IO a
readIORef IORef Bool
debugQPACK

qpackDebug :: DynamicTable -> IO () -> IO ()
qpackDebug :: DynamicTable -> IO () -> IO ()
qpackDebug DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} IO ()
action = do
    Bool
debug <- IORef Bool -> IO Bool
forall a. IORef a -> IO a
readIORef IORef Bool
debugQPACK
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
debug IO ()
action

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

getMaxNumOfEntries :: DynamicTable -> IO Int
getMaxNumOfEntries :: DynamicTable -> IO Int
getMaxNumOfEntries DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = TVar Int -> IO Int
forall a. TVar a -> IO a
readTVarIO TVar Int
maxNumOfEntries

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

{-# INLINE getRevIndex #-}
getRevIndex :: DynamicTable-> RevIndex
getRevIndex :: DynamicTable -> RevIndex
getRevIndex DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = RevIndex
rev
  where
    EncodeInfo RevIndex
rev IORef InsertionPoint
_ = CodeInfo
codeInfo

getHuffmanDecoder :: DynamicTable -> HuffmanDecoder
getHuffmanDecoder :: DynamicTable -> ReadBuffer -> Int -> IO ByteString
getHuffmanDecoder DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = ReadBuffer -> Int -> IO ByteString
huf
  where
    DecodeInfo ReadBuffer -> Int -> IO ByteString
huf = CodeInfo
codeInfo

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

clearLargestReference :: DynamicTable -> IO ()
clearLargestReference :: DynamicTable -> IO ()
clearLargestReference DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = IORef InsertionPoint -> InsertionPoint -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef InsertionPoint
ref InsertionPoint
0
  where
    EncodeInfo RevIndex
_ IORef InsertionPoint
ref = CodeInfo
codeInfo

getLargestReference :: DynamicTable -> IO InsertionPoint
getLargestReference :: DynamicTable -> IO InsertionPoint
getLargestReference DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = IORef InsertionPoint -> IO InsertionPoint
forall a. IORef a -> IO a
readIORef IORef InsertionPoint
ref
  where
    EncodeInfo RevIndex
_ IORef InsertionPoint
ref = CodeInfo
codeInfo

updateLargestReference :: DynamicTable -> AbsoluteIndex -> IO ()
updateLargestReference :: DynamicTable -> AbsoluteIndex -> IO ()
updateLargestReference DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} (AbsoluteIndex Int
idx) = do
    let nidx :: InsertionPoint
nidx = Int -> InsertionPoint
InsertionPoint Int
idx
    InsertionPoint
oidx <- IORef InsertionPoint -> IO InsertionPoint
forall a. IORef a -> IO a
readIORef IORef InsertionPoint
ref
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (InsertionPoint
nidx InsertionPoint -> InsertionPoint -> Bool
forall a. Ord a => a -> a -> Bool
> InsertionPoint
oidx) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ IORef InsertionPoint -> InsertionPoint -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef InsertionPoint
ref InsertionPoint
nidx
  where
    EncodeInfo RevIndex
_ IORef InsertionPoint
ref = CodeInfo
codeInfo

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

insertEntryToEncoder :: Entry -> DynamicTable -> IO AbsoluteIndex
insertEntryToEncoder :: Entry -> DynamicTable -> IO AbsoluteIndex
insertEntryToEncoder Entry
ent dyntbl :: DynamicTable
dyntbl@DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = do
    InsertionPoint Int
insp <- STM InsertionPoint -> IO InsertionPoint
forall a. STM a -> IO a
atomically (STM InsertionPoint -> IO InsertionPoint)
-> STM InsertionPoint -> IO InsertionPoint
forall a b. (a -> b) -> a -> b
$ do
        InsertionPoint
x <- TVar InsertionPoint -> STM InsertionPoint
forall a. TVar a -> STM a
readTVar TVar InsertionPoint
insertionPoint
        TVar InsertionPoint -> InsertionPoint -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar InsertionPoint
insertionPoint (InsertionPoint
x InsertionPoint -> InsertionPoint -> InsertionPoint
forall a. Num a => a -> a -> a
+ InsertionPoint
1)
        InsertionPoint -> STM InsertionPoint
forall (m :: * -> *) a. Monad m => a -> m a
return InsertionPoint
x
    Int
maxN <- STM Int -> IO Int
forall a. STM a -> IO a
atomically (STM Int -> IO Int) -> STM Int -> IO Int
forall a b. (a -> b) -> a -> b
$ TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
maxNumOfEntries
    let i :: Int
i = Int
insp Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
maxN
    Table
table <- STM Table -> IO Table
forall a. STM a -> IO a
atomically (STM Table -> IO Table) -> STM Table -> IO Table
forall a b. (a -> b) -> a -> b
$ TVar Table -> STM Table
forall a. TVar a -> STM a
readTVar TVar Table
circularTable
    STM () -> IO ()
forall a. STM a -> IO a
atomically (STM () -> IO ()) -> STM () -> IO ()
forall a b. (a -> b) -> a -> b
$ Table -> Int -> Entry -> STM ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> e -> m ()
unsafeWrite Table
table Int
i Entry
ent
    let revtbl :: RevIndex
revtbl = DynamicTable -> RevIndex
getRevIndex DynamicTable
dyntbl
    let ai :: AbsoluteIndex
ai = Int -> AbsoluteIndex
AbsoluteIndex Int
insp
    Entry -> HIndex -> RevIndex -> IO ()
insertRevIndex Entry
ent (AbsoluteIndex -> HIndex
DIndex AbsoluteIndex
ai) RevIndex
revtbl
    AbsoluteIndex -> IO AbsoluteIndex
forall (m :: * -> *) a. Monad m => a -> m a
return AbsoluteIndex
ai

insertEntryToDecoder :: Entry -> DynamicTable -> STM ()
insertEntryToDecoder :: Entry -> DynamicTable -> STM ()
insertEntryToDecoder Entry
ent DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} = do
    x :: InsertionPoint
x@(InsertionPoint Int
insp) <- TVar InsertionPoint -> STM InsertionPoint
forall a. TVar a -> STM a
readTVar TVar InsertionPoint
insertionPoint
    TVar InsertionPoint -> InsertionPoint -> STM ()
forall a. TVar a -> a -> STM ()
writeTVar TVar InsertionPoint
insertionPoint (InsertionPoint
x InsertionPoint -> InsertionPoint -> InsertionPoint
forall a. Num a => a -> a -> a
+ InsertionPoint
1)
    Int
maxN <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
maxNumOfEntries
    let i :: Int
i = Int
insp Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
maxN
    Table
table <- TVar Table -> STM Table
forall a. TVar a -> STM a
readTVar TVar Table
circularTable
    Table -> Int -> Entry -> STM ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> e -> m ()
unsafeWrite Table
table Int
i Entry
ent

toDynamicEntry :: DynamicTable -> AbsoluteIndex -> STM Entry
toDynamicEntry :: DynamicTable -> AbsoluteIndex -> STM Entry
toDynamicEntry DynamicTable{TVar Int
TVar Table
TVar InsertionPoint
IORef Bool
IORef BasePoint
IORef AbsoluteIndex
CodeInfo
debugQPACK :: IORef Bool
circularTable :: TVar Table
maxNumOfEntries :: TVar Int
basePoint :: IORef BasePoint
insertionPoint :: TVar InsertionPoint
drainingPoint :: IORef AbsoluteIndex
droppingPoint :: IORef AbsoluteIndex
codeInfo :: CodeInfo
debugQPACK :: DynamicTable -> IORef Bool
circularTable :: DynamicTable -> TVar Table
maxNumOfEntries :: DynamicTable -> TVar Int
basePoint :: DynamicTable -> IORef BasePoint
insertionPoint :: DynamicTable -> TVar InsertionPoint
drainingPoint :: DynamicTable -> IORef AbsoluteIndex
droppingPoint :: DynamicTable -> IORef AbsoluteIndex
codeInfo :: DynamicTable -> CodeInfo
..} (AbsoluteIndex Int
idx) = do
    Int
maxN <- TVar Int -> STM Int
forall a. TVar a -> STM a
readTVar TVar Int
maxNumOfEntries
    let i :: Int
i = Int
idx Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
maxN
    Table
table <- TVar Table -> STM Table
forall a. TVar a -> STM a
readTVar TVar Table
circularTable
    Table -> Int -> STM Entry
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Int -> m e
unsafeRead Table
table Int
i