streamly-lz4-0.1.1: src/Streamly/LZ4.hs
-- |
-- Module : Streamly.LZ4
-- Copyright : (c) 2020 Composewell Technologies
-- License : Apache-2.0
-- Maintainer : streamly@composewell.com
-- Stability : experimental
-- Portability : GHC
--
-- Streaming APIs for LZ4 (<https://github.com/lz4/lz4>) compression and
-- decompression.
--
-- A compressed LZ4 object (e.g. a file) may be represented by a sequence of
-- one or more LZ4 frames defined by the [LZ4 frame
-- format](https://github.com/lz4/lz4/blob/dev/doc/lz4_Frame_format.md). A
-- frame consists of a frame header followed by a number of compressed blocks
-- and a frame footer. The frame header defines the attributes of the
-- compression method and the blocks in the frame. For example, the blocks may
-- be independently compressed or future blocks may depend on the past blocks.
-- It may also describe the maximum size of the blocks in the frame and use of
-- some optional features.
--
-- This module exposes combinators to only compress or decompress the stream of
-- blocks in a frame and not the frame itself. See the "Streamly.Internal.LZ4"
-- module for an experimental frame parsing function.
--
-- How the blocks are encoded, depends on the attributes specified in the frame
-- header. We provide a 'BlockConfig' parameter to specify those options when
-- decoding or encoding a stream of blocks. Assuming you have parsed the frame,
-- you can set the 'BlockConfig' accordingly to parse the stream of blocks
-- appropriately.
--
-- Please build with
-- [fusion-plugin](https://hackage.haskell.org/package/fusion-plugin) for best
-- performance. See the [streamly build
-- guide](https://streamly.composewell.com/streamly-0.8.0/Compiling.html) for
-- more details.
--
-- The APIs are not yet stable and may change in future.
--
module Streamly.LZ4
(
-- * Configuration
BlockConfig
, defaultBlockConfig
, BlockSize(..)
, setBlockMaxSize
-- * Combinators
, compressChunks
, decompressChunks
)
where
import Control.Monad.IO.Class (MonadIO)
import Data.Word (Word8)
import Streamly.Internal.Data.Array.Foreign (Array)
import Streamly.Prelude (SerialT)
import Streamly.Internal.Data.Stream.IsStream.Type (fromStreamD, toStreamD)
import Streamly.Internal.LZ4.Config
import Streamly.Internal.LZ4
--------------------------------------------------------------------------------
-- Compression
--------------------------------------------------------------------------------
-- Note that "speedup" is specific to compression, therefore, it is not part of
-- BlockConfig.
--
-- XXX Ensure little-endian byte order as per the spec
-- XXX Check the size of the input array and fail if it is more than the max
-- block size set in BlockConfig.
-- | @compressChunks config speedup stream@ compresses an input stream of
-- @Array word8@ using the configuration defined by @config@. The resulting
-- stream is of type @Array Word8@ where each array represents a compressed
-- input block. Each input array becomes one compressed block.
--
-- @speedup@ is a compression speedup factor, more the value of @speedup@
-- faster the compression but the size of compressed data may increase. The
-- factor should be between 1 and 65537 inclusive, if it is less than 1 it is
-- set to 1 if it is more than 65537 then it is set to 65537.
--
-- LZ4 does not allow an uncompressed block of size more than 2,113,929,216
-- (0x7E000000) bytes (a little less than 2GiB). If the compressed block
-- length is more than maximum uncompressed block length (approximately 2GiB)
-- it would result in a decompression error.
--
-- See 'BlockConfig' for more details about the format of the compressed block.
--
-- /Since 0.1.0/
{-# INLINE compressChunks #-}
compressChunks ::
MonadIO m
=> BlockConfig
-> Int
-> SerialT m (Array Word8)
-> SerialT m (Array Word8)
compressChunks cfg i m = fromStreamD (compressChunksD cfg i (toStreamD m))
--------------------------------------------------------------------------------
-- Decompression
--------------------------------------------------------------------------------
-- | Decompress a stream of @Array Word8@ compressed using LZ4 stream
-- compression. See 'compressChunks' for the format of the input blocks. The
-- input chunks could be of any size, they are resized to the appropriate block
-- size before decompression based on block headers. The decompressed output
-- arrays correspond to one compressed block each.
--
-- /Since 0.1.0/
{-# INLINE decompressChunks #-}
decompressChunks ::
MonadIO m
=> BlockConfig
-> SerialT m (Array Word8)
-> SerialT m (Array Word8)
decompressChunks bf =
fromStreamD
. decompressChunksRawD bf
. resizeChunksD bf defaultFrameConfig . toStreamD