    {-# LANGUAGE OverloadedStrings #-}

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

        -- * Header and Entry
        toEntry,
        toEntryToken,

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

        -- * For initialization
        dummyEntry,
        maxNumbers,
    ) where

    import qualified Data.ByteString as BS
    import Network.HPACK.Types
    import Network.HTTP.Semantics

    import Imports

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

    -- | Size in bytes.
    type Size = Int

    -- | Type for table entry. Size includes the 32 bytes magic number.
    data Entry = Entry Size Token FieldValue 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 (HeaderName
    k, FieldValue
    v) =
        FieldValue -> Size
    BS.length (HeaderName -> FieldValue
    forall s. CI s -> s
    foldedCase HeaderName
    k)
            Size -> Size -> Size
    forall a. Num a => a -> a -> a
    + FieldValue -> Size
    BS.length FieldValue
    v
            Size -> Size -> Size
    forall a. Num a => a -> a -> a
    + Size
    headerSizeMagicNumber

    headerSize' :: Token -> FieldValue -> Size
    headerSize' :: Token -> FieldValue -> Size
    headerSize' Token
    t FieldValue
    v =
        FieldValue -> Size
    BS.length (Token -> FieldValue
    tokenFoldedKey Token
    t)
            Size -> Size -> Size
    forall a. Num a => a -> a -> a
    + FieldValue -> Size
    BS.length FieldValue
    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@(HeaderName
    k, FieldValue
    v) = Size -> Token -> FieldValue -> Entry
    Entry Size
    siz Token
    t FieldValue
    v
      where
        t :: Token
    t = FieldValue -> Token
    toToken (FieldValue -> Token) -> FieldValue -> Token
    forall a b. (a -> b) -> a -> b
    $ HeaderName -> FieldValue
    forall s. CI s -> s
    foldedCase HeaderName
    k
        siz :: Size
    siz = Header -> Size
    headerSize Header
    kv

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

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

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

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

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

    -- | Getting 'HeaderName'.
    entryHeaderName :: Entry -> HeaderName
    entryHeaderName :: Entry -> HeaderName
    entryHeaderName (Entry Size
    _ Token
    t FieldValue
    _) = Token -> HeaderName
    tokenKey Token
    t -- xxx

    -- | Getting 'FieldValue'.
    entryFieldValue :: Entry -> FieldValue
    entryFieldValue :: Entry -> FieldValue
    entryFieldValue (Entry Size
    _ Token
    _ FieldValue
    v) = FieldValue
    v

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

    -- | Dummy 'Entry' to initialize a dynamic table.
    dummyEntry :: Entry
    dummyEntry :: Entry
    dummyEntry = Size -> Token -> FieldValue -> Entry
    Entry Size
    0 Token
    tokenMax FieldValue
    "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