module Codec.Zlib.Enum ( -- * Enumeratees compress, decompress, gzip, ungzip, -- * Re-exported from zlib-bindings WindowBits (..), defaultWindowBits, ZlibException ) where import Codec.Zlib import Data.Enumerator as E import qualified Data.Enumerator.List as EL import Control.Monad.Trans.Class (lift) import Control.Monad.IO.Class (MonadIO, liftIO) import Data.ByteString (ByteString) -- | Gzip compression with default parameters. gzip :: MonadIO m => Enumeratee ByteString ByteString m a gzip = compress 1 (WindowBits 31) -- | Gzip decompression with default parameters. ungzip :: MonadIO m => Enumeratee ByteString ByteString m a ungzip = decompress (WindowBits 31) -- | -- Decompress (inflate) a stream of 'ByteString's. For example: -- -- > run $ enumFile "test.z" $$ decompress defaultWindowBits $$ printChunks True decompress :: MonadIO m => WindowBits -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library) -> Enumeratee ByteString ByteString m a decompress config inner = do inf <- liftIO $ initInflate config decompress' inf inner decompress' :: MonadIO m => Inflate -> Enumeratee ByteString ByteString m b decompress' inf (Continue k) = do x <- EL.head case x of Nothing -> do chunk <- liftIO $ finishInflate inf lift $ runIteratee $ k $ Chunks [chunk] Just bs -> do chunks <- liftIO $ (feedInflate inf bs >>= callback) step <- lift $ runIteratee $ k $ Chunks chunks decompress' inf step decompress' _ step = return step -- | -- Compress (deflate) a stream of 'ByteString's. The 'WindowBits' also control -- the format (zlib vs. gzip). compress :: MonadIO m => Int -- ^ Compression level -> WindowBits -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library) -> Enumeratee ByteString ByteString m a compress level config inner = do def <- liftIO $ initDeflate level config compress' def inner compress' :: MonadIO m => Deflate -> Enumeratee ByteString ByteString m b compress' def (Continue k) = do x <- EL.head case x of Nothing -> do chunks <- liftIO $ callback (finishDeflate def) lift $ runIteratee $ k $ Chunks chunks Just bs -> do chunks <- liftIO $ (feedDeflate def bs >>= callback) step <- lift $ runIteratee $ k $ Chunks chunks compress' def step compress' _ step = return step callback :: Monad m => m (Maybe a) -> m [a] callback pop = go id where go front = do x <- pop case x of Nothing -> return $ front [] Just y -> go (front . (:) y)