zlib-conduit-0.0.0: Data/Conduit/Zlib.hs
{-# LANGUAGE FlexibleContexts #-}
-- | Streaming compression and decompression using conduits.
--
-- Parts of this code were taken from zlib-enum and adapted for conduits.
module Data.Conduit.Zlib (
-- * Conduits
compress, decompress, gzip, ungzip,
-- * Re-exported from zlib-bindings
WindowBits (..), defaultWindowBits
) where
import Codec.Zlib
import Data.Conduit
import Data.ByteString (ByteString)
import qualified Data.ByteString as S
import Control.Monad.Trans.Resource
import Control.Monad.Trans.Class
-- | Gzip compression with default parameters.
gzip :: ResourceUnsafeIO m => Conduit ByteString m ByteString
gzip = compress 1 (WindowBits 31)
-- | Gzip decompression with default parameters.
ungzip :: ResourceUnsafeIO m => Conduit ByteString m ByteString
ungzip = decompress (WindowBits 31)
-- |
-- Decompress (inflate) a stream of 'ByteString's. For example:
--
-- > sourceFile "test.z" $= decompress defaultWindowBits $$ sinkFile "test"
decompress
:: ResourceUnsafeIO m
=> WindowBits -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library)
-> Conduit ByteString m ByteString
decompress config = Conduit $ do
inf <- lift $ unsafeFromIO $ initInflate config
return $ PreparedConduit (push inf) (close inf)
where
push inf x = do
chunks <- lift $ unsafeFromIO $ withInflateInput inf x callback
return $ Producing chunks
close inf = do
chunk <- lift $ unsafeFromIO $ finishInflate inf
return $ if S.null chunk then [] else [chunk]
-- |
-- Compress (deflate) a stream of 'ByteString's. The 'WindowBits' also control
-- the format (zlib vs. gzip).
compress
:: ResourceUnsafeIO m
=> Int -- ^ Compression level
-> WindowBits -- ^ Zlib parameter (see the zlib-bindings package as well as the zlib C library)
-> Conduit ByteString m ByteString
compress level config = Conduit $ do
def <- lift $ unsafeFromIO $ initDeflate level config
return $ PreparedConduit (push def) (close def)
where
push def x = do
chunks <- lift $ unsafeFromIO $ withDeflateInput def x callback
return $ Producing chunks
close def = do
chunks <- lift $ unsafeFromIO $ finishDeflate def callback
return chunks
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)