{-# LANGUAGE BinaryLiterals #-}
module Network.QPACK.HeaderBlock.Prefix (
encodePrefix,
decodePrefix,
encodeRequiredInsertCount,
decodeRequiredInsertCount,
encodeBase,
decodeBase,
) where
import qualified Control.Exception as E
import Network.ByteOrder
import Network.HPACK.Internal (decodeI, encodeI)
import Imports
import Network.QPACK.Error
import Network.QPACK.Table
import Network.QPACK.Types
encodeRequiredInsertCount :: Int -> RequiredInsertCount -> Int
encodeRequiredInsertCount :: Int -> RequiredInsertCount -> Int
encodeRequiredInsertCount Int
_ RequiredInsertCount
0 = Int
0
encodeRequiredInsertCount Int
maxEntries (RequiredInsertCount Int
reqInsertCount) =
(Int
reqInsertCount Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` (Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
maxEntries)) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
decodeRequiredInsertCount
:: Int -> InsertionPoint -> Int -> RequiredInsertCount
decodeRequiredInsertCount :: Int -> InsertionPoint -> Int -> RequiredInsertCount
decodeRequiredInsertCount Int
_ InsertionPoint
_ Int
0 = RequiredInsertCount
0
decodeRequiredInsertCount Int
0 InsertionPoint
_ Int
n = Int -> RequiredInsertCount
RequiredInsertCount (Int
n Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
decodeRequiredInsertCount Int
maxEntries (InsertionPoint Int
totalNumberOfInserts) Int
encodedInsertCount
| Int
encodedInsertCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
fullRange = DecodeError -> RequiredInsertCount
forall a e. Exception e => e -> a
E.throw DecodeError
IllegalInsertCount
| Int
reqInsertCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
maxValue Bool -> Bool -> Bool
&& Int
reqInsertCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
fullRange =
DecodeError -> RequiredInsertCount
forall a e. Exception e => e -> a
E.throw DecodeError
IllegalInsertCount
| Int
reqInsertCount Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
maxValue = Int -> RequiredInsertCount
RequiredInsertCount (Int
reqInsertCount Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
fullRange)
| Bool
otherwise = Int -> RequiredInsertCount
RequiredInsertCount Int
reqInsertCount
where
fullRange :: Int
fullRange = Int
2 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
maxEntries
maxValue :: Int
maxValue = Int
totalNumberOfInserts Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
maxEntries
maxWrapped :: Int
maxWrapped = (Int
maxValue Int -> Int -> Int
forall a. Integral a => a -> a -> a
`div` Int
fullRange) Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
fullRange
reqInsertCount :: Int
reqInsertCount = Int
maxWrapped Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
encodedInsertCount Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1
encodeBase :: RequiredInsertCount -> BasePoint -> (Bool, Int)
encodeBase :: RequiredInsertCount -> BasePoint -> (Bool, Int)
encodeBase (RequiredInsertCount Int
reqInsCnt) (BasePoint Int
base)
| Int
diff Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
0 = (Bool
False, Int
diff)
| Bool
otherwise = (Bool
True, Int -> Int
forall a. Num a => a -> a
negate Int
diff Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
where
diff :: Int
diff = Int
base Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
reqInsCnt
decodeBase :: RequiredInsertCount -> Bool -> Int -> BasePoint
decodeBase :: RequiredInsertCount -> Bool -> Int -> BasePoint
decodeBase (RequiredInsertCount Int
reqInsCnt) Bool
False Int
deltaBase = Int -> BasePoint
BasePoint (Int
reqInsCnt Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
deltaBase)
decodeBase (RequiredInsertCount Int
reqInsCnt) Bool
True Int
deltaBase = Int -> BasePoint
BasePoint (Int
reqInsCnt Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
deltaBase Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1)
encodePrefix :: WriteBuffer -> DynamicTable -> IO ()
encodePrefix :: WriteBuffer -> DynamicTable -> IO ()
encodePrefix WriteBuffer
wbuf DynamicTable
dyntbl = do
WriteBuffer -> IO ()
clearWriteBuffer WriteBuffer
wbuf
Int
maxEntries <- DynamicTable -> IO Int
getMaxNumOfEntries DynamicTable
dyntbl
BasePoint
baseIndex <- DynamicTable -> IO BasePoint
getBasePoint DynamicTable
dyntbl
RequiredInsertCount
reqInsCnt <- DynamicTable -> IO RequiredInsertCount
getRequiredInsertCount DynamicTable
dyntbl
DynamicTable -> IO () -> IO ()
qpackDebug DynamicTable
dyntbl (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ RequiredInsertCount -> IO ()
forall a. Show a => a -> IO ()
print RequiredInsertCount
reqInsCnt
let ric :: Int
ric = Int -> RequiredInsertCount -> Int
encodeRequiredInsertCount Int
maxEntries RequiredInsertCount
reqInsCnt
WriteBuffer -> (Word8 -> Word8) -> Int -> Int -> IO ()
encodeI WriteBuffer
wbuf Word8 -> Word8
set0 Int
8 Int
ric
let (Bool
s, Int
base) = RequiredInsertCount -> BasePoint -> (Bool, Int)
encodeBase RequiredInsertCount
reqInsCnt BasePoint
baseIndex
set :: Word8 -> Word8
set
| Bool
s = Word8 -> Word8
set1
| Bool
otherwise = Word8 -> Word8
set0
WriteBuffer -> (Word8 -> Word8) -> Int -> Int -> IO ()
encodeI WriteBuffer
wbuf Word8 -> Word8
set Int
7 Int
base
decodePrefix
:: ReadBuffer -> DynamicTable -> IO (RequiredInsertCount, BasePoint, Bool)
decodePrefix :: ReadBuffer
-> DynamicTable -> IO (RequiredInsertCount, BasePoint, Bool)
decodePrefix ReadBuffer
rbuf DynamicTable
dyntbl = do
Int
maxEntries <- DynamicTable -> IO Int
getMaxNumOfEntries DynamicTable
dyntbl
InsertionPoint
totalNumberOfInserts <- DynamicTable -> IO InsertionPoint
getInsertionPoint DynamicTable
dyntbl
Word8
w8 <- ReadBuffer -> IO Word8
forall a. Readable a => a -> IO Word8
read8 ReadBuffer
rbuf
Int
ric <- Int -> Word8 -> ReadBuffer -> IO Int
decodeI Int
8 Word8
w8 ReadBuffer
rbuf
let reqInsCnt :: RequiredInsertCount
reqInsCnt = Int -> InsertionPoint -> Int -> RequiredInsertCount
decodeRequiredInsertCount Int
maxEntries InsertionPoint
totalNumberOfInserts Int
ric
Word8
w8' <- ReadBuffer -> IO Word8
forall a. Readable a => a -> IO Word8
read8 ReadBuffer
rbuf
let s :: Bool
s = Word8
w8' Word8 -> Int -> Bool
forall a. Bits a => a -> Int -> Bool
`testBit` Int
7
w8'' :: Word8
w8'' = Word8
w8' Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b01111111
Int
delta <- Int -> Word8 -> ReadBuffer -> IO Int
decodeI Int
7 Word8
w8'' ReadBuffer
rbuf
let baseIndex :: BasePoint
baseIndex = RequiredInsertCount -> Bool -> Int -> BasePoint
decodeBase RequiredInsertCount
reqInsCnt Bool
s Int
delta
DynamicTable -> IO () -> IO ()
qpackDebug DynamicTable
dyntbl (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
RequiredInsertCount -> String
forall a. Show a => a -> String
show RequiredInsertCount
reqInsCnt
String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", "
String -> String -> String
forall a. [a] -> [a] -> [a]
++ BasePoint -> String
forall a. Show a => a -> String
show BasePoint
baseIndex
String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", "
String -> String -> String
forall a. [a] -> [a] -> [a]
++ InsertionPoint -> String
forall a. Show a => a -> String
show InsertionPoint
totalNumberOfInserts
String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
", maxN "
String -> String -> String
forall a. [a] -> [a] -> [a]
++ Int -> String
forall a. Show a => a -> String
show Int
maxEntries
let needAck :: Bool
needAck = RequiredInsertCount
reqInsCnt RequiredInsertCount -> RequiredInsertCount -> Bool
forall a. Eq a => a -> a -> Bool
/= RequiredInsertCount
0
(RequiredInsertCount, BasePoint, Bool)
-> IO (RequiredInsertCount, BasePoint, Bool)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (RequiredInsertCount
reqInsCnt, BasePoint
baseIndex, Bool
needAck)