    -- | Error handling functions.
    module Codec.Archive.LibZip.Errors
        ( errFromCInt
        , get_error
        , get_file_error
        , catchZipError
        ) where

    import Data.Typeable (Typeable, typeOf)
    import Foreign.C.Types
    import Foreign.Marshal.Alloc (alloca)
    import Foreign.Ptr (nullPtr)
    import Foreign.Storable (peek)
    import qualified Control.Exception as E

    import Bindings.LibZip
    import Codec.Archive.LibZip.Types

    errFromCInt :: CInt -> ZipError
    errFromCInt = toEnum . fromEnum

    get_error :: Zip -> IO ZipError
    get_error z | z == nullPtr = E.throwIO ErrINVAL
    get_error z = alloca $ \zep -> do
       c'zip_error_get z zep nullPtr
       peek zep >>= return . errFromCInt

    get_file_error :: ZipFile -> IO ZipError
    get_file_error zf
        | zf == nullPtr = E.throwIO ErrINVAL
        | otherwise = alloca $ \zep -> do
             c'zip_file_error_get zf zep nullPtr
             peek zep >>= return . errFromCInt

    -- | Wrapper to catch library errors.
    catchZipError :: IO a -> (ZipError -> IO a) -> IO a
    catchZipError f h = E.catchJust ifZipError f h
      where
        ifZipError :: (Typeable e, E.Exception e) => e -> Maybe e
        ifZipError x | typeOf x == typeOf ErrOK = Just x
        ifZipError _ | otherwise = Nothing