1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
|
-- 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
|