module Network.HPACK.HeaderBlock.From (
fromHeaderBlock
, decodeStep
) where
import Control.Applicative ((<$>))
import Network.HPACK.Context
import Network.HPACK.HeaderBlock.HeaderField
import Network.HPACK.Table
fromHeaderBlock :: Context
-> HeaderBlock
-> IO (Context, HeaderSet)
fromHeaderBlock !ctx (r:rs) = decodeStep ctx r >>= \cx -> fromHeaderBlock cx rs
fromHeaderBlock !ctx [] = decodeFinal ctx
decodeStep :: Context -> HeaderField -> IO Context
decodeStep !ctx (Indexed idx)
| idx == 0 = clearRefSets ctx
| isPresent = removeRef ctx idx
| otherwise = do
w <- whichTable idx ctx
case w of
(InStaticTable, e) -> newEntry ctx e
(InHeaderTable, e) -> pushRef ctx idx e
where
isPresent = idx `isPresentIn` ctx
decodeStep !ctx (Literal NotAdd naming v) = do
k <- fromNaming naming ctx
emitOnly ctx (k,v)
decodeStep !ctx (Literal Add naming v) = do
k <- fromNaming naming ctx
newEntry ctx $ toEntry (k,v)
decodeFinal :: Context -> IO (Context, HeaderSet)
decodeFinal ctx = do
!ctx' <- emitNotEmitted ctx
let !hs = getHeaderSet ctx'
!ctx'' = clearHeaderSet ctx'
return (ctx'', hs)
fromNaming :: Naming -> Context -> IO HeaderName
fromNaming (Lit k) _ = return k
fromNaming (Idx idx) ctx = entryHeaderName <$> getEntry idx ctx