packages feed

snappy-lazy-0.1.0.0: src/Codec/Compression/Snappy/BSL.hs

-- | Snappy frames; see
-- [here](http://hackage.haskell.org/package/snappy-framing) for more on the
-- frame format.
module Codec.Compression.Snappy.BSL ( compress
                                    , decompress
                                    ) where

import qualified Codec.Compression.Snappy         as Snappy
import qualified Codec.Compression.Snappy.Framing as Snappy
import           Data.Binary                      (decodeOrFail, encode)
import qualified Data.ByteString.Lazy             as BSL
import           Data.Semigroup                   ((<>))

-- | Throws exception on error.
decompress :: BSL.ByteString -> BSL.ByteString
decompress = BSL.fromChunks . loop
    where loop bs =
            let (res, _, chunk) = asE $ decodeOrFail bs
                in if BSL.null res
                    then [extractUncompressed chunk]
                    else extractUncompressed chunk : loop res
          asE = either (error.show) id
          extractUncompressed (Snappy.Compressed _ d)   = Snappy.decompress d
          extractUncompressed (Snappy.Uncompressed _ x) = x
          extractUncompressed Snappy.StreamIdentifier   = mempty
          extractUncompressed Snappy.Skippable{}        = mempty
          extractUncompressed _                         = error "Expected Uncompressed{}, Skippable{} or StreamIdentifier; possible corrupt stream"

compress :: BSL.ByteString -> BSL.ByteString
compress = (Snappy.streamIdentifier <>) . loop
    where loop bsl =
            let (chunk, res) = Snappy.encode bsl
                in case res of
                    Just x  -> extractCompressed chunk <> loop x
                    Nothing -> extractCompressed chunk
          extractCompressed c@Snappy.Compressed{}   = encode c
          extractCompressed c@Snappy.Uncompressed{} = encode c
          -- see: http://hackage.haskell.org/package/snappy-framing-0.1.2/docs/Codec-Compression-Snappy-Framing.html#v:encode
          extractCompressed _                       = error "Expected Compressed{}; possible corrupt stream"