{-# LANGUAGE Trustworthy #-}
module Data.Conduit.Brotli
(
compress
, decompress
, compressWith
, Brotli.defaultCompressParams
, Brotli.CompressParams
, Brotli.compressLevel
, Brotli.compressWindowSize
, Brotli.compressMode
, Brotli.compressSizeHint
, Brotli.CompressionLevel(..)
, Brotli.CompressionWindowSize(..)
, Brotli.CompressionMode(..)
, decompressWith
, Brotli.defaultDecompressParams
, Brotli.DecompressParams
, Brotli.decompressDisableRingBufferReallocation
) where
import qualified Codec.Compression.Brotli as Brotli
import Control.Applicative as App
import Control.Monad.IO.Class (MonadIO (liftIO))
import Control.Monad.Trans.Resource
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Data.Conduit
import Data.Conduit.List (peek)
decompress :: (MonadThrow m, MonadIO m) => ConduitM ByteString ByteString m ()
decompress = decompressWith Brotli.defaultDecompressParams
decompressWith :: (MonadThrow m, MonadIO m) => Brotli.DecompressParams -> ConduitM ByteString ByteString m ()
decompressWith parms = do
c <- peek
case c of
Nothing -> throwM $ userError $ "Data.Conduit.Brotli.decompress: invalid empty input"
Just _ -> liftIO (Brotli.decompressIO parms) >>= go
where
go s@(Brotli.DecompressInputRequired more) = do
mx <- await
case mx of
Just x
| B.null x -> go s
| otherwise -> liftIO (more x) >>= go
Nothing -> liftIO (more B.empty) >>= go
go (Brotli.DecompressOutputAvailable output cont) = do
yield output
liftIO cont >>= go
go (Brotli.DecompressStreamEnd rest) = do
if B.null rest
then App.pure ()
else leftover rest
go (Brotli.DecompressStreamError ecode) =
throwM $ userError $ "Data.Conduit.Brotli.decompress: error (" ++ Brotli.showBrotliDecoderErrorCode ecode ++ ")"
compress :: (MonadIO m) => ConduitM ByteString ByteString m ()
compress = compressWith Brotli.defaultCompressParams
compressWith :: MonadIO m => Brotli.CompressParams -> ConduitM ByteString ByteString m ()
compressWith parms = do
s <- liftIO (Brotli.compressIO parms)
go s
where
go s@(Brotli.CompressInputRequired _flush more) = do
mx <- await
case mx of
Just x
| B.null x -> go s
| otherwise -> liftIO (more x) >>= go
Nothing -> liftIO (more B.empty) >>= go
go (Brotli.CompressOutputAvailable output cont) = do
yield output
liftIO cont >>= go
go Brotli.CompressStreamEnd = pure ()