{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE ScopedTypeVariables #-} module QIF ( processBlock, Block (..), headerlist, fromCaseSensitive, headerSize, ) where import qualified Control.Exception as E import Data.Attoparsec.ByteString (Parser) import qualified Data.Attoparsec.ByteString as P import Data.ByteString (ByteString) import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BS8 import System.IO import Network.QPACK import Conduit import Data.Conduit.Attoparsec ---------------------------------------------------------------- data Block = Block Int ByteString deriving (Show) ---------------------------------------------------------------- processBlock :: FilePath -> ((PositionRange, Block) -> IO ()) -> IO () processBlock efile func = runConduitRes ( sourceFile efile .| conduitParser block .| mapM_C (liftIO . func) ) ---------------------------------------------------------------- block :: Parser Block block = do num <- toInt <$> P.take 8 len <- toInt <$> P.take 4 dat <- P.take len return $ Block num dat toInt :: ByteString -> Int toInt = BS.foldl' f 0 where f n w8 = n * 256 + fromIntegral w8 ---------------------------------------------------------------- headerlist :: Handle -> IO [Header] headerlist h = loop id where loop b = do ml <- line h case ml of Nothing -> return $ b [] Just l | l == "" -> return $ b [] | otherwise -> do let (k, v0) = BS8.break (== '\t') l v = BS8.drop 1 v0 loop (b . ((mk k, v) :)) line :: Handle -> IO (Maybe ByteString) line h = do el <- E.try $ BS8.hGetLine h case el of Left (_ :: E.IOException) -> return Nothing Right l | BS8.take 1 l == "#" -> line h | otherwise -> return $ Just l ---------------------------------------------------------------- fromCaseSensitive :: [Header] -> [Header] fromCaseSensitive = map (\(k, v) -> (foldedCase $ mk k, v)) headerSize :: Header -> Int headerSize (k, v) = BS.length (foldedCase k) + BS.length v