{-# LANGUAGE OverloadedStrings #-}

module Network.HPACK.Table.Entry (
    -- * Type
    Size,
    Entry (..),
    Header, -- re-exporting
    HeaderName, -- re-exporting
    HeaderValue, -- re-exporting
    Index, -- re-exporting

    -- * Header and Entry
    toEntry,
    toEntryToken,

    -- * Getters
    entrySize,
    entryTokenHeader,
    entryToken,
    entryHeaderName,
    entryHeaderValue,

    -- * For initialization
    dummyEntry,
    maxNumbers,
) where

import qualified Data.ByteString as BS
import Network.HPACK.Token
import Network.HPACK.Types

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

-- | Size in bytes.
type Size = Int

-- | Type for table entry. Size includes the 32 bytes magic number.
data Entry = Entry Size Token HeaderValue deriving (Size -> Entry -> ShowS
[Entry] -> ShowS
Entry -> String
(Size -> Entry -> ShowS)
-> (Entry -> String) -> ([Entry] -> ShowS) -> Show Entry
forall a.
(Size -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Size -> Entry -> ShowS
showsPrec :: Size -> Entry -> ShowS
$cshow :: Entry -> String
show :: Entry -> String
$cshowList :: [Entry] -> ShowS
showList :: [Entry] -> ShowS
Show)

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

headerSizeMagicNumber :: Size
headerSizeMagicNumber :: Size
headerSizeMagicNumber = Size
32

headerSize :: Header -> Size
headerSize :: Header -> Size
headerSize (HeaderValue
k, HeaderValue
v) =
    HeaderValue -> Size
BS.length HeaderValue
k
        Size -> Size -> Size
forall a. Num a => a -> a -> a
+ HeaderValue -> Size
BS.length HeaderValue
v
        Size -> Size -> Size
forall a. Num a => a -> a -> a
+ Size
headerSizeMagicNumber

headerSize' :: Token -> HeaderValue -> Size
headerSize' :: Token -> HeaderValue -> Size
headerSize' Token
t HeaderValue
v =
    HeaderValue -> Size
BS.length (Token -> HeaderValue
tokenFoldedKey Token
t)
        Size -> Size -> Size
forall a. Num a => a -> a -> a
+ HeaderValue -> Size
BS.length HeaderValue
v
        Size -> Size -> Size
forall a. Num a => a -> a -> a
+ Size
headerSizeMagicNumber

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

-- | From 'Header' to 'Entry'.
toEntry :: Header -> Entry
toEntry :: Header -> Entry
toEntry kv :: Header
kv@(HeaderValue
k, HeaderValue
v) = Size -> Token -> HeaderValue -> Entry
Entry Size
siz Token
t HeaderValue
v
  where
    t :: Token
t = HeaderValue -> Token
toToken HeaderValue
k
    siz :: Size
siz = Header -> Size
headerSize Header
kv

toEntryToken :: Token -> HeaderValue -> Entry
toEntryToken :: Token -> HeaderValue -> Entry
toEntryToken Token
t HeaderValue
v = Size -> Token -> HeaderValue -> Entry
Entry Size
siz Token
t HeaderValue
v
  where
    siz :: Size
siz = Token -> HeaderValue -> Size
headerSize' Token
t HeaderValue
v

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

-- | Getting the size of 'Entry'.
entrySize :: Entry -> Size
entrySize :: Entry -> Size
entrySize (Entry Size
siz Token
_ HeaderValue
_) = Size
siz

-- | Getting 'TokenHeader'.
entryTokenHeader :: Entry -> TokenHeader
entryTokenHeader :: Entry -> TokenHeader
entryTokenHeader (Entry Size
_ Token
t HeaderValue
v) = (Token
t, HeaderValue
v)

-- | Getting 'Token'.
entryToken :: Entry -> Token
entryToken :: Entry -> Token
entryToken (Entry Size
_ Token
t HeaderValue
_) = Token
t

-- | Getting 'HeaderName'.
entryHeaderName :: Entry -> HeaderName
entryHeaderName :: Entry -> HeaderValue
entryHeaderName (Entry Size
_ Token
t HeaderValue
_) = Token -> HeaderValue
tokenFoldedKey Token
t

-- | Getting 'HeaderValue'.
entryHeaderValue :: Entry -> HeaderValue
entryHeaderValue :: Entry -> HeaderValue
entryHeaderValue (Entry Size
_ Token
_ HeaderValue
v) = HeaderValue
v

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

-- | Dummy 'Entry' to initialize a dynamic table.
dummyEntry :: Entry
dummyEntry :: Entry
dummyEntry = Size -> Token -> HeaderValue -> Entry
Entry Size
0 Token
tokenMax HeaderValue
"dummyValue"

-- | How many entries can be stored in a dynamic table?
maxNumbers :: Size -> Int
maxNumbers :: Size -> Size
maxNumbers Size
siz = Size
siz Size -> Size -> Size
forall a. Integral a => a -> a -> a
`div` Size
headerSizeMagicNumber