packages feed

lz4-hs 0.1.3.0 → 0.1.4.0

raw patch · 6 files changed

+238/−182 lines, 6 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- Codec.Lz4.Foreign: lZ4FFreeDecompressionContext :: FinalizerPtr ()
+ Codec.Lz4: compressSz :: Int -> ByteString -> ByteString
+ Codec.Lz4.Foreign: Lz4fBlocklinked :: BlockMode
+ Codec.Lz4.Foreign: Lz4fDefault :: BlockSize
+ Codec.Lz4.Foreign: Lz4fFrame :: FrameType
+ Codec.Lz4.Foreign: Lz4fNoblockchecksum :: BlockChecksum
+ Codec.Lz4.Foreign: Lz4fNocontentchecksum :: ContentChecksum
+ Codec.Lz4.Foreign: data BlockChecksum
+ Codec.Lz4.Foreign: data BlockMode
+ Codec.Lz4.Foreign: data BlockSize
+ Codec.Lz4.Foreign: data ContentChecksum
+ Codec.Lz4.Foreign: data FrameType
+ Codec.Lz4.Foreign: instance GHC.Enum.Enum Codec.Lz4.Foreign.BlockChecksum
+ Codec.Lz4.Foreign: instance GHC.Enum.Enum Codec.Lz4.Foreign.BlockMode
+ Codec.Lz4.Foreign: instance GHC.Enum.Enum Codec.Lz4.Foreign.BlockSize
+ Codec.Lz4.Foreign: instance GHC.Enum.Enum Codec.Lz4.Foreign.ContentChecksum
+ Codec.Lz4.Foreign: instance GHC.Enum.Enum Codec.Lz4.Foreign.FrameType
+ Codec.Lz4.Foreign: type LzPreferencesPtr = ForeignPtr (LzPreferences)

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # lz4 +## 0.1.4.0++  * Add `compressSz` supporting higher levels of compression for streams+ ## 0.1.3.0    * Add `decompressBufSz` for frames
lz4-hs.cabal view
@@ -1,6 +1,6 @@ cabal-version:   1.18 name:            lz4-hs-version:         0.1.3.0+version:         0.1.4.0 license:         BSD3 license-file:    LICENSE copyright:       Copyright: (c) 2020 Vanessa McHale
+ src/Codec/Lz4.chs view
@@ -0,0 +1,197 @@+{-# LANGUAGE BangPatterns #-}++-- | The functions in this module throw exceptions on error.+--+-- 'decompress' and 'compress' are fully lazy, i.e. memory efficient.+module Codec.Lz4 ( -- * Functions for working with blocks+                   compressBlock+                 , decompressBlockSz+                 , lZ4MaxInputSize+                 , compressBlockHC+                 , lZ4HCClevelMax+                 -- * Functions for working with frames+                 , compress+                 , compressSz+                 , decompress+                 , decompressBufSz+                 -- * Version info+                 , lZ4VersionNumber+                 , lZ4VersionString+                 ) where++import           Codec.Lz4.Foreign+import           Control.Monad                (when)+import           Control.Monad.ST.Lazy        (runST)+import qualified Control.Monad.ST.Lazy        as LazyST+import qualified Control.Monad.ST.Lazy.Unsafe as LazyST+import qualified Data.ByteString              as BS+import qualified Data.ByteString.Internal     as BS+import qualified Data.ByteString.Lazy         as BSL+import qualified Data.ByteString.Unsafe       as BS+import           Foreign.C.String             (CString)+import           Foreign.C.Types              (CInt)+import           Foreign.Ptr                  (castPtr, nullPtr)+import           Foreign.ForeignPtr           (ForeignPtr, castForeignPtr,+                                               mallocForeignPtrBytes,+                                               newForeignPtr, withForeignPtr)+import           Foreign.Marshal.Alloc        (alloca)+import           Foreign.Storable             (peek, poke)+import           System.IO.Unsafe             (unsafePerformIO)++#include <lz4frame.h>++check :: LZ4FErrorCode -> IO ()+check err = when (lZ4FIsError err) $ error (lZ4FGetErrorName err)++-- | Lazily decompress a frame+decompress :: BSL.ByteString -> BSL.ByteString+decompress = decompressBufSz (64 * 1014)++-- | @since 0.1.3.0+decompressBufSz :: Int -- ^ Size of the output buffer+                -> BSL.ByteString+                -> BSL.ByteString+decompressBufSz bufSz bs = runST $ do++    let bss = BSL.toChunks bs++    (ctx, buf) <- LazyST.unsafeIOToST $ do+        (err, preCtx) <- lZ4FCreateDecompressionContext lZ4FGetVersion+        ctx <- castForeignPtr <$> newForeignPtr lZ4FFreeCompressionContext (castPtr preCtx)+        check err+        dstBuf <- mallocForeignPtrBytes bufSz+        pure (ctx, dstBuf)++    BSL.fromChunks <$> loop ctx buf bss++    where loop :: LzDecompressionCtxPtr -> ForeignPtr a -> [BS.ByteString] -> LazyST.ST s [BS.ByteString]+          loop _ _ [] = pure []+          loop ctx buf (b:bs') = do+                (nxt, res) <- stepChunk ctx buf b+                case nxt of+                    Nothing   -> (res:) <$> loop ctx buf bs'+                    Just next -> (res:) <$> loop ctx buf (next:bs')+++          stepChunk :: LzDecompressionCtxPtr -> ForeignPtr a -> BS.ByteString -> LazyST.ST s (Maybe BS.ByteString, BS.ByteString)+          stepChunk !ctx !dst b = LazyST.unsafeIOToST $+            BS.unsafeUseAsCStringLen b $ \(buf, sz) ->+                withForeignPtr dst $ \d ->+                    alloca $ \dSzPtr ->+                        alloca $ \szPtr -> do+                            poke dSzPtr (fromIntegral bufSz)+                            poke szPtr (fromIntegral sz)+                            res <- lZ4FDecompress ctx d dSzPtr buf szPtr nullPtr+                            check res+                            bRead <- peek szPtr+                            bWritten <- peek dSzPtr+                            outBs <- BS.packCStringLen (castPtr d, fromIntegral bWritten)+                            let remBs = if fromIntegral bRead == sz+                                then Nothing+                                else Just (BS.drop (fromIntegral bRead) b)+                            pure (remBs, outBs)++-- | Lazily compress a frame.+compress :: BSL.ByteString -> BSL.ByteString+compress = compressSz 0++-- | @since 0.1.4.0+compressSz :: Int -> BSL.ByteString -> BSL.ByteString+compressSz lvl bs = runST $ do++    let bss = BSL.toChunks bs++    (ctx, pref, header) <- initCtx+    rest <- loop ctx pref bss++    pure $ BSL.fromChunks (header:rest)++    where initCtx :: LazyST.ST s (LzCtxPtr, LzPreferencesPtr, BS.ByteString)+          initCtx = LazyST.unsafeIOToST $ do+                (err, preCtx) <- lZ4FCreateCompressionContext lZ4FGetVersion+                ctx <- castForeignPtr <$> newForeignPtr lZ4FFreeCompressionContext (castPtr preCtx)+                check err+                dst <- mallocForeignPtrBytes lZ4FHeaderSizeMax+                pref <- mallocForeignPtrBytes {# sizeof LZ4F_preferences_t #}+                preferencesPtr pref lvl+                header <- withForeignPtr dst $ \d -> do+                    res <- lZ4FCompressBegin ctx d lZ4FHeaderSizeMax pref+                    check res+                    BS.packCStringLen (castPtr d, fromIntegral res)+                pure (ctx, pref, header)++          loop :: LzCtxPtr -> LzPreferencesPtr -> [BS.ByteString] -> LazyST.ST s [BS.ByteString]+          loop ctx pref []      = pure <$> finish ctx pref+          loop ctx pref (b:bs') = (:) <$> update ctx pref b <*> loop ctx pref bs'++          finish :: LzCtxPtr -> LzPreferencesPtr -> LazyST.ST s BS.ByteString+          finish ctx pref = LazyST.unsafeIOToST $ do+            let expectedSz = lZ4FCompressBound 0 pref+            dst <- mallocForeignPtrBytes (fromIntegral expectedSz)+            withForeignPtr dst $ \d -> do+                res <- lZ4FCompressEnd ctx d expectedSz nullPtr+                check res+                BS.packCStringLen (castPtr d, fromIntegral res)++          update :: LzCtxPtr -> LzPreferencesPtr -> BS.ByteString -> LazyST.ST s BS.ByteString+          update !ctx !pref b = LazyST.unsafeIOToST $+            BS.unsafeUseAsCStringLen b $ \(buf, sz) -> do+                let expectedSz = lZ4FCompressBound (fromIntegral sz) pref+                dst <- mallocForeignPtrBytes (fromIntegral expectedSz)+                withForeignPtr dst $ \d -> do+                    res <- lZ4FCompressUpdate ctx d expectedSz buf (fromIntegral sz) nullPtr+                    check res+                    BS.packCStringLen (castPtr d, fromIntegral res)++{-# NOINLINE compressBlock #-}+compressBlock :: BS.ByteString -> BS.ByteString+compressBlock = unsafePerformIO . compressBlockGeneric lZ4CompressDefault++{-# NOINLINE compressBlockHC #-}+-- | @since 0.1.1.0+compressBlockHC :: Int -- ^ Compression level (must be less than 'lZ4HCClevelMax')+                -> BS.ByteString+                -> BS.ByteString+compressBlockHC lvl = unsafePerformIO . compressBlockGeneric (\src dst ssz dsz -> lZ4CompressHC src dst ssz dsz (fromIntegral lvl))++compressBlockGeneric :: (CString -> CString -> CInt -> CInt -> IO CInt) -> BS.ByteString -> IO BS.ByteString+compressBlockGeneric cfun bs =+    BS.unsafeUseAsCStringLen bs $ \(buf, sz) -> do+        let resSz = lZ4CompressBound (fromIntegral sz)+        dst <- mallocForeignPtrBytes (fromIntegral resSz)+        withForeignPtr dst $ \d -> do+            bWritten <- cfun buf d (fromIntegral sz) resSz+            when (bWritten == 0) $ error "Compression error"+            pure $ BS.fromForeignPtr (castForeignPtr dst) 0 (fromIntegral bWritten)++{-# NOINLINE decompressBlockSz #-}+-- | Decompress a block. The size of the uncompressed data must be known.+decompressBlockSz :: BS.ByteString+                  -> Int -- ^ Decompressed size+                  -> BS.ByteString+decompressBlockSz bs expectedSz = unsafePerformIO $+    BS.unsafeUseAsCStringLen bs $ \(buf, sz) -> do+        dst <- mallocForeignPtrBytes expectedSz+        withForeignPtr dst $ \d -> do+            bWritten <- lZ4DecompressSafe buf d (fromIntegral sz) (fromIntegral expectedSz)+            when (bWritten < 0) $ error "Decompression error"+        pure $ BS.fromForeignPtr (castForeignPtr dst) 0 expectedSz++cint :: Enum a => a -> CInt+cint = fromIntegral . fromEnum++preferencesPtr :: LzPreferencesPtr -> Int -> IO ()+preferencesPtr fp i =+    withForeignPtr fp $ \p -> do++        {# set LZ4F_preferences_t.frameInfo.blockSizeID #} p (cint Lz4fDefault)+        {# set LZ4F_preferences_t.frameInfo.blockMode #} p (cint Lz4fBlocklinked)+        {# set LZ4F_preferences_t.frameInfo.contentChecksumFlag #} p (cint Lz4fNocontentchecksum)+        {# set LZ4F_preferences_t.frameInfo.frameType #} p (cint Lz4fFrame)+        {# set LZ4F_preferences_t.frameInfo.contentSize #} p 0+        {# set LZ4F_preferences_t.frameInfo.dictID #} p 0+        {# set LZ4F_preferences_t.frameInfo.blockChecksumFlag #} p (cint Lz4fNoblockchecksum)++        {# set LZ4F_preferences_t.compressionLevel #} p (fromIntegral i)+        {# set LZ4F_preferences_t.autoFlush #} p 0+        {# set LZ4F_preferences_t.favorDecSpeed #} p 0
− src/Codec/Lz4.hs
@@ -1,169 +0,0 @@-{-# LANGUAGE BangPatterns #-}---- | The functions in this module throw exceptions on error.------ 'decompress' and 'compress' are fully lazy, i.e. memory efficient.-module Codec.Lz4 ( -- * Functions for working with blocks-                   compressBlock-                 , decompressBlockSz-                 , lZ4MaxInputSize-                 , compressBlockHC-                 , lZ4HCClevelMax-                 -- * Functions for working with frames-                 , compress-                 , decompress-                 , decompressBufSz-                 -- * Version info-                 , lZ4VersionNumber-                 , lZ4VersionString-                 ) where--import           Codec.Lz4.Foreign-import           Control.Monad                (when)-import           Control.Monad.ST.Lazy        (runST)-import qualified Control.Monad.ST.Lazy        as LazyST-import qualified Control.Monad.ST.Lazy.Unsafe as LazyST-import qualified Data.ByteString              as BS-import qualified Data.ByteString.Internal     as BS-import qualified Data.ByteString.Lazy         as BSL-import qualified Data.ByteString.Unsafe       as BS-import           Foreign.C.String             (CString)-import           Foreign.C.Types              (CInt)-import           Foreign.ForeignPtr           (ForeignPtr, castForeignPtr,-                                               mallocForeignPtrBytes,-                                               newForeignPtr, withForeignPtr)-import           Foreign.Marshal.Alloc        (alloca)-import           Foreign.Ptr                  (castPtr, nullPtr)-import           Foreign.Storable             (peek, poke)-import           System.IO.Unsafe             (unsafePerformIO)--check :: LZ4FErrorCode -> IO ()-check err = when (lZ4FIsError err) $ error (lZ4FGetErrorName err)---- | Lazily decompress a frame-decompress :: BSL.ByteString -> BSL.ByteString-decompress = decompressBufSz (64 * 1014)---- | @since 0.1.3.0-decompressBufSz :: Int -- ^ Size of the output buffer-                -> BSL.ByteString-                -> BSL.ByteString-decompressBufSz bufSz bs = runST $ do--    let bss = BSL.toChunks bs--    (ctx, buf) <- LazyST.unsafeIOToST $ do-        (err, preCtx) <- lZ4FCreateDecompressionContext lZ4FGetVersion-        check err-        ctx <- castForeignPtr <$> newForeignPtr lZ4FFreeCompressionContext (castPtr preCtx)-        dstBuf <- mallocForeignPtrBytes bufSz-        pure (ctx, dstBuf)--    BSL.fromChunks <$> loop ctx buf bss--    where loop :: LzDecompressionCtxPtr -> ForeignPtr a -> [BS.ByteString] -> LazyST.ST s [BS.ByteString]-          loop _ _ [] = pure []-          loop ctx buf (b:bs') = do-                (nxt, res) <- stepChunk ctx buf b-                case nxt of-                    Nothing   -> (res:) <$> loop ctx buf bs'-                    Just next -> (res:) <$> loop ctx buf (next:bs')---          stepChunk :: LzDecompressionCtxPtr -> ForeignPtr a -> BS.ByteString -> LazyST.ST s (Maybe BS.ByteString, BS.ByteString)-          stepChunk !ctx !dst b = LazyST.unsafeIOToST $-            BS.unsafeUseAsCStringLen b $ \(buf, sz) ->-                withForeignPtr dst $ \d ->-                    alloca $ \dSzPtr ->-                        alloca $ \szPtr -> do-                            poke dSzPtr (fromIntegral bufSz)-                            poke szPtr (fromIntegral sz)-                            res <- lZ4FDecompress ctx d dSzPtr buf szPtr nullPtr-                            check res-                            bRead <- peek szPtr-                            bWritten <- peek dSzPtr-                            outBs <- BS.packCStringLen (castPtr d, fromIntegral bWritten)-                            let remBs = if fromIntegral bRead == sz-                                then Nothing-                                else Just (BS.drop (fromIntegral bRead) b)-                            pure (remBs, outBs)---- | Lazily compress a frame.-compress :: BSL.ByteString -> BSL.ByteString-compress bs = runST $ do--    let bss = BSL.toChunks bs--    (ctx, header) <- initCtx-    rest <- loop ctx bss--    pure $ BSL.fromChunks (header:rest)--    where initCtx :: LazyST.ST s (LzCtxPtr, BS.ByteString)-          initCtx = LazyST.unsafeIOToST $ do-                (err, preCtx) <- lZ4FCreateCompressionContext lZ4FGetVersion-                check err-                ctx <- castForeignPtr <$> newForeignPtr lZ4FFreeCompressionContext (castPtr preCtx)-                dst <- mallocForeignPtrBytes lZ4FHeaderSizeMax-                header <- withForeignPtr dst $ \d -> do-                    res <- lZ4FCompressBegin ctx d lZ4FHeaderSizeMax nullPtr-                    check res-                    BS.packCStringLen (castPtr d, fromIntegral res)-                pure (ctx, header)--          loop :: LzCtxPtr -> [BS.ByteString] -> LazyST.ST s [BS.ByteString]-          loop ctx []      = pure <$> finish ctx-          loop ctx (b:bs') = (:) <$> update ctx b <*> loop ctx bs'--          finish :: LzCtxPtr -> LazyST.ST s BS.ByteString-          finish ctx = LazyST.unsafeIOToST $ do-            let expectedSz = lZ4FCompressBound 0 nullPtr-            dst <- mallocForeignPtrBytes (fromIntegral expectedSz)-            withForeignPtr dst $ \d -> do-                res <- lZ4FCompressEnd ctx d expectedSz nullPtr-                check res-                BS.packCStringLen (castPtr d, fromIntegral res)--          update :: LzCtxPtr -> BS.ByteString -> LazyST.ST s BS.ByteString-          update !ctx b = LazyST.unsafeIOToST $-            BS.unsafeUseAsCStringLen b $ \(buf, sz) -> do-                let expectedSz = lZ4FCompressBound (fromIntegral sz) nullPtr-                dst <- mallocForeignPtrBytes (fromIntegral expectedSz)-                withForeignPtr dst $ \d -> do-                    res <- lZ4FCompressUpdate ctx d expectedSz buf (fromIntegral sz) nullPtr-                    check res-                    BS.packCStringLen (castPtr d, fromIntegral res)--{-# NOINLINE compressBlock #-}-compressBlock :: BS.ByteString -> BS.ByteString-compressBlock = unsafePerformIO . compressBlockGeneric lZ4CompressDefault--{-# NOINLINE compressBlockHC #-}--- | @since 0.1.1.0-compressBlockHC :: Int -- ^ Compression level (must be less than 'lZ4HCClevelMax')-                -> BS.ByteString-                -> BS.ByteString-compressBlockHC lvl = unsafePerformIO . compressBlockGeneric (\src dst ssz dsz -> lZ4CompressHC src dst ssz dsz (fromIntegral lvl))--compressBlockGeneric :: (CString -> CString -> CInt -> CInt -> IO CInt) -> BS.ByteString -> IO BS.ByteString-compressBlockGeneric cfun bs =-    BS.unsafeUseAsCStringLen bs $ \(buf, sz) -> do-        let resSz = lZ4CompressBound (fromIntegral sz)-        dst <- mallocForeignPtrBytes (fromIntegral resSz)-        withForeignPtr dst $ \d -> do-            bWritten <- cfun buf d (fromIntegral sz) resSz-            when (bWritten == 0) $ error "Compression error"-            pure $ BS.fromForeignPtr (castForeignPtr dst) 0 (fromIntegral bWritten)--{-# NOINLINE decompressBlockSz #-}--- | Decompress a block. The size of the uncompressed data must be known.-decompressBlockSz :: BS.ByteString-                  -> Int -- ^ Decompressed size-                  -> BS.ByteString-decompressBlockSz bs expectedSz = unsafePerformIO $-    BS.unsafeUseAsCStringLen bs $ \(buf, sz) -> do-        dst <- mallocForeignPtrBytes expectedSz-        withForeignPtr dst $ \d -> do-            bWritten <- lZ4DecompressSafe buf d (fromIntegral sz) (fromIntegral expectedSz)-            when (bWritten < 0) $ error "Decompression error"-        pure $ BS.fromForeignPtr (castForeignPtr dst) 0 expectedSz
src/Codec/Lz4/Foreign.chs view
@@ -1,3 +1,5 @@+{-# LANGUAGE CApiFFI #-}+ module Codec.Lz4.Foreign ( -- * Blocks                            lZ4VersionNumber                          , lZ4VersionString@@ -16,10 +18,10 @@                          , lZ4FCompressUpdate                          , lZ4FCompressEnd                          , lZ4FCreateDecompressionContext-                         , lZ4FFreeDecompressionContext                          , lZ4FDecompress                          , lZ4MaxInputSize                          , lZ4CompressHC+                         -- * Macros                          , lZ4HCClevelMax                          -- * Types                          , LZ4FErrorCode@@ -27,6 +29,12 @@                          , LzCtxPtr                          , LzDecompressionCtx                          , LzDecompressionCtxPtr+                         , LzPreferencesPtr+                         , BlockMode (Lz4fBlocklinked)+                         , BlockSize (Lz4fDefault)+                         , ContentChecksum (Lz4fNocontentchecksum)+                         , BlockChecksum (Lz4fNoblockchecksum)+                         , FrameType (Lz4fFrame)                          ) where  import Data.Coerce (coerce)@@ -40,12 +48,18 @@ #include <lz4frame.h> #include <lz4hc.h> +{# enum LZ4F_blockSizeID_t as BlockSize {underscoreToCase} #}+{# enum LZ4F_blockMode_t as BlockMode {underscoreToCase} #}+{# enum LZ4F_contentChecksum_t as ContentChecksum {underscoreToCase} #}+{# enum LZ4F_blockChecksum_t as BlockChecksum {underscoreToCase} #}+{# enum LZ4F_frameType_t as FrameType {underscoreToCase} #}+ {# fun pure LZ4_versionNumber as ^ {} -> `CInt' #} -- | @since 0.1.1.0 {# fun pure LZ4_versionString as ^ {} -> `String' #} -{# fun LZ4_compress_default as ^ { `CString', `CString', `CInt' , `CInt' } -> `CInt' #}-{# fun LZ4_decompress_safe as ^ { `CString', `CString', `CInt' , `CInt' } -> `CInt' #}+{# fun unsafe LZ4_compress_default as ^ { `CString', `CString', `CInt' , `CInt' } -> `CInt' #}+{# fun unsafe LZ4_decompress_safe as ^ { `CString', `CString', `CInt' , `CInt' } -> `CInt' #}  {# fun pure LZ4_compressBound as ^ { `CInt' } -> `CInt' #} @@ -61,16 +75,16 @@  {# pointer *LZ4F_cctx as LzCtxPtr foreign finalizer LZ4F_freeCompressionContext as ^ -> LzCtx #} -{# fun LZ4F_createCompressionContext as ^ { alloca- `Ptr LzCtx' peek*, `CUInt' } -> `LZ4FErrorCode' #}+{# fun unsafe LZ4F_createCompressionContext as ^ { alloca- `Ptr LzCtx' peek*, `CUInt' } -> `LZ4FErrorCode' #}  data LzPreferences -{# pointer *LZ4F_preferences_t as LzPreferencesPtr -> LzPreferences #}+{# pointer *LZ4F_preferences_t as LzPreferencesPtr foreign -> LzPreferences #}  lZ4FHeaderSizeMax :: Integral a => a lZ4FHeaderSizeMax = {# const LZ4F_HEADER_SIZE_MAX #} -{# fun LZ4F_compressBegin as ^ { `LzCtxPtr', castPtr `Ptr a', coerce `CSize', `LzPreferencesPtr' } -> `CSize' coerce #}+{# fun unsafe LZ4F_compressBegin as ^ { `LzCtxPtr', castPtr `Ptr a', coerce `CSize', `LzPreferencesPtr' } -> `CSize' coerce #}  {# fun pure LZ4F_compressBound as ^ { coerce `CSize', `LzPreferencesPtr' } -> `CSize' coerce #} @@ -78,7 +92,7 @@  {# pointer *LZ4F_compressOptions_t as LzCompressOptionsPtr -> LzCompressOptions #} -{# fun LZ4F_compressUpdate as ^+{# fun unsafe LZ4F_compressUpdate as ^     { `LzCtxPtr'     , castPtr `Ptr a'     , coerce `CSize'@@ -88,20 +102,20 @@     } -> `CSize' coerce   #} -{# fun LZ4F_compressEnd as ^+{# fun unsafe LZ4F_compressEnd as ^     { `LzCtxPtr', castPtr `Ptr a', coerce `CSize', `LzCompressOptionsPtr' } -> `CSize' coerce #}  data LzDecompressionCtx  {# pointer *LZ4F_dctx as LzDecompressionCtxPtr foreign finalizer LZ4F_freeDecompressionContext as ^ -> LzDecompressionCtx #} -{# fun LZ4F_createDecompressionContext as ^ { alloca- `Ptr LzDecompressionCtx' peek*, `CUInt' } -> `LZ4FErrorCode' #}+{# fun unsafe LZ4F_createDecompressionContext as ^ { alloca- `Ptr LzDecompressionCtx' peek*, `CUInt' } -> `LZ4FErrorCode' #}  data LzDecompressOptions  {# pointer *LZ4F_decompressOptions_t as LzDecompressOptionsPtr -> LzDecompressOptions #} -{# fun LZ4F_decompress as ^+{# fun unsafe LZ4F_decompress as ^     { `LzDecompressionCtxPtr'     , castPtr `Ptr a'     , castPtr `Ptr CSize'@@ -115,7 +129,7 @@ lZ4MaxInputSize :: Integral a => a lZ4MaxInputSize = {# const LZ4_MAX_INPUT_SIZE #} -{# fun LZ4_compress_HC as ^+{# fun unsafe LZ4_compress_HC as ^     { `CString', `CString', `CInt', `CInt', `CInt' } -> `CInt' #}  -- | @since 0.1.1.0
test/Spec.hs view
@@ -6,6 +6,13 @@ import           Test.Tasty import           Test.Tasty.HUnit +testCompression :: FilePath -> TestTree+testCompression fp = testCase ("Highly compressed frames " ++ fp) $ do+    contents <- BSL.readFile "cbits/lz4.c"+    let sz0 = BSL.length (compressSz 0 contents)+        sz1 = BSL.length (compressSz 6 contents)+    assertBool "higher compression means smaller frames" $ sz1 < sz0+ testRoundtripBlocks :: FilePath -> TestTree testRoundtripBlocks fp = testCase ("Roundtrip " ++ fp) $ do     contents <- BS.readFile fp@@ -23,7 +30,7 @@ main =      defaultMain $-        testGroup "lz4" [testBlocks, testFrames]+        testGroup "lz4" [testBlocks, testFrames, testHC]      where         testBlocks = testGroup "Block compression"@@ -32,4 +39,7 @@             ]         testFrames = testGroup "Frame compression"             [ testRoundtripFrames "cbits/lz4.c"+            ]+        testHC = testGroup "Compression levels"+            [ testCompression "cbits/lz4frame.c"             ]