1
- {-# LANGUAGE CPP, RankNTypes, BangPatterns #-}
1
+ {-# LANGUAGE CPP, RankNTypes, DeriveDataTypeable, BangPatterns #-}
2
2
-----------------------------------------------------------------------------
3
3
-- |
4
4
-- Copyright : (c) 2006-2014 Duncan Coutts
@@ -67,9 +67,10 @@ module Codec.Compression.Zlib.Internal (
67
67
68
68
import Prelude hiding (length )
69
69
import Control.Monad (when )
70
- import Control.Exception (assert )
70
+ import Control.Exception (Exception , throw , assert )
71
71
import Control.Monad.ST.Lazy hiding (stToIO )
72
72
import Control.Monad.ST.Strict (stToIO )
73
+ import Data.Typeable (Typeable )
73
74
import qualified Data.ByteString.Lazy as L
74
75
import qualified Data.ByteString.Lazy.Internal as L
75
76
import qualified Data.ByteString as S
@@ -165,7 +166,7 @@ data DecompressStream m
165
166
| DecompressOutputAvailable S. ByteString (m (DecompressStream m ))
166
167
| DecompressStreamEnd S. ByteString
167
168
-- | An error code and a human readable error message.
168
- | DecompressStreamError DecompressError String
169
+ | DecompressStreamError DecompressError
169
170
170
171
-- | The possible error cases when decompressing a stream.
171
172
--
@@ -181,21 +182,34 @@ data DecompressError =
181
182
-- dictionary, and it's not provided.
182
183
| DictionaryRequired
183
184
185
+ -- | If the stream requires a dictionary and you provide one with the
186
+ -- wrong 'DictionaryHash' then you will get this error.
187
+ | DictionaryMismatch
188
+
184
189
-- | If the compressed data stream is corrupted in any way then you will
185
190
-- get this error, for example if the input data just isn't a compressed
186
191
-- zlib data stream. In particular if the data checksum turns out to be
187
192
-- wrong then you will get all the decompressed data but this error at the
188
193
-- end, instead of the normal sucessful 'StreamEnd'.
189
- | DataError
194
+ | DataFormatError String
195
+ deriving (Eq , Typeable )
196
+
197
+ instance Show DecompressError where
198
+ show TruncatedInput = modprefix " premature end of compressed data stream"
199
+ show DictionaryRequired = modprefix " compressed data stream requires custom dictionary"
200
+ show DictionaryMismatch = modprefix " given dictionary does not match the expected one"
201
+ show (DataFormatError detail) = modprefix (" compressed data stream format error (" ++ detail ++ " )" )
202
+
203
+ modprefix :: ShowS
204
+ modprefix = (" Codec.Compression.Zlib: " ++ )
190
205
191
- -- TODO: throw DecompressError as an Exception class type and document that it
192
- -- does this.
206
+ instance Exception DecompressError
193
207
194
208
foldDecompressStream :: Monad m
195
209
=> ((S. ByteString -> m a ) -> m a )
196
210
-> (S. ByteString -> m a -> m a )
197
211
-> (S. ByteString -> m a )
198
- -> (DecompressError -> String -> m a )
212
+ -> (DecompressError -> m a )
199
213
-> DecompressStream m -> m a
200
214
foldDecompressStream input output end err = fold
201
215
where
@@ -205,15 +219,12 @@ foldDecompressStream input output end err = fold
205
219
fold (DecompressOutputAvailable outchunk next) =
206
220
output outchunk (next >>= fold)
207
221
208
- fold (DecompressStreamEnd inchunk) =
209
- end inchunk
210
-
211
- fold (DecompressStreamError code msg) =
212
- err code msg
222
+ fold (DecompressStreamEnd inchunk) = end inchunk
223
+ fold (DecompressStreamError derr) = err derr
213
224
214
225
foldDecompressStreamWithInput :: (S. ByteString -> a -> a )
215
226
-> (L. ByteString -> a )
216
- -> (DecompressError -> String -> a )
227
+ -> (DecompressError -> a )
217
228
-> (forall s . DecompressStream (ST s ))
218
229
-> L. ByteString
219
230
-> a
@@ -233,8 +244,8 @@ foldDecompressStreamWithInput chunk end err = \s lbs ->
233
244
fold (DecompressStreamEnd inchunk) inchunks =
234
245
return $ end (L. fromChunks (inchunk: inchunks))
235
246
236
- fold (DecompressStreamError code msg ) _ =
237
- return $ err code msg
247
+ fold (DecompressStreamError derr ) _ =
248
+ return $ err derr
238
249
239
250
240
251
data CompressStream m
@@ -499,14 +510,13 @@ decompressStream format (DecompressParams bits initChunkSize mdict) =
499
510
finish (DecompressStreamEnd inchunk)
500
511
501
512
Stream. Error code msg -> case code of
502
- Stream. BufferError -> finish (DecompressStreamError TruncatedInput msg')
503
- where msg' = " premature end of compressed stream"
513
+ Stream. BufferError -> finish (DecompressStreamError TruncatedInput )
504
514
Stream. NeedDict adler -> do
505
515
err <- setDictionary adler mdict
506
516
case err of
507
517
Just streamErr -> finish streamErr
508
518
Nothing -> drainBuffers lastChunk
509
- Stream. DataError -> finish (DecompressStreamError DataError msg)
519
+ Stream. DataError -> finish (DecompressStreamError ( DataFormatError msg) )
510
520
_ -> fail msg
511
521
512
522
-- Note even if we end with an error we still try to flush the last chunk if
@@ -526,15 +536,13 @@ decompressStream format (DecompressParams bits initChunkSize mdict) =
526
536
setDictionary :: Stream. DictionaryHash -> Maybe S. ByteString
527
537
-> Stream (Maybe (DecompressStream Stream ))
528
538
setDictionary _adler Nothing =
529
- return $ Just (DecompressStreamError DictionaryRequired " custom dictionary needed " )
539
+ return $ Just (DecompressStreamError DictionaryRequired )
530
540
setDictionary _adler (Just dict) = do
531
541
status <- Stream. inflateSetDictionary dict
532
542
case status of
533
543
Stream. Ok -> return Nothing
534
- Stream. Error Stream. StreamError _ ->
535
- return $ Just (DecompressStreamError DictionaryRequired " provided dictionary not valid" )
536
544
Stream. Error Stream. DataError _ ->
537
- return $ Just (DecompressStreamError DictionaryRequired " given dictionary does not match the expected one " )
545
+ return $ Just (DecompressStreamError DictionaryMismatch )
538
546
_ -> fail " error when setting inflate dictionary"
539
547
540
548
@@ -627,8 +635,8 @@ decompressStreamToLBS = \strm inchunks ->
627
635
-- the usual case where it's empty) because the zlib and gzip formats know
628
636
-- their own length. So we force the tail of the input here because this
629
637
-- can be important for closing file handles etc.
630
- go (DecompressStreamEnd _) _ ! _inchunks = return L. Empty
631
- go (DecompressStreamError _code msg ) _ _ = fail $ " Codec.Compression.Zlib: " ++ msg
638
+ go (DecompressStreamEnd _) _ ! _inchunks = return L. Empty
639
+ go (DecompressStreamError err ) _ _ = throw err
632
640
633
641
decompressStreamToIO :: DecompressStream Stream -> DecompressStream IO
634
642
decompressStreamToIO =
@@ -649,8 +657,8 @@ decompressStreamToIO =
649
657
(strm', zstate') <- stToIO $ Stream. runStream next zstate
650
658
return (go strm' zstate')
651
659
652
- go (DecompressStreamEnd chunk) _ = DecompressStreamEnd chunk
653
- go (DecompressStreamError code msg ) _ = DecompressStreamError code msg
660
+ go (DecompressStreamEnd chunk) _ = DecompressStreamEnd chunk
661
+ go (DecompressStreamError err ) _ = DecompressStreamError err
654
662
655
663
decompressStreamToST :: DecompressStream Stream -> DecompressStream (ST s )
656
664
decompressStreamToST =
@@ -671,6 +679,5 @@ decompressStreamToST =
671
679
(strm', zstate') <- strictToLazyST $ Stream. runStream next zstate
672
680
return (go strm' zstate')
673
681
674
- go (DecompressStreamEnd chunk) _ = DecompressStreamEnd chunk
675
- go (DecompressStreamError code msg) _ = DecompressStreamError code msg
676
-
682
+ go (DecompressStreamEnd chunk) _ = DecompressStreamEnd chunk
683
+ go (DecompressStreamError err) _ = DecompressStreamError err
0 commit comments