Add support for Zstandard (zstd) compression method

This commit is contained in:
Csaba Hruska
2020-09-16 00:10:40 +02:00
committed by Mark Karpov
parent 6df7409fa4
commit 7dee54beb6
6 changed files with 70 additions and 4 deletions
+7
View File
@@ -1,3 +1,10 @@
## Zip 1.6.0
* Added support for Zstandard (zstd) compression
* Added a Cabal flag `-fdisable-zstd` to remove the zstd C library
dependency and hence support for Zstd entries.
## Zip 1.5.0
* Added the `packDirRecur'` function.
+24 -4
View File
@@ -66,7 +66,11 @@ import System.IO
import System.IO.Error (isDoesNotExistError)
#ifdef ENABLE_BZIP2
import qualified Data.Conduit.BZlib as BZ
import qualified Data.Conduit.BZlib as BZ
#endif
#ifdef ENABLE_ZSTD
import qualified Data.Conduit.Zstd as Zstandard
#endif
----------------------------------------------------------------------------
@@ -167,7 +171,7 @@ data MsDosTime = MsDosTime
-- | “Version created by” to specify when writing archive data.
zipVersion :: Version
zipVersion = Version [4, 6] []
zipVersion = Version [6, 3] []
----------------------------------------------------------------------------
-- Higher-level operations
@@ -587,6 +591,13 @@ sinkData h compression = do
BZ.bzip2 .| dataSink
#else
BZip2 -> throwM BZip2Unsupported
#endif
#ifdef ENABLE_ZSTD
Zstd ->
withCompression $
Zstandard.compress 1 .| dataSink
#else
Zstd -> throwM ZstdUnsupported
#endif
return
DataDescriptor
@@ -1086,6 +1097,7 @@ toCompressionMethod :: Word16 -> Maybe CompressionMethod
toCompressionMethod 0 = Just Store
toCompressionMethod 8 = Just Deflate
toCompressionMethod 12 = Just BZip2
toCompressionMethod 93 = Just Zstd
toCompressionMethod _ = Nothing
-- | Convert 'CompressionMethod' to its numeric representation as per .ZIP
@@ -1094,6 +1106,7 @@ fromCompressionMethod :: CompressionMethod -> Word16
fromCompressionMethod Store = 0
fromCompressionMethod Deflate = 8
fromCompressionMethod BZip2 = 12
fromCompressionMethod Zstd = 93
-- | Check if an entry with these parameters needs Zip64 extension.
needsZip64 :: EntryDescription -> Bool
@@ -1113,6 +1126,7 @@ getZipVersion zip64 m = max zip64ver mver
Just Store -> [2, 0]
Just Deflate -> [2, 0]
Just BZip2 -> [4, 6]
Just Zstd -> [6, 3]
-- | Return decompressing 'Conduit' corresponding to the given compression
-- method.
@@ -1124,9 +1138,15 @@ decompressingPipe Store = C.awaitForever C.yield
decompressingPipe Deflate = Z.decompress $ Z.WindowBits (-15)
#ifdef ENABLE_BZIP2
decompressingPipe BZip2 = BZ.bunzip2
decompressingPipe BZip2 = BZ.bunzip2
#else
decompressingPipe BZip2 = throwM BZip2Unsupported
decompressingPipe BZip2 = throwM BZip2Unsupported
#endif
#ifdef ENABLE_ZSTD
decompressingPipe Zstd = Zstandard.decompress
#else
decompressingPipe Zstd = throwM ZstdUnsupported
#endif
-- | Sink that calculates CRC32 check sum for incoming stream.
+17
View File
@@ -182,6 +182,10 @@ data CompressionMethod
Deflate
| -- | Compressed using BZip2 algorithm
BZip2
| -- | Compressed using Zstandard algorithm
--
-- @since 1.6.0
Zstd
deriving (Show, Read, Eq, Ord, Enum, Bounded, Data, Typeable)
----------------------------------------------------------------------------
@@ -212,6 +216,13 @@ data ZipException
--
-- @since 1.3.0
| BZip2Unsupported
#endif
#ifndef ENABLE_ZSTD
-- | Thrown when attempting to decompress a 'Zstd' entry and the
-- library is compiled without support for it.
--
-- @since 1.6.0
| ZstdUnsupported
#endif
ParsingFailed FilePath String
deriving (Eq, Ord, Typeable)
@@ -228,4 +239,10 @@ instance Show ZipException where
"the zip library has been built with bzip2 disabled."
#endif
#ifndef ENABLE_ZSTD
show ZstdUnsupported =
"Encountered a zipfile entry with Zstd compression, but " ++
"the zip library has been built with zstd disabled."
#endif
instance Exception ZipException
+2
View File
@@ -98,6 +98,7 @@ For reference, here is a [copy of the specification][specification].
* Store (no compression, just store files “as is”)
* [DEFLATE](deflate)
* [Bzip2](bzip2)
* [Zstandard](zstd)
The best way to add a new compression method to the library is to write a
conduit that will do the compression and publish it as a library. `zip` can
@@ -284,3 +285,4 @@ Distributed under BSD 3 clause license.
[specification]: https://pkware.cachefly.net/webdocs/APPNOTE/APPNOTE-6.3.3.TXT
[deflate]: https://en.wikipedia.org/wiki/DEFLATE
[bzip2]: https://en.wikipedia.org/wiki/Bzip2
[zstd]: https://en.wikipedia.org/wiki/Zstandard
+4
View File
@@ -95,6 +95,9 @@ instance Arbitrary CompressionMethod where
[ Store,
#ifdef ENABLE_BZIP2
BZip2,
#endif
#ifdef ENABLE_ZSTD
Zstd,
#endif
Deflate
]
@@ -386,6 +389,7 @@ versionNeededSpec =
Store -> [2, 0]
Deflate -> [2, 0]
BZip2 -> [4, 6]
Zstd -> [6, 3]
)
addEntrySpec :: SpecWith FilePath
+16
View File
@@ -32,6 +32,13 @@ flag disable-bzip2
default: False
manual: True
flag disable-zstd
description:
Removes dependency on zstd C library and hence support for Zstandard entries.
default: False
manual: True
library
exposed-modules:
Codec.Archive.Zip
@@ -67,6 +74,9 @@ library
if !flag(disable-bzip2)
build-depends: bzlib-conduit >=0.3 && <0.4
if !flag(disable-zstd)
build-depends: conduit-zstd >=0.0.2 && <0.1
if flag(dev)
cpp-options: -DHASKELL_ZIP_DEV_MODE
ghc-options:
@@ -79,6 +89,9 @@ library
if !flag(disable-bzip2)
cpp-options: -DENABLE_BZIP2
if !flag(disable-zstd)
cpp-options: -DENABLE_ZSTD
if os(windows)
cpp-options: -DZIP_OS=0
@@ -132,3 +145,6 @@ test-suite tests
if !flag(disable-bzip2)
cpp-options: -DENABLE_BZIP2
if !flag(disable-zstd)
cpp-options: -DENABLE_ZSTD