{-# LANGUAGE BinaryLiterals #-}

module Network.QPACK.HeaderBlock.Decode where

import Control.Concurrent.STM
import qualified Control.Exception as E
import qualified Data.ByteString.Char8 as BS8
import Data.CaseInsensitive
import Network.ByteOrder
import Network.HPACK.Internal (
    HuffmanDecoder,
    decodeH,
    decodeI,
    decodeS,
    decodeSimple,
    decodeSophisticated,
    entryToken,
    entryTokenHeader,
 )
import Network.HTTP.Types

import Imports
import Network.QPACK.Error
import Network.QPACK.HeaderBlock.Prefix
import Network.QPACK.Table
import Network.QPACK.Types

decodeTokenHeader
    :: DynamicTable
    -> ReadBuffer
    -> IO (TokenHeaderTable, Bool)
decodeTokenHeader :: DynamicTable -> ReadBuffer -> IO (TokenHeaderTable, Bool)
decodeTokenHeader DynamicTable
dyntbl ReadBuffer
rbuf = do
    (RequiredInsertCount
reqInsertCount, BasePoint
bp, Bool
needAck) <- ReadBuffer
-> DynamicTable -> IO (RequiredInsertCount, BasePoint, Bool)
decodePrefix ReadBuffer
rbuf DynamicTable
dyntbl
    Bool
ready <- DynamicTable -> RequiredInsertCount -> IO Bool
checkRequiredInsertCountNB DynamicTable
dyntbl RequiredInsertCount
reqInsertCount
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
ready (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        Bool
ok <- DynamicTable -> IO Bool
tryIncreaseStreams DynamicTable
dyntbl
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
ok (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ DecodeError -> IO ()
forall e a. Exception e => e -> IO a
E.throwIO DecodeError
BlockedStreamsOverflow
        DynamicTable -> RequiredInsertCount -> IO ()
checkRequiredInsertCount DynamicTable
dyntbl RequiredInsertCount
reqInsertCount
        DynamicTable -> IO ()
decreaseStreams DynamicTable
dyntbl
    DynamicTable -> RequiredInsertCount -> IO ()
checkRequiredInsertCount DynamicTable
dyntbl RequiredInsertCount
reqInsertCount
    let bufsiz :: Offset
bufsiz = Offset
2048
    ForeignPtr Word8
gcbuf <- Offset -> IO (ForeignPtr Word8)
forall a. Offset -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes Offset
2048
    let hufdec :: ReadBuffer -> Offset -> IO ByteString
hufdec = ForeignPtr Word8 -> Offset -> ReadBuffer -> Offset -> IO ByteString
decodeH ForeignPtr Word8
gcbuf Offset
bufsiz
    TokenHeaderTable
tbl <- (Word8 -> ReadBuffer -> IO TokenHeader)
-> ReadBuffer -> IO TokenHeaderTable
decodeSophisticated (DynamicTable
-> BasePoint
-> (ReadBuffer -> Offset -> IO ByteString)
-> Word8
-> ReadBuffer
-> IO TokenHeader
toTokenHeader DynamicTable
dyntbl BasePoint
bp ReadBuffer -> Offset -> IO ByteString
hufdec) ReadBuffer
rbuf
    (TokenHeaderTable, Bool) -> IO (TokenHeaderTable, Bool)
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (TokenHeaderTable
tbl, Bool
needAck)

decodeTokenHeaderS
    :: DynamicTable
    -> ReadBuffer
    -> IO (Maybe ([Header], Bool))
decodeTokenHeaderS :: DynamicTable -> ReadBuffer -> IO (Maybe ([Header], Bool))
decodeTokenHeaderS DynamicTable
dyntbl ReadBuffer
rbuf = do
    (RequiredInsertCount
reqInsertCount, BasePoint
bp, Bool
needAck) <- ReadBuffer
-> DynamicTable -> IO (RequiredInsertCount, BasePoint, Bool)
decodePrefix ReadBuffer
rbuf DynamicTable
dyntbl
    Bool
ok <- DynamicTable -> RequiredInsertCount -> IO Bool
checkRequiredInsertCountNB DynamicTable
dyntbl RequiredInsertCount
reqInsertCount
    if Bool
ok
        then do
            let bufsiz :: Offset
bufsiz = Offset
2048
            ForeignPtr Word8
gcbuf <- Offset -> IO (ForeignPtr Word8)
forall a. Offset -> IO (ForeignPtr a)
mallocPlainForeignPtrBytes Offset
2048
            let hufdec :: ReadBuffer -> Offset -> IO ByteString
hufdec = ForeignPtr Word8 -> Offset -> ReadBuffer -> Offset -> IO ByteString
decodeH ForeignPtr Word8
gcbuf Offset
bufsiz
            [Header]
hs <- (Word8 -> ReadBuffer -> IO TokenHeader)
-> ReadBuffer -> IO [Header]
decodeSimple (DynamicTable
-> BasePoint
-> (ReadBuffer -> Offset -> IO ByteString)
-> Word8
-> ReadBuffer
-> IO TokenHeader
toTokenHeader DynamicTable
dyntbl BasePoint
bp ReadBuffer -> Offset -> IO ByteString
hufdec) ReadBuffer
rbuf
            Maybe ([Header], Bool) -> IO (Maybe ([Header], Bool))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe ([Header], Bool) -> IO (Maybe ([Header], Bool)))
-> Maybe ([Header], Bool) -> IO (Maybe ([Header], Bool))
forall a b. (a -> b) -> a -> b
$ ([Header], Bool) -> Maybe ([Header], Bool)
forall a. a -> Maybe a
Just ([Header]
hs, Bool
needAck)
        else Maybe ([Header], Bool) -> IO (Maybe ([Header], Bool))
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe ([Header], Bool)
forall a. Maybe a
Nothing

{- FOURMOLU_DISABLE -}
toTokenHeader
    :: DynamicTable
    -> BasePoint
    -> HuffmanDecoder
    -> Word8
    -> ReadBuffer
    -> IO TokenHeader
toTokenHeader :: DynamicTable
-> BasePoint
-> (ReadBuffer -> Offset -> IO ByteString)
-> Word8
-> ReadBuffer
-> IO TokenHeader
toTokenHeader DynamicTable
dyntbl BasePoint
bp ReadBuffer -> Offset -> IO ByteString
hufdec Word8
w8 ReadBuffer
rbuf
    | Word8
w8 Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
7 =
        ReadBuffer -> DynamicTable -> BasePoint -> Word8 -> IO TokenHeader
decodeIndexedFieldLine                  ReadBuffer
rbuf DynamicTable
dyntbl        BasePoint
bp Word8
w8
    | Word8
w8 Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
6 =
        ReadBuffer
-> DynamicTable
-> (ReadBuffer -> Offset -> IO ByteString)
-> BasePoint
-> Word8
-> IO TokenHeader
decodeLiteralFieldLineWithNameReference ReadBuffer
rbuf DynamicTable
dyntbl ReadBuffer -> Offset -> IO ByteString
hufdec BasePoint
bp Word8
w8
    | Word8
w8 Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
5 =
        ReadBuffer
-> DynamicTable
-> (ReadBuffer -> Offset -> IO ByteString)
-> BasePoint
-> Word8
-> IO TokenHeader
decodeLiteralFieldLineWithLiteralName   ReadBuffer
rbuf DynamicTable
dyntbl ReadBuffer -> Offset -> IO ByteString
hufdec BasePoint
bp Word8
w8
    | Word8
w8 Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
4 =
        ReadBuffer -> DynamicTable -> BasePoint -> Word8 -> IO TokenHeader
decodeIndexedFieldLineWithPostBaseIndex ReadBuffer
rbuf DynamicTable
dyntbl        BasePoint
bp Word8
w8
    | Bool
otherwise =
        ReadBuffer
-> DynamicTable
-> (ReadBuffer -> Offset -> IO ByteString)
-> BasePoint
-> Word8
-> IO TokenHeader
decodeLiteralFieldLineWithPostBaseNameReference ReadBuffer
rbuf DynamicTable
dyntbl ReadBuffer -> Offset -> IO ByteString
hufdec BasePoint
bp Word8
w8
{- FOURMOLU_ENABLE -}

-- 4.5.2.  Indexed Field Line
decodeIndexedFieldLine
    :: ReadBuffer -> DynamicTable -> BasePoint -> Word8 -> IO TokenHeader
decodeIndexedFieldLine :: ReadBuffer -> DynamicTable -> BasePoint -> Word8 -> IO TokenHeader
decodeIndexedFieldLine ReadBuffer
rbuf DynamicTable
dyntbl BasePoint
bp Word8
w8 = do
    Offset
i <- Offset -> Word8 -> ReadBuffer -> IO Offset
decodeI Offset
6 (Word8
w8 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00111111) ReadBuffer
rbuf
    let static :: Bool
static = Word8
w8 Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
6
        hidx :: HIndex
hidx
            | Bool
static = AbsoluteIndex -> HIndex
SIndex (AbsoluteIndex -> HIndex) -> AbsoluteIndex -> HIndex
forall a b. (a -> b) -> a -> b
$ Offset -> AbsoluteIndex
AbsoluteIndex Offset
i
            | Bool
otherwise = AbsoluteIndex -> HIndex
DIndex (AbsoluteIndex -> HIndex) -> AbsoluteIndex -> HIndex
forall a b. (a -> b) -> a -> b
$ PreBaseIndex -> BasePoint -> AbsoluteIndex
fromPreBaseIndex (Offset -> PreBaseIndex
PreBaseIndex Offset
i) BasePoint
bp
    TokenHeader
ret <- STM TokenHeader -> IO TokenHeader
forall a. STM a -> IO a
atomically (Entry -> TokenHeader
entryTokenHeader (Entry -> TokenHeader) -> STM Entry -> STM TokenHeader
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynamicTable -> HIndex -> STM Entry
toIndexedEntry DynamicTable
dyntbl HIndex
hidx)
    DynamicTable -> IO () -> IO ()
qpackDebug DynamicTable
dyntbl (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        DynamicTable -> HIndex -> IO ()
checkHIndex DynamicTable
dyntbl HIndex
hidx
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
            String
"IndexedFieldLine (" String -> String -> String
forall a. [a] -> [a] -> [a]
++ HIndex -> String
forall a. Show a => a -> String
show HIndex
hidx String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") " String -> String -> String
forall a. [a] -> [a] -> [a]
++ TokenHeader -> String
showTokenHeader TokenHeader
ret
    TokenHeader -> IO TokenHeader
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return TokenHeader
ret

-- 4.5.3.  Indexed Field Line With Post-Base Index
decodeIndexedFieldLineWithPostBaseIndex
    :: ReadBuffer -> DynamicTable -> BasePoint -> Word8 -> IO TokenHeader
decodeIndexedFieldLineWithPostBaseIndex :: ReadBuffer -> DynamicTable -> BasePoint -> Word8 -> IO TokenHeader
decodeIndexedFieldLineWithPostBaseIndex ReadBuffer
rbuf DynamicTable
dyntbl BasePoint
bp Word8
w8 = do
    Offset
i <- Offset -> Word8 -> ReadBuffer -> IO Offset
decodeI Offset
4 (Word8
w8 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00001111) ReadBuffer
rbuf
    let hidx :: HIndex
hidx = AbsoluteIndex -> HIndex
DIndex (AbsoluteIndex -> HIndex) -> AbsoluteIndex -> HIndex
forall a b. (a -> b) -> a -> b
$ PostBaseIndex -> BasePoint -> AbsoluteIndex
fromPostBaseIndex (Offset -> PostBaseIndex
PostBaseIndex Offset
i) BasePoint
bp
    TokenHeader
ret <- STM TokenHeader -> IO TokenHeader
forall a. STM a -> IO a
atomically (Entry -> TokenHeader
entryTokenHeader (Entry -> TokenHeader) -> STM Entry -> STM TokenHeader
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynamicTable -> HIndex -> STM Entry
toIndexedEntry DynamicTable
dyntbl HIndex
hidx)
    DynamicTable -> IO () -> IO ()
qpackDebug DynamicTable
dyntbl (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        DynamicTable -> HIndex -> IO ()
checkHIndex DynamicTable
dyntbl HIndex
hidx
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
            String
"IndexedFieldLineWithPostBaseIndex ("
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ HIndex -> String
forall a. Show a => a -> String
show HIndex
hidx
                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
bp
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" after "
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ Offset -> String
forall a. Show a => a -> String
show Offset
i
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") "
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ TokenHeader -> String
showTokenHeader TokenHeader
ret
    TokenHeader -> IO TokenHeader
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return TokenHeader
ret

-- 4.5.4.  Literal Field Line With Name Reference
decodeLiteralFieldLineWithNameReference
    :: ReadBuffer
    -> DynamicTable
    -> HuffmanDecoder
    -> BasePoint
    -> Word8
    -> IO TokenHeader
decodeLiteralFieldLineWithNameReference :: ReadBuffer
-> DynamicTable
-> (ReadBuffer -> Offset -> IO ByteString)
-> BasePoint
-> Word8
-> IO TokenHeader
decodeLiteralFieldLineWithNameReference ReadBuffer
rbuf DynamicTable
dyntbl ReadBuffer -> Offset -> IO ByteString
hufdec BasePoint
bp Word8
w8 = do
    Offset
i <- Offset -> Word8 -> ReadBuffer -> IO Offset
decodeI Offset
4 (Word8
w8 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00001111) ReadBuffer
rbuf
    let static :: Bool
static = Word8
w8 Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
4
        hidx :: HIndex
hidx
            | Bool
static = AbsoluteIndex -> HIndex
SIndex (AbsoluteIndex -> HIndex) -> AbsoluteIndex -> HIndex
forall a b. (a -> b) -> a -> b
$ Offset -> AbsoluteIndex
AbsoluteIndex Offset
i
            | Bool
otherwise = AbsoluteIndex -> HIndex
DIndex (AbsoluteIndex -> HIndex) -> AbsoluteIndex -> HIndex
forall a b. (a -> b) -> a -> b
$ PreBaseIndex -> BasePoint -> AbsoluteIndex
fromPreBaseIndex (Offset -> PreBaseIndex
PreBaseIndex Offset
i) BasePoint
bp
    Token
key <- STM Token -> IO Token
forall a. STM a -> IO a
atomically (Entry -> Token
entryToken (Entry -> Token) -> STM Entry -> STM Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynamicTable -> HIndex -> STM Entry
toIndexedEntry DynamicTable
dyntbl HIndex
hidx)
    ByteString
val <- (Word8 -> Word8)
-> (Word8 -> Bool)
-> Offset
-> (ReadBuffer -> Offset -> IO ByteString)
-> ReadBuffer
-> IO ByteString
decodeS (Word8 -> Offset -> Word8
forall a. Bits a => a -> Offset -> a
`clearBit` Offset
7) (Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
7) Offset
7 ReadBuffer -> Offset -> IO ByteString
hufdec ReadBuffer
rbuf
    let ret :: TokenHeader
ret = (Token
key, ByteString
val)
    DynamicTable -> IO () -> IO ()
qpackDebug DynamicTable
dyntbl (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        DynamicTable -> HIndex -> IO ()
checkHIndex DynamicTable
dyntbl HIndex
hidx
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
            String
"LiteralFieldLineWithNameReference ("
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ HIndex -> String
forall a. Show a => a -> String
show HIndex
hidx
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") "
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ TokenHeader -> String
showTokenHeader TokenHeader
ret
    TokenHeader -> IO TokenHeader
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return TokenHeader
ret

-- 4.5.5.  Literal Field Line With Post-Base Name Reference
decodeLiteralFieldLineWithPostBaseNameReference
    :: ReadBuffer
    -> DynamicTable
    -> HuffmanDecoder
    -> BasePoint
    -> Word8
    -> IO TokenHeader
decodeLiteralFieldLineWithPostBaseNameReference :: ReadBuffer
-> DynamicTable
-> (ReadBuffer -> Offset -> IO ByteString)
-> BasePoint
-> Word8
-> IO TokenHeader
decodeLiteralFieldLineWithPostBaseNameReference ReadBuffer
rbuf DynamicTable
dyntbl ReadBuffer -> Offset -> IO ByteString
hufdec BasePoint
bp Word8
w8 = do
    Offset
i <- Offset -> Word8 -> ReadBuffer -> IO Offset
decodeI Offset
3 (Word8
w8 Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000111) ReadBuffer
rbuf
    let hidx :: HIndex
hidx = AbsoluteIndex -> HIndex
DIndex (AbsoluteIndex -> HIndex) -> AbsoluteIndex -> HIndex
forall a b. (a -> b) -> a -> b
$ PostBaseIndex -> BasePoint -> AbsoluteIndex
fromPostBaseIndex (Offset -> PostBaseIndex
PostBaseIndex Offset
i) BasePoint
bp
    Token
key <- STM Token -> IO Token
forall a. STM a -> IO a
atomically (Entry -> Token
entryToken (Entry -> Token) -> STM Entry -> STM Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DynamicTable -> HIndex -> STM Entry
toIndexedEntry DynamicTable
dyntbl HIndex
hidx)
    ByteString
val <- (Word8 -> Word8)
-> (Word8 -> Bool)
-> Offset
-> (ReadBuffer -> Offset -> IO ByteString)
-> ReadBuffer
-> IO ByteString
decodeS (Word8 -> Offset -> Word8
forall a. Bits a => a -> Offset -> a
`clearBit` Offset
7) (Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
7) Offset
7 ReadBuffer -> Offset -> IO ByteString
hufdec ReadBuffer
rbuf
    let ret :: TokenHeader
ret = (Token
key, ByteString
val)
    DynamicTable -> IO () -> IO ()
qpackDebug DynamicTable
dyntbl (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        DynamicTable -> HIndex -> IO ()
checkHIndex DynamicTable
dyntbl HIndex
hidx
        String -> IO ()
putStrLn (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
            String
"LiteralFieldLineWithPostBaseNameReference ("
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ HIndex -> String
forall a. Show a => a -> String
show HIndex
hidx
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
") "
                String -> String -> String
forall a. [a] -> [a] -> [a]
++ TokenHeader -> String
showTokenHeader TokenHeader
ret
    TokenHeader -> IO TokenHeader
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return TokenHeader
ret

-- 4.5.6.  Literal Field Line With Literal Name
decodeLiteralFieldLineWithLiteralName
    :: ReadBuffer
    -> DynamicTable
    -> HuffmanDecoder
    -> BasePoint
    -> Word8
    -> IO TokenHeader
decodeLiteralFieldLineWithLiteralName :: ReadBuffer
-> DynamicTable
-> (ReadBuffer -> Offset -> IO ByteString)
-> BasePoint
-> Word8
-> IO TokenHeader
decodeLiteralFieldLineWithLiteralName ReadBuffer
rbuf DynamicTable
dyntbl ReadBuffer -> Offset -> IO ByteString
hufdec BasePoint
_bp Word8
_w8 = do
    ReadBuffer -> Offset -> IO ()
forall a. Readable a => a -> Offset -> IO ()
ff ReadBuffer
rbuf (-Offset
1)
    Token
key <- ByteString -> Token
toToken (ByteString -> Token) -> IO ByteString -> IO Token
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Word8 -> Word8)
-> (Word8 -> Bool)
-> Offset
-> (ReadBuffer -> Offset -> IO ByteString)
-> ReadBuffer
-> IO ByteString
decodeS (Word8 -> Word8 -> Word8
forall a. Bits a => a -> a -> a
.&. Word8
0b00000111) (Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
3) Offset
3 ReadBuffer -> Offset -> IO ByteString
hufdec ReadBuffer
rbuf
    ByteString
val <- (Word8 -> Word8)
-> (Word8 -> Bool)
-> Offset
-> (ReadBuffer -> Offset -> IO ByteString)
-> ReadBuffer
-> IO ByteString
decodeS (Word8 -> Offset -> Word8
forall a. Bits a => a -> Offset -> a
`clearBit` Offset
7) (Word8 -> Offset -> Bool
forall a. Bits a => a -> Offset -> Bool
`testBit` Offset
7) Offset
7 ReadBuffer -> Offset -> IO ByteString
hufdec ReadBuffer
rbuf
    let ret :: TokenHeader
ret = (Token
key, ByteString
val)
    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
$
            String
"LiteralFieldLineWithLiteralName " String -> String -> String
forall a. [a] -> [a] -> [a]
++ TokenHeader -> String
showTokenHeader TokenHeader
ret
    TokenHeader -> IO TokenHeader
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return TokenHeader
ret

showTokenHeader :: TokenHeader -> String
showTokenHeader :: TokenHeader -> String
showTokenHeader (Token
t, ByteString
val) = String
"\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
key String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\" \"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ ByteString -> String
BS8.unpack ByteString
val String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""
  where
    key :: String
key = ByteString -> String
BS8.unpack (ByteString -> String) -> ByteString -> String
forall a b. (a -> b) -> a -> b
$ CI ByteString -> ByteString
forall s. CI s -> s
foldedCase (CI ByteString -> ByteString) -> CI ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ Token -> CI ByteString
tokenKey Token
t