{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE RecordWildCards #-}

module Network.HPACK.Table.Dynamic (
    DynamicTable(..)
  , newDynamicTableForEncoding
  , newDynamicTableForDecoding
  , renewDynamicTable
  , huffmanDecoder
  , printDynamicTable
  , isDynamicTableEmpty
  , isSuitableSize
  , TableSizeAction(..)
  , needChangeTableSize
  , setLimitForEncoding
  , resetLimitForEncoding
  , insertEntry
  , toDynamicEntry
  , CodeInfo(..)
  , withDynamicTableForEncoding
  , withDynamicTableForDecoding
  , toIndexedEntry
  , fromHIndexToIndex
  , getRevIndex
  ) where

import Control.Exception (throwIO)
import Data.Array.Base (unsafeRead, unsafeWrite)
import Data.Array.IO (IOArray, newArray)
import qualified Data.ByteString.Char8 as BS
import Data.IORef

import Imports
import Network.HPACK.Huffman
import Network.HPACK.Table.Entry
import Network.HPACK.Table.RevIndex
import Network.HPACK.Table.Static
import Network.HPACK.Types

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

-- For decoder
{-# INLINE toIndexedEntry #-}
toIndexedEntry :: DynamicTable -> Index -> IO Entry
toIndexedEntry :: DynamicTable -> Index -> IO Entry
toIndexedEntry DynamicTable
dyntbl Index
idx
  | Index
idx Index -> Index -> Bool
forall a. Ord a => a -> a -> Bool
<= Index
0               = DecodeError -> IO Entry
forall e a. Exception e => e -> IO a
throwIO (DecodeError -> IO Entry) -> DecodeError -> IO Entry
forall a b. (a -> b) -> a -> b
$ Index -> DecodeError
IndexOverrun Index
idx
  | Index
idx Index -> Index -> Bool
forall a. Ord a => a -> a -> Bool
<= Index
staticTableSize = Entry -> IO Entry
forall (m :: * -> *) a. Monad m => a -> m a
return (Entry -> IO Entry) -> Entry -> IO Entry
forall a b. (a -> b) -> a -> b
$ Index -> Entry
toStaticEntry Index
idx
  | Bool
otherwise              = DynamicTable -> Index -> IO Entry
toDynamicEntry DynamicTable
dyntbl Index
idx

-- For encoder
{-# INLINE fromHIndexToIndex #-}
fromHIndexToIndex :: DynamicTable -> HIndex -> IO Index
fromHIndexToIndex :: DynamicTable -> HIndex -> IO Index
fromHIndexToIndex DynamicTable
_ (SIndex Index
idx) = Index -> IO Index
forall (m :: * -> *) a. Monad m => a -> m a
return Index
idx
fromHIndexToIndex DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
..} (DIndex Index
didx) = do
    Index
maxN <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxNumOfEntries
    Index
off <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
offset
    Index
x <- Index -> Index -> IO Index
adj Index
maxN (Index
didx Index -> Index -> Index
forall a. Num a => a -> a -> a
- Index
off)
    Index -> IO Index
forall (m :: * -> *) a. Monad m => a -> m a
return (Index -> IO Index) -> Index -> IO Index
forall a b. (a -> b) -> a -> b
$ Index
x Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
staticTableSize

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

type Table = IOArray Index Entry

{-
        offset
        v
   +-+-+-+-+-+-+-+-+
   | | | |z|y|x| | |
   +-+-+-+-+-+-+-+-+
          1 2 3      (numOfEntries = 3)

After insertion:

      offset
      v
   +-+-+-+-+-+-+-+-+
   | | |w|z|y|x| | |
   +-+-+-+-+-+-+-+-+
        1 2 3 4      (numOfEntries = 4)
-}

data CodeInfo =
    EncodeInfo RevIndex -- Reverse index
               -- The value informed by SETTINGS_HEADER_TABLE_SIZE.
               -- If 'Nothing', dynamic table size update is not necessary.
               -- Otherwise, dynamic table size update is sent
               -- and this value should be set to 'Nothing'.
               (IORef (Maybe Size))
  | DecodeInfo HuffmanDecoder
               (IORef Size)  -- The limit size

-- | Type for dynamic table.
data DynamicTable = DynamicTable {
    DynamicTable -> CodeInfo
codeInfo :: CodeInfo
  -- | An array
  , DynamicTable -> IORef Table
circularTable :: IORef Table
  -- | Start point
  , DynamicTable -> IORef Index
offset :: IORef Index
  -- | The current number of entries
  , DynamicTable -> IORef Index
numOfEntries :: IORef Int
  -- | The size of the array
  , DynamicTable -> IORef Index
maxNumOfEntries :: IORef Int
  -- | The current dynamic table size (defined in HPACK)
  , DynamicTable -> IORef Index
dynamicTableSize :: IORef Size
  -- | The max dynamic table size (defined in HPACK)
  , DynamicTable -> IORef Index
maxDynamicTableSize :: IORef Size
  }

{-# INLINE adj #-}
adj :: Int -> Int -> IO Int
adj :: Index -> Index -> IO Index
adj Index
maxN Index
x
  | Index
maxN Index -> Index -> Bool
forall a. Eq a => a -> a -> Bool
== Index
0 = DecodeError -> IO Index
forall e a. Exception e => e -> IO a
throwIO DecodeError
TooSmallTableSize
  | Bool
otherwise = let ret :: Index
ret = (Index
x Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
maxN) Index -> Index -> Index
forall a. Integral a => a -> a -> a
`mod` Index
maxN
                in Index -> IO Index
forall (m :: * -> *) a. Monad m => a -> m a
return Index
ret

huffmanDecoder :: DynamicTable -> HuffmanDecoder
huffmanDecoder :: DynamicTable -> HuffmanDecoder
huffmanDecoder DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = HuffmanDecoder
dec
  where
    DecodeInfo HuffmanDecoder
dec IORef Index
_ = CodeInfo
codeInfo

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

-- | Printing 'DynamicTable'.
printDynamicTable :: DynamicTable -> IO ()
printDynamicTable :: DynamicTable -> IO ()
printDynamicTable DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Index
maxN <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxNumOfEntries
    Index
off <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
offset
    Index
n <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
numOfEntries
    let beg :: Index
beg = Index
off Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
1
        end :: Index
end = Index
off Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
n
    Table
tbl <- IORef Table -> IO Table
forall a. IORef a -> IO a
readIORef IORef Table
circularTable
    [Entry]
es <- (Index -> IO Entry) -> [Index] -> IO [Entry]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (Index -> Index -> IO Index
adj Index
maxN (Index -> IO Index) -> (Index -> IO Entry) -> Index -> IO Entry
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> Table -> Index -> IO Entry
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Index -> m e
unsafeRead Table
tbl) [Index
beg .. Index
end]
    let ts :: [(Index, Entry)]
ts = [Index] -> [Entry] -> [(Index, Entry)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Index
1..] [Entry]
es
    ((Index, Entry) -> IO ()) -> [(Index, Entry)] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Index, Entry) -> IO ()
printEntry [(Index, Entry)]
ts
    Index
dsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
dynamicTableSize
    Index
maxdsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxDynamicTableSize
    String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ String
"      Table size: " String -> String -> String
forall a. [a] -> [a] -> [a]
++ Index -> String
forall a. Show a => a -> String
show Index
dsize String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"/" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Index -> String
forall a. Show a => a -> String
show Index
maxdsize

printEntry :: (Index,Entry) -> IO ()
printEntry :: (Index, Entry) -> IO ()
printEntry (Index
i,Entry
e) = do
    String -> IO ()
putStr String
"[ "
    String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Index -> String
forall a. Show a => a -> String
show Index
i
    String -> IO ()
putStr String
"] (s = "
    String -> IO ()
putStr (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$ Index -> String
forall a. Show a => a -> String
show (Index -> String) -> Index -> String
forall a b. (a -> b) -> a -> b
$ Entry -> Index
entrySize Entry
e
    String -> IO ()
putStr String
") "
    ByteString -> IO ()
BS.putStr (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Entry -> ByteString
entryHeaderName Entry
e
    String -> IO ()
putStr String
": "
    ByteString -> IO ()
BS.putStrLn (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Entry -> ByteString
entryHeaderValue Entry
e

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

isDynamicTableEmpty :: DynamicTable -> IO Bool
isDynamicTableEmpty :: DynamicTable -> IO Bool
isDynamicTableEmpty DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Index
n <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
numOfEntries
    Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Index
n Index -> Index -> Bool
forall a. Eq a => a -> a -> Bool
== Index
0

isSuitableSize :: Size -> DynamicTable -> IO Bool
isSuitableSize :: Index -> DynamicTable -> IO Bool
isSuitableSize Index
siz DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    let DecodeInfo HuffmanDecoder
_ IORef Index
limref = CodeInfo
codeInfo
    Index
lim <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
limref
    Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Index
siz Index -> Index -> Bool
forall a. Ord a => a -> a -> Bool
<= Index
lim

data TableSizeAction = Keep | Change Size | Ignore Size

needChangeTableSize :: DynamicTable -> IO TableSizeAction
needChangeTableSize :: DynamicTable -> IO TableSizeAction
needChangeTableSize DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    let EncodeInfo RevIndex
_ IORef (Maybe Index)
limref = CodeInfo
codeInfo
    Maybe Index
mlim <- IORef (Maybe Index) -> IO (Maybe Index)
forall a. IORef a -> IO a
readIORef IORef (Maybe Index)
limref
    Index
maxsiz <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxDynamicTableSize
    TableSizeAction -> IO TableSizeAction
forall (m :: * -> *) a. Monad m => a -> m a
return (TableSizeAction -> IO TableSizeAction)
-> TableSizeAction -> IO TableSizeAction
forall a b. (a -> b) -> a -> b
$ case Maybe Index
mlim of
        Maybe Index
Nothing          -> TableSizeAction
Keep
        Just Index
lim
          | Index
lim Index -> Index -> Bool
forall a. Ord a => a -> a -> Bool
< Index
maxsiz -> Index -> TableSizeAction
Change Index
lim
          | Bool
otherwise    -> Index -> TableSizeAction
Ignore Index
maxsiz

-- | When SETTINGS_HEADER_TABLE_SIZE is received from a peer,
--   its value should be set by this function.
setLimitForEncoding :: Size -> DynamicTable -> IO ()
setLimitForEncoding :: Index -> DynamicTable -> IO ()
setLimitForEncoding Index
siz DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    let EncodeInfo RevIndex
_ IORef (Maybe Index)
limref = CodeInfo
codeInfo
    IORef (Maybe Index) -> Maybe Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe Index)
limref (Maybe Index -> IO ()) -> Maybe Index -> IO ()
forall a b. (a -> b) -> a -> b
$ Index -> Maybe Index
forall a. a -> Maybe a
Just Index
siz

resetLimitForEncoding :: DynamicTable -> IO ()
resetLimitForEncoding :: DynamicTable -> IO ()
resetLimitForEncoding DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    let EncodeInfo RevIndex
_ IORef (Maybe Index)
limref = CodeInfo
codeInfo
    IORef (Maybe Index) -> Maybe Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef (Maybe Index)
limref Maybe Index
forall a. Maybe a
Nothing

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

-- | Creating 'DynamicTable' for encoding.
newDynamicTableForEncoding :: Size -- ^ The dynamic table size
                           -> IO DynamicTable
newDynamicTableForEncoding :: Index -> IO DynamicTable
newDynamicTableForEncoding Index
maxsiz = do
    RevIndex
rev <- IO RevIndex
newRevIndex
    IORef (Maybe Index)
lim <- Maybe Index -> IO (IORef (Maybe Index))
forall a. a -> IO (IORef a)
newIORef Maybe Index
forall a. Maybe a
Nothing
    let info :: CodeInfo
info = RevIndex -> IORef (Maybe Index) -> CodeInfo
EncodeInfo RevIndex
rev IORef (Maybe Index)
lim
    Index -> CodeInfo -> IO DynamicTable
newDynamicTable Index
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 :: Index -> Index -> IO DynamicTable
newDynamicTableForDecoding Index
maxsiz Index
huftmpsiz = do
    IORef Index
lim <- Index -> IO (IORef Index)
forall a. a -> IO (IORef a)
newIORef Index
maxsiz
    ForeignPtr Word8
buf <- Index -> IO (ForeignPtr Word8)
forall a. Index -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes Index
huftmpsiz
    let decoder :: HuffmanDecoder
decoder = ForeignPtr Word8 -> Index -> HuffmanDecoder
decodeH ForeignPtr Word8
buf Index
huftmpsiz
        info :: CodeInfo
info = HuffmanDecoder -> IORef Index -> CodeInfo
DecodeInfo HuffmanDecoder
decoder IORef Index
lim
    Index -> CodeInfo -> IO DynamicTable
newDynamicTable Index
maxsiz CodeInfo
info

newDynamicTable :: Size -> CodeInfo -> IO DynamicTable
newDynamicTable :: Index -> CodeInfo -> IO DynamicTable
newDynamicTable Index
maxsiz CodeInfo
info = do
    Table
tbl <- (Index, Index) -> Entry -> IO Table
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> e -> m (a i e)
newArray (Index
0,Index
end) Entry
dummyEntry
    CodeInfo
-> IORef Table
-> IORef Index
-> IORef Index
-> IORef Index
-> IORef Index
-> IORef Index
-> DynamicTable
DynamicTable CodeInfo
info (IORef Table
 -> IORef Index
 -> IORef Index
 -> IORef Index
 -> IORef Index
 -> IORef Index
 -> DynamicTable)
-> IO (IORef Table)
-> IO
     (IORef Index
      -> IORef Index
      -> IORef Index
      -> IORef Index
      -> IORef Index
      -> DynamicTable)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Table -> IO (IORef Table)
forall a. a -> IO (IORef a)
newIORef Table
tbl     -- circularTable
                      IO
  (IORef Index
   -> IORef Index
   -> IORef Index
   -> IORef Index
   -> IORef Index
   -> DynamicTable)
-> IO (IORef Index)
-> IO
     (IORef Index
      -> IORef Index -> IORef Index -> IORef Index -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Index -> IO (IORef Index)
forall a. a -> IO (IORef a)
newIORef Index
end     -- offset
                      IO
  (IORef Index
   -> IORef Index -> IORef Index -> IORef Index -> DynamicTable)
-> IO (IORef Index)
-> IO (IORef Index -> IORef Index -> IORef Index -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Index -> IO (IORef Index)
forall a. a -> IO (IORef a)
newIORef Index
0       -- numOfEntries
                      IO (IORef Index -> IORef Index -> IORef Index -> DynamicTable)
-> IO (IORef Index)
-> IO (IORef Index -> IORef Index -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Index -> IO (IORef Index)
forall a. a -> IO (IORef a)
newIORef Index
maxN    -- maxNumOfEntries
                      IO (IORef Index -> IORef Index -> DynamicTable)
-> IO (IORef Index) -> IO (IORef Index -> DynamicTable)
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Index -> IO (IORef Index)
forall a. a -> IO (IORef a)
newIORef Index
0       -- dynamicTableSize
                      IO (IORef Index -> DynamicTable)
-> IO (IORef Index) -> IO DynamicTable
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Index -> IO (IORef Index)
forall a. a -> IO (IORef a)
newIORef Index
maxsiz  -- maxDynamicTableSize
  where
    maxN :: Index
maxN = Index -> Index
maxNumbers Index
maxsiz
    end :: Index
end = Index
maxN Index -> Index -> Index
forall a. Num a => a -> a -> a
- Index
1

-- | Renewing 'DynamicTable' with necessary entries copied.
renewDynamicTable :: Size -> DynamicTable -> IO ()
renewDynamicTable :: Index -> DynamicTable -> IO ()
renewDynamicTable Index
0 DynamicTable
_ = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return () -- FIXME: handle case 'Max table size = 0'.
renewDynamicTable Index
maxsiz dyntbl :: DynamicTable
dyntbl@DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Bool
renew <- DynamicTable -> Index -> IO Bool
shouldRenew DynamicTable
dyntbl Index
maxsiz
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
renew (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        [Entry]
entries <- DynamicTable -> IO [Entry]
getEntries DynamicTable
dyntbl
        let maxN :: Index
maxN = Index -> Index
maxNumbers Index
maxsiz
            end :: Index
end = Index
maxN Index -> Index -> Index
forall a. Num a => a -> a -> a
- Index
1
        Table
newtbl <- (Index, Index) -> Entry -> IO Table
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
(i, i) -> e -> m (a i e)
newArray (Index
0,Index
end) Entry
dummyEntry
        IORef Table -> Table -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Table
circularTable Table
newtbl
        IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
offset Index
end
        IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
numOfEntries Index
0
        IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
maxNumOfEntries Index
maxN
        IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
dynamicTableSize Index
0
        IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
maxDynamicTableSize Index
maxsiz
        case CodeInfo
codeInfo of
            EncodeInfo RevIndex
rev IORef (Maybe Index)
_ -> RevIndex -> IO ()
renewRevIndex RevIndex
rev
            CodeInfo
_                -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
        DynamicTable -> [Entry] -> IO ()
copyEntries DynamicTable
dyntbl [Entry]
entries

getEntries :: DynamicTable -> IO [Entry]
getEntries :: DynamicTable -> IO [Entry]
getEntries DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Index
maxN <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxNumOfEntries
    Index
off <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
offset
    Index
n <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
numOfEntries
    Table
table <- IORef Table -> IO Table
forall a. IORef a -> IO a
readIORef IORef Table
circularTable
    let readTable :: Index -> IO Entry
readTable Index
i = Index -> Index -> IO Index
adj Index
maxN (Index
off Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
i) IO Index -> (Index -> IO Entry) -> IO Entry
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Table -> Index -> IO Entry
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Index -> m e
unsafeRead Table
table
    [Index] -> (Index -> IO Entry) -> IO [Entry]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Index
1 .. Index
n] Index -> IO Entry
readTable

copyEntries :: DynamicTable -> [Entry] -> IO ()
copyEntries :: DynamicTable -> [Entry] -> IO ()
copyEntries DynamicTable
_                           [] = () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
copyEntries dyntbl :: DynamicTable
dyntbl@DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} (Entry
e:[Entry]
es) = do
    Index
dsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
dynamicTableSize
    Index
maxdsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxDynamicTableSize
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Index
dsize Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Entry -> Index
entrySize Entry
e Index -> Index -> Bool
forall a. Ord a => a -> a -> Bool
<= Index
maxdsize) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        Entry -> DynamicTable -> IO ()
insertEnd Entry
e DynamicTable
dyntbl
        DynamicTable -> [Entry] -> IO ()
copyEntries DynamicTable
dyntbl [Entry]
es

-- | Is the size of 'DynamicTable' really changed?
shouldRenew :: DynamicTable -> Size -> IO Bool
shouldRenew :: DynamicTable -> Index -> IO Bool
shouldRenew DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} Index
maxsiz = do
    Index
maxdsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxDynamicTableSize
    Bool -> IO Bool
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool -> IO Bool) -> Bool -> IO Bool
forall a b. (a -> b) -> a -> b
$ Index
maxdsize Index -> Index -> Bool
forall a. Eq a => a -> a -> Bool
/= Index
maxsiz

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

-- | Creating 'DynamicTable' for encoding,
--   performing the action and
--   clearing the 'DynamicTable'.
withDynamicTableForEncoding :: Size -- ^ The dynamic table size
                            -> (DynamicTable -> IO a)
                            -> IO a
withDynamicTableForEncoding :: Index -> (DynamicTable -> IO a) -> IO a
withDynamicTableForEncoding Index
maxsiz DynamicTable -> IO a
action =
    Index -> IO DynamicTable
newDynamicTableForEncoding Index
maxsiz IO DynamicTable -> (DynamicTable -> IO a) -> IO a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DynamicTable -> IO a
action

-- | Creating 'DynamicTable' for decoding,
--   performing the action and
--   clearing the 'DynamicTable'.
withDynamicTableForDecoding :: Size -- ^ The dynamic table size
                            -> Size -- ^ The size of temporary buffer for Huffman
                            -> (DynamicTable -> IO a)
                            -> IO a
withDynamicTableForDecoding :: Index -> Index -> (DynamicTable -> IO a) -> IO a
withDynamicTableForDecoding Index
maxsiz Index
huftmpsiz DynamicTable -> IO a
action =
    Index -> Index -> IO DynamicTable
newDynamicTableForDecoding Index
maxsiz Index
huftmpsiz IO DynamicTable -> (DynamicTable -> IO a) -> IO a
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= DynamicTable -> IO a
action

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

-- | Inserting 'Entry' to 'DynamicTable'.
--   New 'DynamicTable', the largest new 'Index'
--   and a set of dropped OLD 'Index'
--   are returned.
insertEntry :: Entry -> DynamicTable -> IO ()
insertEntry :: Entry -> DynamicTable -> IO ()
insertEntry Entry
e dyntbl :: DynamicTable
dyntbl@DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Entry -> DynamicTable -> IO ()
insertFront Entry
e DynamicTable
dyntbl
    [Entry]
es <- DynamicTable -> IO [Entry]
adjustTableSize DynamicTable
dyntbl
    case CodeInfo
codeInfo of
        EncodeInfo RevIndex
rev IORef (Maybe Index)
_ -> [Entry] -> RevIndex -> IO ()
deleteRevIndexList [Entry]
es RevIndex
rev
        CodeInfo
_                -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

insertFront :: Entry -> DynamicTable -> IO ()
insertFront :: Entry -> DynamicTable -> IO ()
insertFront Entry
e DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Index
maxN <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxNumOfEntries
    Index
off <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
offset
    Index
n <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
numOfEntries
    Index
dsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
dynamicTableSize
    Table
table <- IORef Table -> IO Table
forall a. IORef a -> IO a
readIORef IORef Table
circularTable
    let i :: Index
i = Index
off
        dsize' :: Index
dsize' = Index
dsize Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Entry -> Index
entrySize Entry
e
    Index
off' <- Index -> Index -> IO Index
adj Index
maxN (Index
off Index -> Index -> Index
forall a. Num a => a -> a -> a
- Index
1)
    Table -> Index -> Entry -> IO ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Index -> e -> m ()
unsafeWrite Table
table Index
i Entry
e
    IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
offset Index
off'
    IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
numOfEntries (Index -> IO ()) -> Index -> IO ()
forall a b. (a -> b) -> a -> b
$ Index
n Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
1
    IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
dynamicTableSize Index
dsize'
    case CodeInfo
codeInfo of
        EncodeInfo RevIndex
rev IORef (Maybe Index)
_ -> Entry -> HIndex -> RevIndex -> IO ()
insertRevIndex Entry
e (Index -> HIndex
DIndex Index
i) RevIndex
rev
        CodeInfo
_                -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

adjustTableSize :: DynamicTable -> IO [Entry]
adjustTableSize :: DynamicTable -> IO [Entry]
adjustTableSize dyntbl :: DynamicTable
dyntbl@DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = [Entry] -> IO [Entry]
adjust []
  where
    adjust :: [Entry] -> IO [Entry]
    adjust :: [Entry] -> IO [Entry]
adjust [Entry]
es = do
        Index
dsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
dynamicTableSize
        Index
maxdsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxDynamicTableSize
        if Index
dsize Index -> Index -> Bool
forall a. Ord a => a -> a -> Bool
<= Index
maxdsize then
            [Entry] -> IO [Entry]
forall (m :: * -> *) a. Monad m => a -> m a
return [Entry]
es
          else do
            Entry
e <- DynamicTable -> IO Entry
removeEnd DynamicTable
dyntbl
            [Entry] -> IO [Entry]
adjust (Entry
eEntry -> [Entry] -> [Entry]
forall a. a -> [a] -> [a]
:[Entry]
es)

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

insertEnd :: Entry -> DynamicTable -> IO ()
insertEnd :: Entry -> DynamicTable -> IO ()
insertEnd Entry
e DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Index
maxN <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxNumOfEntries
    Index
off <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
offset
    Index
n <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
numOfEntries
    Index
dsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
dynamicTableSize
    Table
table <- IORef Table -> IO Table
forall a. IORef a -> IO a
readIORef IORef Table
circularTable
    Index
i <- Index -> Index -> IO Index
adj Index
maxN (Index
off Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
n Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
1)
    let dsize' :: Index
dsize' = Index
dsize Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Entry -> Index
entrySize Entry
e
    Table -> Index -> Entry -> IO ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Index -> e -> m ()
unsafeWrite Table
table Index
i Entry
e
    IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
numOfEntries (Index -> IO ()) -> Index -> IO ()
forall a b. (a -> b) -> a -> b
$ Index
n Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
1
    IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
dynamicTableSize Index
dsize'
    case CodeInfo
codeInfo of
        EncodeInfo RevIndex
rev IORef (Maybe Index)
_ -> Entry -> HIndex -> RevIndex -> IO ()
insertRevIndex Entry
e (Index -> HIndex
DIndex Index
i) RevIndex
rev
        CodeInfo
_                -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

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

removeEnd :: DynamicTable -> IO Entry
removeEnd :: DynamicTable -> IO Entry
removeEnd DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = do
    Index
maxN <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxNumOfEntries
    Index
off <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
offset
    Index
n <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
numOfEntries
    Index
i <- Index -> Index -> IO Index
adj Index
maxN (Index
off Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
n)
    Table
table <- IORef Table -> IO Table
forall a. IORef a -> IO a
readIORef IORef Table
circularTable
    Entry
e <- Table -> Index -> IO Entry
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Index -> m e
unsafeRead Table
table Index
i
    Table -> Index -> Entry -> IO ()
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Index -> e -> m ()
unsafeWrite Table
table Index
i Entry
dummyEntry -- let the entry GCed
    Index
dsize <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
dynamicTableSize
    let dsize' :: Index
dsize' = Index
dsize Index -> Index -> Index
forall a. Num a => a -> a -> a
- Entry -> Index
entrySize Entry
e
    IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
numOfEntries (Index
n Index -> Index -> Index
forall a. Num a => a -> a -> a
- Index
1)
    IORef Index -> Index -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Index
dynamicTableSize Index
dsize'
    Entry -> IO Entry
forall (m :: * -> *) a. Monad m => a -> m a
return Entry
e

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

{-# INLINE toDynamicEntry #-}
toDynamicEntry :: DynamicTable -> Index -> IO Entry
toDynamicEntry :: DynamicTable -> Index -> IO Entry
toDynamicEntry DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} Index
idx = do
    Index
maxN <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
maxNumOfEntries
    Index
off <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
offset
    Index
n <- IORef Index -> IO Index
forall a. IORef a -> IO a
readIORef IORef Index
numOfEntries
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Index
idx Index -> Index -> Bool
forall a. Ord a => a -> a -> Bool
> Index
n Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
staticTableSize) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ DecodeError -> IO ()
forall e a. Exception e => e -> IO a
throwIO (DecodeError -> IO ()) -> DecodeError -> IO ()
forall a b. (a -> b) -> a -> b
$ Index -> DecodeError
IndexOverrun Index
idx
    Index
didx <- Index -> Index -> IO Index
adj Index
maxN (Index
idx Index -> Index -> Index
forall a. Num a => a -> a -> a
+ Index
off Index -> Index -> Index
forall a. Num a => a -> a -> a
- Index
staticTableSize)
    Table
table <- IORef Table -> IO Table
forall a. IORef a -> IO a
readIORef IORef Table
circularTable
    Table -> Index -> IO Entry
forall (a :: * -> * -> *) e (m :: * -> *) i.
(MArray a e m, Ix i) =>
a i e -> Index -> m e
unsafeRead Table
table Index
didx

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

{-# INLINE getRevIndex #-}
getRevIndex :: DynamicTable-> RevIndex
getRevIndex :: DynamicTable -> RevIndex
getRevIndex DynamicTable{IORef Index
IORef Table
CodeInfo
maxDynamicTableSize :: IORef Index
dynamicTableSize :: IORef Index
maxNumOfEntries :: IORef Index
numOfEntries :: IORef Index
offset :: IORef Index
circularTable :: IORef Table
codeInfo :: CodeInfo
maxDynamicTableSize :: DynamicTable -> IORef Index
dynamicTableSize :: DynamicTable -> IORef Index
maxNumOfEntries :: DynamicTable -> IORef Index
numOfEntries :: DynamicTable -> IORef Index
offset :: DynamicTable -> IORef Index
circularTable :: DynamicTable -> IORef Table
codeInfo :: DynamicTable -> CodeInfo
..} = RevIndex
rev
  where
    EncodeInfo RevIndex
rev IORef (Maybe Index)
_ = CodeInfo
codeInfo