-- Copyright (c) 2016-present, Facebook, Inc. -- All rights reserved. -- -- This source code is licensed under the BSD-style license found in -- the LICENSE file in the root directory of this source tree. An -- additional grant of patent rights can be found in the PATENTS file -- in the same directory. -- | -- Module : Codec.Compression.Zstd.Efficient -- Copyright : (c) 2016-present, Facebook, Inc. All rights reserved. -- -- License : BSD3 -- Maintainer : bryano@fb.com -- Stability : experimental -- Portability : GHC -- -- These functions allow for pre-allocation and reuse of relatively -- expensive data structures, such as compression and decompression -- contexts and dictionaries. -- -- If your application mostly deals with small payloads and is -- particularly sensitive to latency or throughput, using these -- pre-allocated structures may make a noticeable difference to -- performance. module Codec.Compression.Zstd.Efficient ( -- * Basic entry points Decompress(..) , decompressedSize , C.maxCLevel -- ** Cheaper operations using contexts -- *** Compression , CCtx , withCCtx , compressCCtx -- *** Decompression , DCtx , withDCtx , decompressDCtx -- * Dictionary-based compression , Dict , mkDict , fromDict , trainFromSamples , getDictID -- ** Basic pure API , compressUsingDict , decompressUsingDict -- ** Pre-digested dictionaries , Base.CDict , createCDict , compressUsingCDict , Base.DDict , createDDict , decompressUsingDDict ) where import Codec.Compression.Zstd.Internal import Codec.Compression.Zstd.Types (Decompress(..), Dict(..), mkDict) import Codec.Compression.Zstd.Base.Types (CDict(..), DDict(..)) import Data.ByteString.Internal (ByteString(..)) import Foreign.ForeignPtr (withForeignPtr) import System.IO.Unsafe (unsafePerformIO) import qualified Codec.Compression.Zstd.FFI as C import qualified Codec.Compression.Zstd.Base as Base -- | Compress the given data as a single zstd compressed frame. compressCCtx :: CCtx -- ^ Compression context. -> Int -- ^ Compression level. Must be >= 1 and <= 'C.maxCLevel'. -> ByteString -- ^ Payload to compress. -> IO ByteString compressCCtx (CCtx cc) level bs = compressWith "compressCCtx" (C.compressCCtx cc) level bs -- | Decompress a single-frame payload of known size. Typically this -- will be a payload that was compressed with 'compress'. -- -- /Note:/ This function is not capable of decompressing a payload -- generated by the streaming or lazy compression APIs. decompressDCtx :: DCtx -- ^ Decompression context. -> ByteString -- ^ Compressed payload. -> IO Decompress decompressDCtx (DCtx cc) bs = decompressWith (C.decompressDCtx cc) bs -- | Compress the given data as a single zstd compressed frame, using -- a prebuilt dictionary. compressUsingDict :: Dict -- ^ Compression dictionary. -> Int -- ^ Compression level. Must be >= 1 and <= 'C.maxCLevel'. -> ByteString -- ^ Payload to compress. -> ByteString compressUsingDict dict level bs = unsafePerformIO . withCCtx $ \(CCtx ctx) -> withDict dict $ \dictPtr dictLen -> let compressor dp dl sp sl l = C.compressUsingDict ctx dp dl sp sl dictPtr dictLen l in compressWith "compressUsingDict" compressor level bs -- | Decompress a single-frame payload of known size, using a prebuilt -- dictionary. Typically this will be a payload that was compressed -- with 'compressUsingDict'. -- -- /Note:/ This function is not capable of decompressing a payload -- generated by the streaming or lazy compression APIs. decompressUsingDict :: Dict -- ^ Dictionary. -> ByteString -- ^ Payload to decompress. -> Decompress decompressUsingDict dict bs = unsafePerformIO . withDCtx $ \(DCtx ctx) -> withDict dict $ \dictPtr dictLen -> let decompressor dp dl sp sl = C.decompressUsingDict ctx dp dl sp sl dictPtr dictLen in decompressWith decompressor bs -- | Create a pre-digested compression dictionary. createCDict :: Int -- ^ Compression level. -> Dict -- ^ Dictionary. -> CDict createCDict level d = unsafePerformIO $ withDict d $ \dict size -> Base.createCDict dict (fromIntegral size) level -- | Compress the given data as a single zstd compressed frame, using -- a pre-built, pre-digested dictionary. compressUsingCDict :: CCtx -- ^ Compression context. -> CDict -- ^ Compression dictionary. -> ByteString -- ^ Payload to compress. -> IO ByteString compressUsingCDict (CCtx ctx) (CD fp) bs = withForeignPtr fp $ \dict -> do let compressor dp dl sp sl _ = C.compressUsingCDict ctx dp dl sp sl dict compressWith "compressUsingCDict" compressor 0 bs -- | Create a pre-digested compression dictionary. createDDict :: Dict -- ^ Dictionary. -> DDict createDDict d = unsafePerformIO $ withDict d $ \dict size -> Base.createDDict dict (fromIntegral size) -- | Decompress a single-frame payload of known size, using a -- pre-built, pre-digested dictionary. Typically this will be a -- payload that was compressed with 'compressUsingCDict'. -- -- /Note:/ This function is not capable of decompressing a payload -- generated by the streaming or lazy compression APIs. decompressUsingDDict :: DCtx -- ^ Decompression context. -> DDict -- ^ Decompression dictionary. -> ByteString -- ^ Payload to compress. -> IO Decompress decompressUsingDDict (DCtx ctx) (DD fp) bs = withForeignPtr fp $ \dict -> do let decompressor dp dl sp sl = C.decompressUsingDDict ctx dp dl sp sl dict decompressWith decompressor bs