{-# LANGUAGE RankNTypes #-}
import Codec.Compression.Zlib (ZlibDecoder (..), decompressIncremental)
import Control.Monad (unless)
import qualified Data.ByteString as S
import qualified Data.ByteString.Lazy as L
import Data.List (isSuffixOf)
import GHC.IO (stToIO)
import GHC.Prim (RealWorld)
import GHC.ST (ST)
import System.Environment (getArgs)
import System.IO (Handle, IOMode (..), hClose, openFile)
import Prelude hiding (readFile, writeFile)
main :: IO ()
main = do
args <- getArgs
case args of
[ifile] ->
if ".z" `isSuffixOf` ifile
then do
bstr <- L.readFile ifile
let outname = take (length ifile - 2) ifile
hndl <- openFile outname WriteMode
runDecompression hndl (L.toChunks bstr) decompressIncremental
else putStrLn "Unexpected file name."
_ ->
putStrLn "USAGE: deflate [filename]"
runDecompression :: Handle -> [S.ByteString] -> ST RealWorld (ZlibDecoder RealWorld) -> IO ()
runDecompression hndl ls decoder = do
nextState <- stToIO decoder
case nextState of
Done -> do
unless (null ls) $
putStrLn "WARNING: Finished decompression with data left."
hClose hndl
DecompError e -> do
putStrLn ("ERROR: " ++ show e)
hClose hndl
NeedMore f
| (x : rest) <- ls -> runDecompression hndl rest (f x)
| otherwise -> do
putStrLn "ERROR: Ran out of data mid-decompression."
hClose hndl
Chunk c m -> do
S.hPut hndl c
runDecompression hndl ls m