    {-# LINE 1 "Codec/Compression/Zlib/Stream.hsc" #-}
    {-# LANGUAGE CPP, ForeignFunctionInterface, DeriveDataTypeable #-}

    {-# LINE 3 "Codec/Compression/Zlib/Stream.hsc" #-}
    {-# LANGUAGE DeriveGeneric #-}

    {-# LINE 5 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 6 "Codec/Compression/Zlib/Stream.hsc" #-}
    {-# LANGUAGE CApiFFI #-}

    {-# LINE 8 "Codec/Compression/Zlib/Stream.hsc" #-}
    -----------------------------------------------------------------------------
    -- |
    -- Copyright   :  (c) 2006-2015 Duncan Coutts
    -- License     :  BSD-style
    --
    -- Maintainer  :  duncan@community.haskell.org
    --
    -- Zlib wrapper layer
    --
    -----------------------------------------------------------------------------
    module Codec.Compression.Zlib.Stream (

      -- * The Zlib state monad
      Stream,
      State,
      mkState,
      runStream,
      unsafeLiftIO,
      finalise,

      -- * Initialisation
      deflateInit,
      inflateInit,

      -- ** Initialisation parameters
      Format(..),
        gzipFormat,
        zlibFormat,
        rawFormat,
        gzipOrZlibFormat,
        formatSupportsDictionary,
      CompressionLevel(..),
        defaultCompression,
        noCompression,
        bestSpeed,
        bestCompression,
        compressionLevel,
      Method(..),
        deflateMethod,
      WindowBits(..),
        defaultWindowBits,
        windowBits,
      MemoryLevel(..),
        defaultMemoryLevel,
        minMemoryLevel,
        maxMemoryLevel,
        memoryLevel,
      CompressionStrategy(..),
        defaultStrategy,
        filteredStrategy,
        huffmanOnlyStrategy,

      -- * The buisness
      deflate,
      inflate,
      Status(..),
      Flush(..),
      ErrorCode(..),
      -- ** Special operations
      inflateReset,

      -- * Buffer management
      -- ** Input buffer
      pushInputBuffer,
      inputBufferEmpty,
      popRemainingInputBuffer,

      -- ** Output buffer
      pushOutputBuffer,
      popOutputBuffer,
      outputBufferBytesAvailable,
      outputBufferSpaceRemaining,
      outputBufferFull,

      -- ** Dictionary
      deflateSetDictionary,
      inflateSetDictionary,

      -- ** Dictionary hashes
      DictionaryHash,
      dictionaryHash,
      zeroDictionaryHash,

    {-# LINE 97 "Codec/Compression/Zlib/Stream.hsc" #-}

      ) where

    -- Note we don't use the MIN_VERSION_* macros here for compatability with
    -- old Cabal versions that come with old GHC, that didn't provide these
    -- macros for .hsc files. So we use __GLASGOW_HASKELL__ as a proxy.

    import Foreign
             ( Word8, Ptr, nullPtr, plusPtr, peekByteOff, pokeByteOff
             , ForeignPtr, FinalizerPtr, mallocForeignPtrBytes, addForeignPtrFinalizer
             , withForeignPtr, touchForeignPtr, minusPtr )

    {-# LINE 109 "Codec/Compression/Zlib/Stream.hsc" #-}
    import Foreign.ForeignPtr.Unsafe ( unsafeForeignPtrToPtr )
    import System.IO.Unsafe          ( unsafePerformIO )

    {-# LINE 114 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 115 "Codec/Compression/Zlib/Stream.hsc" #-}
    import Foreign
             ( finalizeForeignPtr )

    {-# LINE 118 "Codec/Compression/Zlib/Stream.hsc" #-}
    import Foreign.C
    import Data.ByteString.Internal (nullForeignPtr)
    import qualified Data.ByteString.Unsafe as B
    import Data.ByteString (ByteString)

    {-# LINE 125 "Codec/Compression/Zlib/Stream.hsc" #-}
    import Control.Monad (ap,liftM)

    {-# LINE 127 "Codec/Compression/Zlib/Stream.hsc" #-}
    import qualified Control.Monad.Fail as Fail

    {-# LINE 129 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 130 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 131 "Codec/Compression/Zlib/Stream.hsc" #-}
    import Control.Monad.ST.Strict

    {-# LINE 135 "Codec/Compression/Zlib/Stream.hsc" #-}
    import Control.Monad.ST.Unsafe

    {-# LINE 139 "Codec/Compression/Zlib/Stream.hsc" #-}
    import Control.Exception (assert)
    import Data.Typeable (Typeable)

    {-# LINE 142 "Codec/Compression/Zlib/Stream.hsc" #-}
    import GHC.Generics (Generic)

    {-# LINE 144 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 147 "Codec/Compression/Zlib/Stream.hsc" #-}

    import Prelude hiding (length)

    pushInputBuffer :: ForeignPtr Word8 -> Int -> Int -> Stream ()
    pushInputBuffer inBuf' offset length = do

      -- must not push a new input buffer if the last one is not used up
      inAvail <- getInAvail
      assert (inAvail == 0) $ return ()

      -- Now that we're setting a new input buffer, we can be sure that zlib no
      -- longer has a reference to the old one. Therefore this is the last point
      -- at which the old buffer had to be retained. It's safe to release now.
      inBuf <- getInBuf
      unsafeLiftIO $ touchForeignPtr inBuf

      -- now set the available input buffer ptr and length
      setInBuf   inBuf'
      setInAvail length
      setInNext  (unsafeForeignPtrToPtr inBuf' `plusPtr` offset)
      -- Note the 'unsafe'. We are passing the raw ptr inside inBuf' to zlib.
      -- To make this safe we need to hold on to the ForeignPtr for at least as
      -- long as zlib is using the underlying raw ptr.

    inputBufferEmpty :: Stream Bool
    inputBufferEmpty = getInAvail >>= return . (==0)

    popRemainingInputBuffer :: Stream (ForeignPtr Word8, Int, Int)
    popRemainingInputBuffer = do

      inBuf    <- getInBuf
      inNext   <- getInNext
      inAvail  <- getInAvail

      -- there really should be something to pop, otherwise it's silly
      assert (inAvail > 0) $ return ()
      setInAvail 0

      return (inBuf, inNext `minusPtr` unsafeForeignPtrToPtr inBuf, inAvail)

    pushOutputBuffer :: ForeignPtr Word8 -> Int -> Int -> Stream ()
    pushOutputBuffer outBuf' offset length = do

      --must not push a new buffer if there is still data in the old one
      outAvail <- getOutAvail
      assert (outAvail == 0) $ return ()
      -- Note that there may still be free space in the output buffer, that's ok,
      -- you might not want to bother completely filling the output buffer say if
      -- there's only a few free bytes left.

      outBuf <- getOutBuf
      unsafeLiftIO $ touchForeignPtr outBuf

      -- now set the available input buffer ptr and length
      setOutBuf  outBuf'
      setOutFree length
      setOutNext (unsafeForeignPtrToPtr outBuf' `plusPtr` offset)

      setOutOffset offset
      setOutAvail  0

    -- get that part of the output buffer that is currently full
    -- (might be 0, use outputBufferBytesAvailable to check)
    -- this may leave some space remaining in the buffer, use
    -- outputBufferSpaceRemaining to check.
    popOutputBuffer :: Stream (ForeignPtr Word8, Int, Int)
    popOutputBuffer = do

      outBuf    <- getOutBuf
      outOffset <- getOutOffset
      outAvail  <- getOutAvail

      -- there really should be something to pop, otherwise it's silly
      assert (outAvail > 0) $ return ()

      setOutOffset (outOffset + outAvail)
      setOutAvail  0

      return (outBuf, outOffset, outAvail)

    -- this is the number of bytes available in the output buffer
    outputBufferBytesAvailable :: Stream Int
    outputBufferBytesAvailable = getOutAvail

    -- you needen't get all the output immediately, you can continue until
    -- there is no more output space available, this tells you that amount
    outputBufferSpaceRemaining :: Stream Int
    outputBufferSpaceRemaining = getOutFree

    -- you only need to supply a new buffer when there is no more output buffer
    -- space remaining
    outputBufferFull :: Stream Bool
    outputBufferFull = liftM (==0) outputBufferSpaceRemaining

    -- you can only run this when the output buffer is not empty
    -- you can run it when the input buffer is empty but it doesn't do anything
    -- after running deflate either the output buffer will be full
    -- or the input buffer will be empty (or both)
    deflate :: Flush -> Stream Status
    deflate flush = do

      outFree <- getOutFree

      -- deflate needs free space in the output buffer
      assert (outFree > 0) $ return ()

      result <- deflate_ flush
      outFree' <- getOutFree

      -- number of bytes of extra output there is available as a result of
      -- the call to deflate:
      let outExtra = outFree - outFree'

      outAvail <- getOutAvail
      setOutAvail (outAvail + outExtra)
      return result

    inflate :: Flush -> Stream Status
    inflate flush = do

      outFree <- getOutFree

      -- inflate needs free space in the output buffer
      assert (outFree > 0) $ return ()

      result <- inflate_ flush
      outFree' <- getOutFree

      -- number of bytes of extra output there is available as a result of
      -- the call to inflate:
      let outExtra = outFree - outFree'

      outAvail <- getOutAvail
      setOutAvail (outAvail + outExtra)
      return result

    inflateReset :: Stream ()
    inflateReset = do

      outAvail <- getOutAvail
      inAvail  <- getInAvail
      -- At the point where this is used, all the output should have been consumed
      -- and any trailing input should be extracted and resupplied explicitly, not
      -- just left.
      assert (outAvail == 0 && inAvail == 0) $ return ()

      err <- withStreamState $ \zstream ->
        c_inflateReset zstream
      failIfError err

    deflateSetDictionary :: ByteString -> Stream Status
    deflateSetDictionary dict = do
      err <- withStreamState $ \zstream ->
               B.unsafeUseAsCStringLen dict $ \(ptr, len) ->
                 c_deflateSetDictionary zstream ptr (fromIntegral len)
      toStatus err

    inflateSetDictionary :: ByteString -> Stream Status
    inflateSetDictionary dict = do
      err <- withStreamState $ \zstream -> do
               B.unsafeUseAsCStringLen dict $ \(ptr, len) ->
                 c_inflateSetDictionary zstream ptr (fromIntegral len)
      toStatus err

    -- | A hash of a custom compression dictionary. These hashes are used by
    -- zlib as dictionary identifiers.
    -- (The particular hash function used is Adler32.)
    --
    newtype DictionaryHash = DictHash CULong
      deriving (Eq, Ord, Read, Show)

    -- | Update a running 'DictionaryHash'. You can generate a 'DictionaryHash'
    -- from one or more 'ByteString's by starting from 'zeroDictionaryHash', e.g.
    --
    -- > dictionaryHash zeroDictionaryHash :: ByteString -> DictionaryHash
    --
    -- or
    --
    -- > foldl' dictionaryHash zeroDictionaryHash :: [ByteString] -> DictionaryHash
    --
    dictionaryHash :: DictionaryHash -> ByteString -> DictionaryHash
    dictionaryHash (DictHash adler) dict =
      unsafePerformIO $
        B.unsafeUseAsCStringLen dict $ \(ptr, len) ->
          liftM DictHash $ c_adler32 adler ptr (fromIntegral len)

    -- | A zero 'DictionaryHash' to use as the initial value with 'dictionaryHash'.
    --
    zeroDictionaryHash :: DictionaryHash
    zeroDictionaryHash = DictHash 0

    ----------------------------
    -- Stream monad
    --

    newtype Stream a = Z {
        unZ :: ForeignPtr StreamState
            -> ForeignPtr Word8
            -> ForeignPtr Word8
            -> Int -> Int
            -> IO (ForeignPtr Word8
                  ,ForeignPtr Word8
                  ,Int, Int, a)
      }

    instance Functor Stream where
      fmap   = liftM

    instance Applicative Stream where
      pure   = returnZ
      (<*>)  = ap
      (*>)   = thenZ_

    instance Monad Stream where
      (>>=)  = thenZ
    --  m >>= f = (m `thenZ` \a -> consistencyCheck `thenZ_` returnZ a) `thenZ` f
      (>>)   = (*>)

    {-# LINE 383 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 389 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 391 "Codec/Compression/Zlib/Stream.hsc" #-}
    instance Fail.MonadFail Stream where
      fail   = (finalise >>) . failZ

    {-# LINE 394 "Codec/Compression/Zlib/Stream.hsc" #-}

    returnZ :: a -> Stream a
    returnZ a = Z $ \_ inBuf outBuf outOffset outLength ->
                      return (inBuf, outBuf, outOffset, outLength, a)
    {-# INLINE returnZ #-}

    thenZ :: Stream a -> (a -> Stream b) -> Stream b
    thenZ (Z m) f =
      Z $ \stream inBuf outBuf outOffset outLength ->
        m stream inBuf outBuf outOffset outLength >>=
          \(inBuf', outBuf', outOffset', outLength', a) ->
            unZ (f a) stream inBuf' outBuf' outOffset' outLength'
    {-# INLINE thenZ #-}

    thenZ_ :: Stream a -> Stream b -> Stream b
    thenZ_ (Z m) f =
      Z $ \stream inBuf outBuf outOffset outLength ->
        m stream inBuf outBuf outOffset outLength >>=
          \(inBuf', outBuf', outOffset', outLength', _) ->
            unZ f stream inBuf' outBuf' outOffset' outLength'
    {-# INLINE thenZ_ #-}

    failZ :: String -> Stream a
    failZ msg = Z (\_ _ _ _ _ -> fail ("Codec.Compression.Zlib: " ++ msg))

    data State s = State !(ForeignPtr StreamState)
                         !(ForeignPtr Word8)
                         !(ForeignPtr Word8)
          {-# UNPACK #-} !Int
          {-# UNPACK #-} !Int

    mkState :: ST s (State s)
    mkState = unsafeIOToST $ do
      stream <- mallocForeignPtrBytes (112)
    {-# LINE 428 "Codec/Compression/Zlib/Stream.hsc" #-}
      withForeignPtr stream $ \ptr -> do
        (\hsc_ptr -> pokeByteOff hsc_ptr 48)       ptr nullPtr
    {-# LINE 430 "Codec/Compression/Zlib/Stream.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 64)    ptr nullPtr
    {-# LINE 431 "Codec/Compression/Zlib/Stream.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 72)     ptr nullPtr
    {-# LINE 432 "Codec/Compression/Zlib/Stream.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 80)    ptr nullPtr
    {-# LINE 433 "Codec/Compression/Zlib/Stream.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 0)   ptr nullPtr
    {-# LINE 434 "Codec/Compression/Zlib/Stream.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 24)  ptr nullPtr
    {-# LINE 435 "Codec/Compression/Zlib/Stream.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 8)  ptr (0 :: CUInt)
    {-# LINE 436 "Codec/Compression/Zlib/Stream.hsc" #-}
        (\hsc_ptr -> pokeByteOff hsc_ptr 32) ptr (0 :: CUInt)
    {-# LINE 437 "Codec/Compression/Zlib/Stream.hsc" #-}
      return (State stream nullForeignPtr nullForeignPtr 0 0)

    runStream :: Stream a -> State s -> ST s (a, State s)
    runStream (Z m) (State stream inBuf outBuf outOffset outLength) =
      unsafeIOToST $
        m stream inBuf outBuf outOffset outLength >>=
          \(inBuf', outBuf', outOffset', outLength', a) ->
            return (a, State stream inBuf' outBuf' outOffset' outLength')

    -- This is marked as unsafe because runStream uses unsafeIOToST so anything
    -- lifted here can end up being unsafePerformIO'd.
    unsafeLiftIO :: IO a -> Stream a
    unsafeLiftIO m = Z $ \_stream inBuf outBuf outOffset outLength -> do
      a <- m
      return (inBuf, outBuf, outOffset, outLength, a)

    getStreamState :: Stream (ForeignPtr StreamState)
    getStreamState = Z $ \stream inBuf outBuf outOffset outLength -> do
      return (inBuf, outBuf, outOffset, outLength, stream)

    getInBuf :: Stream (ForeignPtr Word8)
    getInBuf = Z $ \_stream inBuf outBuf outOffset outLength -> do
      return (inBuf, outBuf, outOffset, outLength, inBuf)

    getOutBuf :: Stream (ForeignPtr Word8)
    getOutBuf = Z $ \_stream inBuf outBuf outOffset outLength -> do
      return (inBuf, outBuf, outOffset, outLength, outBuf)

    getOutOffset :: Stream Int
    getOutOffset = Z $ \_stream inBuf outBuf outOffset outLength -> do
      return (inBuf, outBuf, outOffset, outLength, outOffset)

    getOutAvail :: Stream Int
    getOutAvail = Z $ \_stream inBuf outBuf outOffset outLength -> do
      return (inBuf, outBuf, outOffset, outLength, outLength)

    setInBuf :: ForeignPtr Word8 -> Stream ()
    setInBuf inBuf = Z $ \_stream _ outBuf outOffset outLength -> do
      return (inBuf, outBuf, outOffset, outLength, ())

    setOutBuf :: ForeignPtr Word8 -> Stream ()
    setOutBuf outBuf = Z $ \_stream inBuf _ outOffset outLength -> do
      return (inBuf, outBuf, outOffset, outLength, ())

    setOutOffset :: Int -> Stream ()
    setOutOffset outOffset = Z $ \_stream inBuf outBuf _ outLength -> do
      return (inBuf, outBuf, outOffset, outLength, ())

    setOutAvail :: Int -> Stream ()
    setOutAvail outLength = Z $ \_stream inBuf outBuf outOffset _ -> do
      return (inBuf, outBuf, outOffset, outLength, ())

    ----------------------------
    -- Debug stuff
    --

    {-# LINE 532 "Codec/Compression/Zlib/Stream.hsc" #-}

    ----------------------------
    -- zlib wrapper layer
    --

    data Status =
        Ok
      | StreamEnd
      | Error ErrorCode String

    data ErrorCode =
        NeedDict DictionaryHash
      | FileError
      | StreamError
      | DataError
      | MemoryError
      | BufferError -- ^ No progress was possible or there was not enough room in
                    --   the output buffer when 'Finish' is used. Note that
                    --   'BuferError' is not fatal, and 'inflate' can be called
                    --   again with more input and more output space to continue.
      | VersionError
      | Unexpected

    toStatus :: CInt -> Stream Status
    toStatus errno = case errno of
      (0)            -> return Ok
    {-# LINE 559 "Codec/Compression/Zlib/Stream.hsc" #-}
      (1)    -> return StreamEnd
    {-# LINE 560 "Codec/Compression/Zlib/Stream.hsc" #-}
      (2)     -> do
    {-# LINE 561 "Codec/Compression/Zlib/Stream.hsc" #-}
        adler <- withStreamPtr ((\hsc_ptr -> peekByteOff hsc_ptr 96))
    {-# LINE 562 "Codec/Compression/Zlib/Stream.hsc" #-}
        err (NeedDict (DictHash adler))  "custom dictionary needed"
      (-5)     -> err BufferError  "buffer error"
    {-# LINE 564 "Codec/Compression/Zlib/Stream.hsc" #-}
      (-1)         -> err FileError    "file error"
    {-# LINE 565 "Codec/Compression/Zlib/Stream.hsc" #-}
      (-2)  -> err StreamError  "stream error"
    {-# LINE 566 "Codec/Compression/Zlib/Stream.hsc" #-}
      (-3)    -> err DataError    "data error"
    {-# LINE 567 "Codec/Compression/Zlib/Stream.hsc" #-}
      (-4)     -> err MemoryError  "insufficient memory"
    {-# LINE 568 "Codec/Compression/Zlib/Stream.hsc" #-}
      (-6) -> err VersionError "incompatible zlib version"
    {-# LINE 569 "Codec/Compression/Zlib/Stream.hsc" #-}
      other                      -> return $ Error Unexpected
                                      ("unexpected zlib status: " ++ show other)
     where
       err errCode altMsg = liftM (Error errCode) $ do
        msgPtr <- withStreamPtr ((\hsc_ptr -> peekByteOff hsc_ptr 48))
    {-# LINE 574 "Codec/Compression/Zlib/Stream.hsc" #-}
        if msgPtr /= nullPtr
         then unsafeLiftIO (peekCAString msgPtr)
         else return altMsg

    failIfError :: CInt -> Stream ()
    failIfError errno = toStatus errno >>= \status -> case status of
      (Error _ msg) -> fail msg
      _             -> return ()

    data Flush =
        NoFlush
      | SyncFlush
      | FullFlush
      | Finish
    --  | Block -- only available in zlib 1.2 and later, uncomment if you need it.

    fromFlush :: Flush -> CInt
    fromFlush NoFlush   = 0
    {-# LINE 593 "Codec/Compression/Zlib/Stream.hsc" #-}
    fromFlush SyncFlush = 2
    {-# LINE 594 "Codec/Compression/Zlib/Stream.hsc" #-}
    fromFlush FullFlush = 3
    {-# LINE 595 "Codec/Compression/Zlib/Stream.hsc" #-}
    fromFlush Finish    = 4
    {-# LINE 596 "Codec/Compression/Zlib/Stream.hsc" #-}
    --  fromFlush Block     = #{const Z_BLOCK}

    -- | The format used for compression or decompression. There are three
    -- variations.
    --
    data Format = GZip | Zlib | Raw | GZipOrZlib
      deriving (Eq, Ord, Enum, Bounded, Show, Typeable

    {-# LINE 605 "Codec/Compression/Zlib/Stream.hsc" #-}
                  , Generic

    {-# LINE 607 "Codec/Compression/Zlib/Stream.hsc" #-}
               )

    {-# DEPRECATED GZip       "Use gzipFormat. Format constructors will be hidden in version 0.7"       #-}
    {-# DEPRECATED Zlib       "Use zlibFormat. Format constructors will be hidden in version 0.7"       #-}
    {-# DEPRECATED Raw        "Use rawFormat. Format constructors will be hidden in version 0.7"        #-}
    {-# DEPRECATED GZipOrZlib "Use gzipOrZlibFormat. Format constructors will be hidden in version 0.7" #-}

    -- | The gzip format uses a header with a checksum and some optional meta-data
    -- about the compressed file. It is intended primarily for compressing
    -- individual files but is also sometimes used for network protocols such as
    -- HTTP. The format is described in detail in RFC #1952
    -- <http://www.ietf.org/rfc/rfc1952.txt>
    --
    gzipFormat :: Format
    gzipFormat = GZip

    -- | The zlib format uses a minimal header with a checksum but no other
    -- meta-data. It is especially designed for use in network protocols. The
    -- format is described in detail in RFC #1950
    -- <http://www.ietf.org/rfc/rfc1950.txt>
    --
    zlibFormat :: Format
    zlibFormat = Zlib

    -- | The \'raw\' format is just the compressed data stream without any
    -- additional header, meta-data or data-integrity checksum. The format is
    -- described in detail in RFC #1951 <http://www.ietf.org/rfc/rfc1951.txt>
    --
    rawFormat :: Format
    rawFormat = Raw

    -- | This is not a format as such. It enabled zlib or gzip decoding with
    -- automatic header detection. This only makes sense for decompression.
    --
    gzipOrZlibFormat :: Format
    gzipOrZlibFormat = GZipOrZlib

    formatSupportsDictionary :: Format -> Bool
    formatSupportsDictionary Zlib = True
    formatSupportsDictionary Raw  = True
    formatSupportsDictionary _    = False

    -- | The compression method
    --
    data Method = Deflated
      deriving (Eq, Ord, Enum, Bounded, Show, Typeable

    {-# LINE 654 "Codec/Compression/Zlib/Stream.hsc" #-}
                  , Generic

    {-# LINE 656 "Codec/Compression/Zlib/Stream.hsc" #-}
               )

    {-# DEPRECATED Deflated "Use deflateMethod. Method constructors will be hidden in version 0.7" #-}

    -- | \'Deflate\' is the only method supported in this version of zlib.
    -- Indeed it is likely to be the only method that ever will be supported.
    --
    deflateMethod :: Method
    deflateMethod = Deflated

    fromMethod :: Method -> CInt
    fromMethod Deflated = 8
    {-# LINE 668 "Codec/Compression/Zlib/Stream.hsc" #-}

    -- | The compression level parameter controls the amount of compression. This
    -- is a trade-off between the amount of compression and the time required to do
    -- the compression.
    --
    data CompressionLevel =
        DefaultCompression
      | NoCompression
      | BestSpeed
      | BestCompression
      | CompressionLevel Int
      deriving (Eq, Show, Typeable

    {-# LINE 682 "Codec/Compression/Zlib/Stream.hsc" #-}
                  , Generic

    {-# LINE 684 "Codec/Compression/Zlib/Stream.hsc" #-}
               )

    {-# DEPRECATED DefaultCompression "Use defaultCompression. CompressionLevel constructors will be hidden in version 0.7" #-}
    {-# DEPRECATED NoCompression      "Use noCompression. CompressionLevel constructors will be hidden in version 0.7"      #-}
    {-# DEPRECATED BestSpeed          "Use bestSpeed. CompressionLevel constructors will be hidden in version 0.7"          #-}
    {-# DEPRECATED BestCompression    "Use bestCompression. CompressionLevel constructors will be hidden in version 0.7"    #-}
    --FIXME: cannot deprecate constructor named the same as the type
    {- DEPRECATED CompressionLevel   "Use compressionLevel. CompressionLevel constructors will be hidden in version 0.7"   -}

    -- | The default compression level is 6 (that is, biased towards higher
    -- compression at expense of speed).
    defaultCompression :: CompressionLevel
    defaultCompression = DefaultCompression

    -- | No compression, just a block copy.
    noCompression :: CompressionLevel
    noCompression = CompressionLevel 0

    -- | The fastest compression method (less compression)
    bestSpeed :: CompressionLevel
    bestSpeed = CompressionLevel 1

    -- | The slowest compression method (best compression).
    bestCompression :: CompressionLevel
    bestCompression = CompressionLevel 9

    -- | A specific compression level between 0 and 9.
    compressionLevel :: Int -> CompressionLevel
    compressionLevel n
      | n >= 0 && n <= 9 = CompressionLevel n
      | otherwise        = error "CompressionLevel must be in the range 0..9"

    fromCompressionLevel :: CompressionLevel -> CInt
    fromCompressionLevel DefaultCompression   = -1
    fromCompressionLevel NoCompression        = 0
    fromCompressionLevel BestSpeed            = 1
    fromCompressionLevel BestCompression      = 9
    fromCompressionLevel (CompressionLevel n)
               | n >= 0 && n <= 9 = fromIntegral n
               | otherwise        = error "CompressLevel must be in the range 1..9"

    -- | This specifies the size of the compression window. Larger values of this
    -- parameter result in better compression at the expense of higher memory
    -- usage.
    --
    -- The compression window size is the value of the the window bits raised to
    -- the power 2. The window bits must be in the range @9..15@ which corresponds
    -- to compression window sizes of 512b to 32Kb. The default is 15 which is also
    -- the maximum size.
    --
    -- The total amount of memory used depends on the window bits and the
    -- 'MemoryLevel'. See the 'MemoryLevel' for the details.
    --
    data WindowBits = WindowBits Int
                    | DefaultWindowBits -- This constructor must be last to make
                                        -- the Ord instance work. The Ord instance
                                        -- is used by the tests.
                                        -- It makse sense because the default value
                                        -- is is also the max value at 15.
      deriving (Eq, Ord, Show, Typeable

    {-# LINE 746 "Codec/Compression/Zlib/Stream.hsc" #-}
                  , Generic

    {-# LINE 748 "Codec/Compression/Zlib/Stream.hsc" #-}
               )

    {-# DEPRECATED DefaultWindowBits  "Use defaultWindowBits. WindowBits constructors will be hidden in version 0.7" #-}
    --FIXME: cannot deprecate constructor named the same as the type
    {- DEPRECATED WindowBits         "Use windowBits. WindowBits constructors will be hidden in version 0.7"        -}

    -- | The default 'WindowBits' is 15 which is also the maximum size.
    --
    defaultWindowBits :: WindowBits
    defaultWindowBits = WindowBits 15

    -- | A specific compression window size, specified in bits in the range @9..15@
    --
    windowBits :: Int -> WindowBits
    windowBits n
      | n >= 9 && n <= 15 = WindowBits n
      | otherwise         = error "WindowBits must be in the range 9..15"

    fromWindowBits :: Format -> WindowBits-> CInt
    fromWindowBits format bits = (formatModifier format) (checkWindowBits bits)
      where checkWindowBits DefaultWindowBits = 15
            checkWindowBits (WindowBits n)
              | n >= 9 && n <= 15 = fromIntegral n
              | otherwise         = error "WindowBits must be in the range 9..15"
            formatModifier Zlib       = id
            formatModifier GZip       = (+16)
            formatModifier GZipOrZlib = (+32)
            formatModifier Raw        = negate

    -- | The 'MemoryLevel' parameter specifies how much memory should be allocated
    -- for the internal compression state. It is a tradoff between memory usage,
    -- compression ratio and compression speed. Using more memory allows faster
    -- compression and a better compression ratio.
    --
    -- The total amount of memory used for compression depends on the 'WindowBits'
    -- and the 'MemoryLevel'. For decompression it depends only on the
    -- 'WindowBits'. The totals are given by the functions:
    --
    -- > compressTotal windowBits memLevel = 4 * 2^windowBits + 512 * 2^memLevel
    -- > decompressTotal windowBits = 2^windowBits
    --
    -- For example, for compression with the default @windowBits = 15@ and
    -- @memLevel = 8@ uses @256Kb@. So for example a network server with 100
    -- concurrent compressed streams would use @25Mb@. The memory per stream can be
    -- halved (at the cost of somewhat degraded and slower compressionby) by
    -- reducing the @windowBits@ and @memLevel@ by one.
    --
    -- Decompression takes less memory, the default @windowBits = 15@ corresponds
    -- to just @32Kb@.
    --
    data MemoryLevel =
        DefaultMemoryLevel
      | MinMemoryLevel
      | MaxMemoryLevel
      | MemoryLevel Int
      deriving (Eq, Show, Typeable

    {-# LINE 806 "Codec/Compression/Zlib/Stream.hsc" #-}
                  , Generic

    {-# LINE 808 "Codec/Compression/Zlib/Stream.hsc" #-}
               )

    {-# DEPRECATED DefaultMemoryLevel "Use defaultMemoryLevel. MemoryLevel constructors will be hidden in version 0.7" #-}
    {-# DEPRECATED MinMemoryLevel     "Use minMemoryLevel. MemoryLevel constructors will be hidden in version 0.7"     #-}
    {-# DEPRECATED MaxMemoryLevel     "Use maxMemoryLevel. MemoryLevel constructors will be hidden in version 0.7"     #-}
    --FIXME: cannot deprecate constructor named the same as the type
    {- DEPRECATED MemoryLevel        "Use memoryLevel. MemoryLevel constructors will be hidden in version 0.7"        -}

    -- | The default memory level. (Equivalent to @'memoryLevel' 8@)
    --
    defaultMemoryLevel :: MemoryLevel
    defaultMemoryLevel = MemoryLevel 8

    -- | Use minimum memory. This is slow and reduces the compression ratio.
    -- (Equivalent to @'memoryLevel' 1@)
    --
    minMemoryLevel :: MemoryLevel
    minMemoryLevel = MemoryLevel 1

    -- | Use maximum memory for optimal compression speed.
    -- (Equivalent to @'memoryLevel' 9@)
    --
    maxMemoryLevel :: MemoryLevel
    maxMemoryLevel = MemoryLevel 9

    -- | A specific level in the range @1..9@
    --
    memoryLevel :: Int -> MemoryLevel
    memoryLevel n
      | n >= 1 && n <= 9 = MemoryLevel n
      | otherwise        = error "MemoryLevel must be in the range 1..9"

    fromMemoryLevel :: MemoryLevel -> CInt
    fromMemoryLevel DefaultMemoryLevel = 8
    fromMemoryLevel MinMemoryLevel     = 1
    fromMemoryLevel MaxMemoryLevel     = 9
    fromMemoryLevel (MemoryLevel n)
             | n >= 1 && n <= 9 = fromIntegral n
             | otherwise        = error "MemoryLevel must be in the range 1..9"

    -- | The strategy parameter is used to tune the compression algorithm.
    --
    -- The strategy parameter only affects the compression ratio but not the
    -- correctness of the compressed output even if it is not set appropriately.
    --
    data CompressionStrategy =
        DefaultStrategy
      | Filtered
      | HuffmanOnly
      deriving (Eq, Ord, Enum, Bounded, Show, Typeable

    {-# LINE 860 "Codec/Compression/Zlib/Stream.hsc" #-}
                  , Generic

    {-# LINE 862 "Codec/Compression/Zlib/Stream.hsc" #-}
               )

    {-
    -- -- only available in zlib 1.2 and later, uncomment if you need it.
      | RLE             -- ^ Use 'RLE' to limit match distances to one (run-length
                        --   encoding). 'RLE' is designed to be almost as fast as
                        --   'HuffmanOnly', but give better compression for PNG
                        --   image data.
      | Fixed           -- ^ 'Fixed' prevents the use of dynamic Huffman codes,
                        --   allowing for a simpler decoder for special applications.
    -}

    {-# DEPRECATED DefaultStrategy "Use defaultStrategy. CompressionStrategy constructors will be hidden in version 0.7"     #-}
    {-# DEPRECATED Filtered        "Use filteredStrategy. CompressionStrategy constructors will be hidden in version 0.7"    #-}
    {-# DEPRECATED HuffmanOnly     "Use huffmanOnlyStrategy. CompressionStrategy constructors will be hidden in version 0.7" #-}

    -- | Use this default compression strategy for normal data.
    --
    defaultStrategy :: CompressionStrategy
    defaultStrategy = DefaultStrategy

    -- | Use the filtered compression strategy for data produced by a filter (or
    -- predictor). Filtered data consists mostly of small values with a somewhat
    -- random distribution. In this case, the compression algorithm is tuned to
    -- compress them better. The effect of this strategy is to force more Huffman
    -- coding and less string matching; it is somewhat intermediate between
    -- 'defaultCompressionStrategy' and 'huffmanOnlyCompressionStrategy'.
    --
    filteredStrategy :: CompressionStrategy
    filteredStrategy = Filtered

    -- | Use the Huffman-only compression strategy to force Huffman encoding only
    -- (no string match).
    --
    huffmanOnlyStrategy :: CompressionStrategy
    huffmanOnlyStrategy = HuffmanOnly

    fromCompressionStrategy :: CompressionStrategy -> CInt
    fromCompressionStrategy DefaultStrategy = 0
    {-# LINE 902 "Codec/Compression/Zlib/Stream.hsc" #-}
    fromCompressionStrategy Filtered        = 1
    {-# LINE 903 "Codec/Compression/Zlib/Stream.hsc" #-}
    fromCompressionStrategy HuffmanOnly     = 2
    {-# LINE 904 "Codec/Compression/Zlib/Stream.hsc" #-}
    --fromCompressionStrategy RLE             = #{const Z_RLE}
    --fromCompressionStrategy Fixed           = #{const Z_FIXED}

    withStreamPtr :: (Ptr StreamState -> IO a) -> Stream a
    withStreamPtr f = do
      stream <- getStreamState
      unsafeLiftIO (withForeignPtr stream f)

    withStreamState :: (StreamState -> IO a) -> Stream a
    withStreamState f = do
      stream <- getStreamState
      unsafeLiftIO (withForeignPtr stream (f . StreamState))

    setInAvail :: Int -> Stream ()
    setInAvail val = withStreamPtr $ \ptr ->
      (\hsc_ptr -> pokeByteOff hsc_ptr 8) ptr (fromIntegral val :: CUInt)
    {-# LINE 921 "Codec/Compression/Zlib/Stream.hsc" #-}

    getInAvail :: Stream Int
    getInAvail = liftM (fromIntegral :: CUInt -> Int) $
      withStreamPtr ((\hsc_ptr -> peekByteOff hsc_ptr 8))
    {-# LINE 925 "Codec/Compression/Zlib/Stream.hsc" #-}

    setInNext :: Ptr Word8 -> Stream ()
    setInNext val = withStreamPtr (\ptr -> (\hsc_ptr -> pokeByteOff hsc_ptr 0) ptr val)
    {-# LINE 928 "Codec/Compression/Zlib/Stream.hsc" #-}

    getInNext :: Stream (Ptr Word8)
    getInNext = withStreamPtr ((\hsc_ptr -> peekByteOff hsc_ptr 0))
    {-# LINE 931 "Codec/Compression/Zlib/Stream.hsc" #-}

    setOutFree :: Int -> Stream ()
    setOutFree val = withStreamPtr $ \ptr ->
      (\hsc_ptr -> pokeByteOff hsc_ptr 32) ptr (fromIntegral val :: CUInt)
    {-# LINE 935 "Codec/Compression/Zlib/Stream.hsc" #-}

    getOutFree :: Stream Int
    getOutFree = liftM (fromIntegral :: CUInt -> Int) $
      withStreamPtr ((\hsc_ptr -> peekByteOff hsc_ptr 32))
    {-# LINE 939 "Codec/Compression/Zlib/Stream.hsc" #-}

    setOutNext  :: Ptr Word8 -> Stream ()
    setOutNext val = withStreamPtr (\ptr -> (\hsc_ptr -> pokeByteOff hsc_ptr 24) ptr val)
    {-# LINE 942 "Codec/Compression/Zlib/Stream.hsc" #-}

    {-# LINE 947 "Codec/Compression/Zlib/Stream.hsc" #-}

    inflateInit :: Format -> WindowBits -> Stream ()
    inflateInit format bits = do
      checkFormatSupported format
      err <- withStreamState $ \zstream ->
        c_inflateInit2 zstream (fromIntegral (fromWindowBits format bits))
      failIfError err
      getStreamState >>= unsafeLiftIO . addForeignPtrFinalizer c_inflateEnd

    deflateInit :: Format
                -> CompressionLevel
                -> Method
                -> WindowBits
                -> MemoryLevel
                -> CompressionStrategy
                -> Stream ()
    deflateInit format compLevel method bits memLevel strategy = do
      checkFormatSupported format
      err <- withStreamState $ \zstream ->
        c_deflateInit2 zstream
                      (fromCompressionLevel compLevel)
                      (fromMethod method)
                      (fromWindowBits format bits)
                      (fromMemoryLevel memLevel)
                      (fromCompressionStrategy strategy)
      failIfError err
      getStreamState >>= unsafeLiftIO . addForeignPtrFinalizer c_deflateEnd

    inflate_ :: Flush -> Stream Status
    inflate_ flush = do
      err <- withStreamState $ \zstream ->
        c_inflate zstream (fromFlush flush)
      toStatus err

    deflate_ :: Flush -> Stream Status
    deflate_ flush = do
      err <- withStreamState $ \zstream ->
        c_deflate zstream (fromFlush flush)
      toStatus err

    -- | This never needs to be used as the stream's resources will be released
    -- automatically when no longer needed, however this can be used to release
    -- them early. Only use this when you can guarantee that the stream will no
    -- longer be needed, for example if an error occurs or if the stream ends.
    --
    finalise :: Stream ()

    {-# LINE 994 "Codec/Compression/Zlib/Stream.hsc" #-}
    --TODO: finalizeForeignPtr is ghc-only
    finalise = getStreamState >>= unsafeLiftIO . finalizeForeignPtr

    {-# LINE 999 "Codec/Compression/Zlib/Stream.hsc" #-}

    checkFormatSupported :: Format -> Stream ()
    checkFormatSupported format = do
      version <- unsafeLiftIO (peekCAString =<< c_zlibVersion)
      case version of
        ('1':'.':'1':'.':_)
           | format == GZip
          || format == GZipOrZlib
          -> fail $ "version 1.1.x of the zlib C library does not support the"
                 ++ " 'gzip' format via the in-memory api, only the 'raw' and "
                 ++ " 'zlib' formats."
        _ -> return ()

    ----------------------
    -- The foreign imports

    newtype StreamState = StreamState (Ptr StreamState)

    -- inflateInit2 and deflateInit2 are actually defined as macros in zlib.h
    -- They are defined in terms of inflateInit2_ and deflateInit2_ passing two
    -- additional arguments used to detect compatability problems. They pass the
    -- version of zlib as a char * and the size of the z_stream struct.
    -- If we compile via C then we can avoid this hassle however thats not really
    -- kosher since the Haskell FFI is defined at the C ABI level, not the C
    -- language level. There is no requirement to compile via C and pick up C
    -- headers. So it's much better if we can make it work properly and that'd
    -- also allow compiling via ghc's ncg which is a good thing since the C
    -- backend is not going to be around forever.
    --
    -- So we define c_inflateInit2 and c_deflateInit2 here as wrappers around
    -- their _ counterparts and pass the extra args.
    --
    -- As of GHC 7.6, we can import macros directly using the CApiFFI extension.
    -- This avoids the need for the hsc2hs #{const_str} construct, which means
    -- hsc2hs can run in cross-compilation mode.

    #ifdef NON_BLOCKING_FFI
    #define SAFTY safe
    #else
    #define SAFTY unsafe
    #endif

    {-# LINE 1042 "Codec/Compression/Zlib/Stream.hsc" #-}
    foreign import capi unsafe "zlib.h inflateInit2"
      c_inflateInit2 :: StreamState -> CInt -> IO CInt

    foreign import capi unsafe "zlib.h deflateInit2"
      c_deflateInit2 :: StreamState
                     -> CInt -> CInt -> CInt -> CInt -> CInt -> IO CInt

    {-# LINE 1069 "Codec/Compression/Zlib/Stream.hsc" #-}

    foreign import ccall SAFTY "zlib.h inflate"
      c_inflate :: StreamState -> CInt -> IO CInt

    foreign import ccall unsafe "zlib.h &inflateEnd"
      c_inflateEnd :: FinalizerPtr StreamState

    foreign import ccall unsafe "zlib.h inflateReset"
      c_inflateReset :: StreamState -> IO CInt

    foreign import ccall unsafe "zlib.h deflateSetDictionary"
      c_deflateSetDictionary :: StreamState
                             -> Ptr CChar
                             -> CUInt
                             -> IO CInt

    foreign import ccall unsafe "zlib.h inflateSetDictionary"
      c_inflateSetDictionary :: StreamState
                             -> Ptr CChar
                             -> CUInt
                             -> IO CInt

    foreign import ccall SAFTY "zlib.h deflate"
      c_deflate :: StreamState -> CInt -> IO CInt

    foreign import ccall unsafe "zlib.h &deflateEnd"
      c_deflateEnd :: FinalizerPtr StreamState

    foreign import ccall unsafe "zlib.h zlibVersion"
      c_zlibVersion :: IO CString

    foreign import ccall unsafe "zlib.h adler32"
      c_adler32 :: CULong
                -> Ptr CChar
                -> CUInt
                -> IO CULong