-- GENERATED by C->Haskell Compiler, version 0.28.3 Switcheroo, 25 November 2017 (Haskell)
-- Edit the ORIGNAL .chs file instead!


{-# LINE 1 "src/Mdbx/FFI.chs" #-}
{-|
Module      : Mdbx.FFI
Copyright   : (c) 2021 Francisco Vallarino
License     : BSD-3-Clause (see the LICENSE file)
Maintainer  : fjvallarino@gmail.com
Stability   : experimental
Portability : non-portable

Low level bindings to libmdbx functions.
-}
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Mdbx.FFI (
  -- * Environment
  MdbxEnvFlags(..),
  MdbxEnv(..),
  MdbxEnvMode(..),
  mdbx_env_create,
  mdbx_env_set_geometry,
  mdbx_env_open,
  mdbx_env_close,

  -- * Transaction
  MdbxTxnFlags(..),
  MdbxTxn(..),
  mdbx_txn_begin,
  mdbx_txn_commit,
  mdbx_txn_abort,
  mdbx_txn_env,

  -- * Database
  MdbxDbFlags(..),
  MdbxDbi(..),
  mdbx_dbi_open,
  mdbx_dbi_close,

  -- * Data
  MdbxVal(..),
  emptyMdbxVal,

  -- * CRUD
  MdbxPutFlags(..),
  mdbx_put,
  mdbx_get,
  mdbx_del,

  -- * Cursor
  MdbxCursorOp(..),
  MdbxCursor(..),
  mdbx_cursor_open,
  mdbx_cursor_close,
  mdbx_cursor_del,
  mdbx_cursor_get,
  mdbx_cursor_put,
  mdbx_cursor_count,
  mdbx_strerror,
  mdbx_cmp,

  -- * Error
  MdbxError(..),

  -- * Conversion for types used in keys
  mdbx_key_from_float,
  mdbx_key_from_double,
  mdbx_key_from_int32,
  mdbx_key_from_int64,

  mdbx_float_from_key,
  mdbx_double_from_key,
  mdbx_int32_from_key,
  mdbx_int64_from_key
) where
import qualified Foreign.C.String as C2HSImp
import qualified Foreign.C.Types as C2HSImp
import qualified Foreign.Ptr as C2HSImp
import qualified Foreign.Storable as C2HSImp
import qualified System.IO.Unsafe as C2HSImp



import GHC.Float (castWord32ToFloat, castWord64ToDouble)
import Foreign
import Foreign.C



-- Common

{-# LINE 84 "src/Mdbx/FFI.chs" #-}


-- | Error codes for the different operations.
data MdbxError = MdbxKeyexist
               | MdbxFirstLmdbErrcode
               | MdbxNotfound
               | MdbxPageNotfound
               | MdbxCorrupted
               | MdbxPanic
               | MdbxVersionMismatch
               | MdbxInvalid
               | MdbxMapFull
               | MdbxDbsFull
               | MdbxReadersFull
               | MdbxTxnFull
               | MdbxCursorFull
               | MdbxPageFull
               | MdbxUnableExtendMapsize
               | MdbxIncompatible
               | MdbxBadRslot
               | MdbxBadTxn
               | MdbxBadValsize
               | MdbxBadDbi
               | MdbxProblem
               | MdbxLastLmdbErrcode
               | MdbxBusy
               | MdbxFirstAddedErrcode
               | MdbxEmultival
               | MdbxEbadsign
               | MdbxWannaRecovery
               | MdbxEkeymismatch
               | MdbxTooLarge
               | MdbxThreadMismatch
               | MdbxTxnOverlapping
               | MdbxLastAddedErrcode
               | MdbxResultTrue
               | MdbxSuccess
               | MdbxResultFalse
               | MdbxEperm
               | MdbxEnofile
               | MdbxEintr
               | MdbxEio
               | MdbxEnomem
               | MdbxEaccess
               | MdbxEremote
               | MdbxEinval
               | MdbxErofs
               | MdbxEnosys
               | MdbxEnodata
  deriving (Show,Eq,Ord)
instance Enum MdbxError where
  succ MdbxKeyexist = MdbxNotfound
  succ MdbxFirstLmdbErrcode = MdbxNotfound
  pred :: MdbxEnvFlags -> MdbxEnvFlags
succ MdbxEnvFlags
MdbxNotfound = MdbxPageNotfound
  succ MdbxPageNotfound = MdbxCorrupted
  succ MdbxCorrupted = MdbxPanic
  succ MdbxPanic = MdbxVersionMismatch
  succ MdbxVersionMismatch = MdbxInvalid
  succ MdbxInvalid = MdbxMapFull
  succ MdbxMapFull = MdbxDbsFull
  succ MdbxDbsFull = MdbxReadersFull
  succ MdbxReadersFull = MdbxTxnFull
  succ MdbxTxnFull = MdbxCursorFull
  succ MdbxCursorFull = MdbxPageFull
  succ MdbxEnvFlags
MdbxPageFull = MdbxUnableExtendMapsize
  succ MdbxUnableExtendMapsize = MdbxIncompatible
  succ MdbxIncompatible = MdbxBadRslot
  succ MdbxBadRslot = MdbxBadTxn
  succ MdbxBadTxn = MdbxBadValsize
  succ MdbxBadValsize = MdbxBadDbi
  succ MdbxBadDbi = MdbxProblem
  succ MdbxEnvMode
MdbxEnv
MdbxProblem = MdbxBusy
  succ MdbxLastLmdbErrcode = MdbxBusy
  succ MdbxBusy = MdbxEmultival
  succ MdbxFirstAddedErrcode = MdbxEmultival
  succ MdbxEmultival = MdbxEbadsign
  succ MdbxEbadsign = MdbxWannaRecovery
  succ MdbxWannaRecovery = MdbxEkeymismatch
  succ MdbxEkeymismatch = MdbxTooLarge
  succ MdbxTooLarge = MdbxThreadMismatch
  succ MdbxThreadMismatch = MdbxTxnOverlapping
  succ MdbxTxnOverlapping = MdbxResultTrue
  succ MdbxLastAddedErrcode = MdbxResultTrue
  succ MdbxResultTrue = MdbxSuccess
  succ MdbxSuccess = MdbxEperm
  succ MdbxResultFalse = MdbxEperm
  succ MdbxEperm = MdbxEnofile
  succ MdbxEnofile = MdbxEintr
  succ MdbxEintr = MdbxEio
  succ MdbxEio = MdbxEnomem
  succ MdbxEnomem = MdbxEaccess
  succ MdbxEaccess = MdbxEremote
  succ MdbxEremote = MdbxEinval
  succ MdbxEinval = MdbxErofs
  succ MdbxErofs = MdbxEnosys
  succ MdbxEnosys = MdbxEnodata
  succ MdbxEnodata = error "MdbxError.succ: MdbxEnodata has no successor"

  pred MdbxNotfound = MdbxKeyexist
  pred MdbxPageNotfound = MdbxNotfound
  pred MdbxCorrupted = MdbxPageNotfound
  pred :: MdbxTxnFlags -> MdbxTxnFlags
pred MdbxPanic = MdbxCorrupted
  pred MdbxVersionMismatch = MdbxPanic
  pred MdbxInvalid = MdbxVersionMismatch
  pred MdbxMapFull = MdbxInvalid
  pred MdbxDbsFull = MdbxMapFull
  pred MdbxReadersFull = MdbxDbsFull
  pred MdbxTxnFull = MdbxReadersFull
  pred MdbxCursorFull = MdbxTxnFull
  pred MdbxPageFull = MdbxCursorFull
  pred MdbxUnableExtendMapsize = MdbxPageFull
  pred MdbxIncompatible = MdbxUnableExtendMapsize
  pred MdbxBadRslot = MdbxIncompatible
  pred MdbxBadTxn = MdbxBadRslot
  pred MdbxBadValsize = MdbxBadTxn
  pred MdbxBadDbi = MdbxBadValsize
  pred MdbxProblem = MdbxBadDbi
  pred MdbxLastLmdbErrcode = MdbxBadDbi
  pred MdbxBusy = MdbxProblem
  pred MdbxFirstAddedErrcode = MdbxProblem
  pred MdbxEmultival = MdbxBusy
  pred MdbxEbadsign = MdbxEmultival
  pred MdbxWannaRecovery = MdbxEbadsign
  pred MdbxEkeymismatch = MdbxWannaRecovery
  pred MdbxTooLarge = MdbxEkeymismatch
  pred MdbxThreadMismatch = MdbxTooLarge
  pred MdbxTxnOverlapping = MdbxThreadMismatch
  pred MdbxLastAddedErrcode = MdbxThreadMismatch
  pred MdbxResultTrue = MdbxTxnOverlapping
  pred MdbxSuccess = MdbxResultTrue
  pred MdbxResultFalse = MdbxResultTrue
  pred MdbxEperm = MdbxSuccess
  pred MdbxEnofile = MdbxEperm
  pred MdbxEintr = MdbxEnofile
  pred MdbxEio = MdbxEintr
  pred MdbxEnomem = MdbxEio
  pred MdbxEaccess = MdbxEnomem
  pred MdbxEremote = MdbxEaccess
  succ :: MdbxDbFlags -> MdbxDbFlags
pred MdbxEinval = MdbxEremote
  pred MdbxErofs = MdbxEinval
  pred MdbxEnosys = MdbxErofs
  pred MdbxEnodata = MdbxEnosys
  pred MdbxDbFlags
MdbxKeyexist = error "MdbxError.pred: MdbxKeyexist has no predecessor"
  pred MdbxFirstLmdbErrcode = error "MdbxError.pred: MdbxFirstLmdbErrcode has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from MdbxEnodata

  fromEnum MdbxKeyexist = (-30799)
  fromEnum MdbxFirstLmdbErrcode = (-30799)
  fromEnum MdbxNotfound = (-30798)
  fromEnum MdbxPageNotfound = (-30797)
  fromEnum MdbxCorrupted = (-30796)
  fromEnum MdbxPanic = (-30795)
  fromEnum MdbxVersionMismatch = (-30794)
  fromEnum MdbxInvalid = (-30793)
  fromEnum MdbxMapFull = (-30792)
  fromEnum MdbxDbsFull = (-30791)
  fromEnum MdbxReadersFull = (-30790)
  enumFrom :: MdbxDbFlags -> [MdbxDbFlags]
fromEnum MdbxTxnFull = (-30788)
  fromEnum MdbxCursorFull = (-30787)
  fromEnum MdbxPageFull = (-30786)
  fromEnum MdbxUnableExtendMapsize = (-30785)
  fromEnum MdbxIncompatible = (-30784)
  fromEnum MdbxBadRslot = (-30783)
  fromEnum MdbxBadTxn = (-30782)
  fromEnum MdbxBadValsize = (-30781)
  fromEnum MdbxBadDbi = (-30780)
  fromEnum MdbxProblem = (-30779)
  fromEnum MdbxLastLmdbErrcode = (-30779)
  fromEnum MdbxBusy = (-30778)
  fromEnum MdbxFirstAddedErrcode = (-30778)
  fromEnum MdbxEmultival = (-30421)
  fromEnum MdbxEbadsign = (-30420)
  fromEnum MdbxWannaRecovery = (-30419)
  fromEnum MdbxEkeymismatch = (-30418)
  fromEnum MdbxTooLarge = (-30417)
  fromEnum MdbxThreadMismatch = (-30416)
  fromEnum MdbxTxnOverlapping = (-30415)
  fromEnum MdbxLastAddedErrcode = (-30415)
  fromEnum MdbxResultTrue = (-1)
  fromEnum MdbxSuccess = 0
  fromEnum MdbxResultFalse = 0
  fromEnum MdbxEperm = 1
  fromEnum MdbxEnofile = 2
  fromEnum MdbxEintr = 4
  fromEnum MdbxEio = 5
  fromEnum MdbxEnomem = 12
  fromEnum MdbxEaccess = 13
  fromEnum MdbxEremote = 15
  fromEnum MdbxEinval = 22
  fromEnum MdbxErofs = 30
  fromEnum MdbxEnosys = 38
  fromEnum MdbxEnodata = 61

  toEnum (-30799) = MdbxKeyexist
  toEnum (-30798) = MdbxNotfound
  toEnum (-30797) = MdbxPageNotfound
  toEnum (-30796) = MdbxCorrupted
  toEnum (-30795) = MdbxPanic
  toEnum (-30794) = MdbxVersionMismatch
  toEnum (-30793) = MdbxInvalid
  toEnum (-30792) = MdbxMapFull
  toEnum (-30791) = MdbxDbsFull
  toEnum (-30790) = MdbxReadersFull
  toEnum (-30788) = MdbxTxnFull
  toEnum (-30787) = MdbxCursorFull
  toEnum (-30786) = MdbxPageFull
  Int -> IO Int
forall (m :: * -> *) a. Monad m => a -> m a
toEnum (-30785) = MdbxUnableExtendMapsize
  toEnum (-30784) = MdbxIncompatible
  toEnum (-30783) = MdbxBadRslot
  toEnum (-30782) = MdbxBadTxn
  toEnum (-30781) = MdbxBadValsize
  toEnum (-30780) = MdbxBadDbi
  toEnum (-30779) = MdbxProblem
  toEnum (-30778) = MdbxBusy
  toEnum (-30421) = MdbxEmultival
  toEnum (-30420) = MdbxEbadsign
  toEnum (-30419) = MdbxWannaRecovery
  toEnum (-30418) = MdbxEkeymismatch
  toEnum (-30417) = MdbxTooLarge
  toEnum (-30416) = MdbxThreadMismatch
  toEnum (-30415) = MdbxTxnOverlapping
  toEnum (-1) = MdbxResultTrue
  toEnum 0 = MdbxSuccess
  toEnum 1 = MdbxEperm
  toEnum 2 = MdbxEnofile
  toEnum 4 = MdbxEintr
  toEnum 5 = MdbxEio
  toEnum 12 = MdbxEnomem
  toEnum 13 = MdbxEaccess
  toEnum 15 = MdbxEremote
  toEnum 22 = MdbxEinval
  toEnum 30 = MdbxErofs
  toEnum 38 = MdbxEnosys
  toEnum 61 = MdbxEnodata
  toEnum unmatched = error ("MdbxError.toEnum: Cannot match " ++ show unmatched)

{-# LINE 87 "src/Mdbx/FFI.chs" #-}


-- Environment

-- | Environment object, needed for all the operations.
newtype MdbxEnv = MdbxEnv (C2HSImp.Ptr (MdbxEnv))
{-# LINE 92 "src/Mdbx/FFI.chs" #-}

deriving instance Storable MdbxEnv

-- | Flags for opening an environment.
data MdbxEnvFlags
  = MdbxEnvDefaults
  | MdbxSyncDurable
  | MdbxNosubdir
  | MdbxSafeNosync
  | MdbxMapasync
  | MdbxRdonly
  | MdbxNometasync
  | MdbxWritemap
  | MdbxUtterlyNosync
  | MdbxNotls
  | MdbxExclusive
  | MdbxNordahead
  | MdbxNomeminit
  | MdbxCoalesce
  | MdbxLiforeclaim
  | MdbxPageperturb
  | MdbxAccede
  deriving (Show, Eq, Ord)

--{# enum MDBX_env_flags_t as MdbxEnvFlags {underscoreToCase} deriving (Show, Eq, Ord) #}

instance Enum MdbxEnvFlags where
  succ MdbxEnvDefaults = MdbxNosubdir
  succ MdbxSyncDurable = MdbxNosubdir
  succ MdbxNosubdir = MdbxSafeNosync
  succ MdbxSafeNosync = MdbxRdonly
  succ MdbxMapasync = MdbxRdonly
  succ MdbxRdonly = MdbxNometasync
  succ MdbxNometasync = MdbxWritemap
  succ MdbxWritemap = MdbxUtterlyNosync
  succ MdbxUtterlyNosync = MdbxNotls
  succ MdbxNotls = MdbxExclusive
  succ MdbxExclusive = MdbxNordahead
  succ MdbxNordahead = MdbxNomeminit
  succ MdbxNomeminit = MdbxCoalesce
  succ MdbxCoalesce = MdbxLiforeclaim
  succ MdbxLiforeclaim = MdbxPageperturb
  succ MdbxPageperturb = MdbxAccede
  succ MdbxAccede = error "MdbxEnvFlags.succ: MdbxAccede has no successor"

  pred MdbxNosubdir = MdbxEnvDefaults
  pred MdbxSafeNosync = MdbxNosubdir
  pred MdbxMapasync = MdbxNosubdir
  pred MdbxRdonly = MdbxSafeNosync
  pred MdbxNometasync = MdbxRdonly
  pred MdbxWritemap = MdbxNometasync
  pred MdbxUtterlyNosync = MdbxWritemap
  pred MdbxNotls = MdbxUtterlyNosync
  pred MdbxExclusive = MdbxNotls
  pred MdbxNordahead = MdbxExclusive
  pred MdbxNomeminit = MdbxNordahead
  pred MdbxCoalesce = MdbxNomeminit
  pred MdbxLiforeclaim = MdbxCoalesce
  pred MdbxPageperturb = MdbxLiforeclaim
  pred MdbxAccede = MdbxPageperturb
  pred MdbxEnvDefaults = error "MdbxEnvFlags.pred: MdbxEnvDefaults has no predecessor"
  pred MdbxSyncDurable = error "MdbxEnvFlags.pred: MdbxSyncDurable has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from MdbxAccede

  fromEnum MdbxEnvDefaults = 0
  fromEnum MdbxSyncDurable = 0
  fromEnum MdbxNosubdir = 16384
  fromEnum MdbxSafeNosync = 65536
  fromEnum MdbxMapasync = 65536
  fromEnum MdbxRdonly = 131072
  fromEnum MdbxNometasync = 262144
  fromEnum MdbxWritemap = 524288
  fromEnum MdbxUtterlyNosync = 1114112
  fromEnum MdbxNotls = 2097152
  fromEnum MdbxExclusive = 4194304
  fromEnum MdbxNordahead = 8388608
  fromEnum MdbxNomeminit = 16777216
  fromEnum MdbxCoalesce = 33554432
  fromEnum MdbxLiforeclaim = 67108864
  fromEnum MdbxPageperturb = 134217728
  fromEnum MdbxAccede = 1073741824

  toEnum 0 = MdbxEnvDefaults
  toEnum 16384 = MdbxNosubdir
  toEnum 65536 = MdbxSafeNosync
  toEnum 131072 = MdbxRdonly
  toEnum 262144 = MdbxNometasync
  toEnum 524288 = MdbxWritemap
  toEnum 1114112 = MdbxUtterlyNosync
  toEnum 2097152 = MdbxNotls
  toEnum 4194304 = MdbxExclusive
  toEnum 8388608 = MdbxNordahead
  toEnum 16777216 = MdbxNomeminit
  toEnum 33554432 = MdbxCoalesce
  toEnum 67108864 = MdbxLiforeclaim
  toEnum 134217728 = MdbxPageperturb
  toEnum 1073741824 = MdbxAccede
  toEnum unmatched = error ("MdbxEnvFlags.toEnum: Cannot match " ++ show unmatched)

{-# LINE 117 "src/Mdbx/FFI.chs" #-}


-- | UNIX permissions to set on created files. Zero value means to open existing, but do not create.
type MdbxEnvMode = (C2HSImp.CUInt)
{-# LINE 120 "src/Mdbx/FFI.chs" #-}


{-# LINE 121 "src/Mdbx/FFI.chs" #-}


-- Opening and closing.

-- | Creates an environment. Represents a database in the file system.
mdbx_env_create :: IO ((Int), (MdbxEnv))
mdbx_env_create =
  alloca $ \a1' -> 
  mdbx_env_create'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a1'>>= \a1'' -> 
  return (res', a1'')

{-# LINE 126 "src/Mdbx/FFI.chs" #-}


{--
Haddock ignores these:

- size_lower: Minimum size of the database in bytes.
- size_now: Current size of the database in bytes.
- size_upper: Maximum size of the database in bytes.
- growth_step: Step growth size of the database in bytes. Must be greater than
  zero to allow for growth.
- shrink_threshold: Step shrink size of the database in bytes. Must be greater
  than zero to allow for shrinkage and lower than growth_step to avoid shrinking
  after growth.
- pagesize: Page size of the database in bytes.
--}

{-|
Sets geometry of an environment. All the parameters can receive -1 to keep the
current value. Receives (expressed in bytes): size_lower, size_now, size_upper,
growth_step, shrink_threshold, pagesize.
-}
mdbx_env_set_geometry :: (MdbxEnv) -> (Int) -> (Int) -> (Int) -> (Int) -> (Int) -> (Int) -> IO ((Int))
mdbx_env_set_geometry a1 a2 a3 a4 a5 a6 a7 =
  let {a1' = id a1} in 
  let {a2' = fromIntegral a2} in 
  let {a3' = fromIntegral a3} in 
  let {a4' = fromIntegral a4} in 
  let {a5' = fromIntegral a5} in 
  let {a6' = fromIntegral a6} in 
  let {a7' = fromIntegral a7} in 
  mdbx_env_set_geometry'_ a1' a2' a3' a4' a5' a6' a7' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 147 "src/Mdbx/FFI.chs" #-}


-- | Opens an environment. Receives name, flags and mode.
mdbx_env_open :: (MdbxEnv) -> (String) -> ([MdbxEnvFlags]) -> (MdbxEnvMode) -> IO ((Int))
mdbx_env_open a1 a2 a3 a4 =
  let {a1' = id a1} in 
  C2HSImp.withCString a2 $ \a2' -> 
  let {a3' = bitMask a3} in 
  let {a4' = id a4} in 
  mdbx_env_open'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 150 "src/Mdbx/FFI.chs" #-}


-- | Closes an environment.
mdbx_env_close :: (MdbxEnv) -> IO ((Int))
mdbx_env_close a1 =
  let {a1' = id a1} in 
  mdbx_env_close'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 153 "src/Mdbx/FFI.chs" #-}


{-- Closes an env (env, dontSync) --}
-- Fails under ghci
-- {# fun unsafe mdbx_env_close_ex {`MdbxEnv', `Bool'} -> `Int' #}

-- Transaction

-- | Transaction instance. Needed for all operations with data, even reading.
newtype MdbxTxn = MdbxTxn (C2HSImp.Ptr (MdbxTxn))
{-# LINE 162 "src/Mdbx/FFI.chs" #-}

deriving instance Storable MdbxTxn

-- | Flags for a transaction.
data MdbxTxnFlags
  = MdbxTxnReadwrite
  | MdbxTxnNosync
  | MdbxTxnRdonly
  | MdbxTxnNometasync
  | MdbxTxnRdonlyPrepare
  | MdbxTxnTry
  deriving (Show, Eq, Ord)

-- {# enum MDBX_txn_flags_t as MdbxTxnFlags {underscoreToCase} deriving (Show, Eq, Ord) #}

instance Enum MdbxTxnFlags where
  succ MdbxTxnReadwrite = MdbxTxnNosync
  succ MdbxTxnNosync = MdbxTxnRdonly
  succ MdbxTxnRdonly = MdbxTxnNometasync
  succ MdbxTxnNometasync = MdbxTxnRdonlyPrepare
  succ MdbxTxnRdonlyPrepare = MdbxTxnTry
  succ MdbxTxnTry = error "MdbxTxnFlags.succ: MdbxTxnTry has no successor"

  pred MdbxTxnNosync = MdbxTxnReadwrite
  pred MdbxTxnRdonly = MdbxTxnNosync
  pred MdbxTxnNometasync = MdbxTxnRdonly
  pred MdbxTxnRdonlyPrepare = MdbxTxnNometasync
  pred MdbxTxnTry = MdbxTxnRdonlyPrepare
  pred MdbxTxnReadwrite = error "MdbxTxnFlags.pred: MdbxTxnReadwrite has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from MdbxTxnTry

  fromEnum MdbxTxnReadwrite = 0
  fromEnum MdbxTxnNosync = 65536
  fromEnum MdbxTxnRdonly = 131072
  fromEnum MdbxTxnNometasync = 262144
  fromEnum MdbxTxnRdonlyPrepare = 16908288
  fromEnum MdbxTxnTry = 268435456

  toEnum 0 = MdbxTxnReadwrite
  toEnum 65536 = MdbxTxnNosync
  toEnum 131072 = MdbxTxnRdonly
  toEnum 262144 = MdbxTxnNometasync
  toEnum 16908288 = MdbxTxnRdonlyPrepare
  toEnum 268435456 = MdbxTxnTry
  toEnum unmatched = error ("MdbxTxnFlags.toEnum: Cannot match " ++ show unmatched)

{-# LINE 176 "src/Mdbx/FFI.chs" #-}


{-|
Begins a new transaction.

Arguments:

- Environment.
- Parent transaction, or Nothing.
- Flags.
-}
mdbx_txn_begin :: (MdbxEnv) -> (Maybe MdbxTxn) -> ([MdbxTxnFlags]) -> IO ((Int), (MdbxTxn))
mdbx_txn_begin a1 a2 a3 =
  let {a1' = id a1} in 
  maybeTxn a2 $ \a2' -> 
  let {a3' = bitMask a3} in 
  alloca $ \a4' -> 
  mdbx_txn_begin'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a4'>>= \a4'' -> 
  return (res', a4'')

{-# LINE 187 "src/Mdbx/FFI.chs" #-}


-- | Commits a transaction.
mdbx_txn_commit :: (MdbxTxn) -> IO ((Int))
mdbx_txn_commit a1 =
  let {a1' = id a1} in 
  mdbx_txn_commit'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 190 "src/Mdbx/FFI.chs" #-}


-- | Aborts a transaction.
mdbx_txn_abort :: (MdbxTxn) -> IO ((Int))
mdbx_txn_abort a1 =
  let {a1' = id a1} in 
  mdbx_txn_abort'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 193 "src/Mdbx/FFI.chs" #-}


-- | Gets the environment from a transaction.
mdbx_txn_env :: (MdbxTxn) -> IO ((MdbxEnv))
mdbx_txn_env a1 =
  let {a1' = id a1} in 
  mdbx_txn_env'_ a1' >>= \res ->
  let {res' = id res} in
  return (res')

{-# LINE 196 "src/Mdbx/FFI.chs" #-}


-- MdbxEnv* mdbx_txn_env	(	const MdbxTxn * 	txn	)

-- Database

-- | Database instance. Represents a logical table in the database.
type MdbxDbi = (C2HSImp.CUInt)
{-# LINE 203 "src/Mdbx/FFI.chs" #-}


{-# LINE 204 "src/Mdbx/FFI.chs" #-}


-- | Flags for a database.
data MdbxDbFlags
  = MdbxDbDefaults
  | MdbxReversekey
  | MdbxDupsort
  | MdbxIntegerkey
  | MdbxDupfixed
  | MdbxIntegerdup
  | MdbxReversedup
  | MdbxCreate
  | MdbxDbAccede
  deriving (Show, Eq, Ord)

--{# enum MDBX_db_flags_t as MdbxDbFlags {underscoreToCase} deriving (Show, Eq, Ord) #}

instance Enum MdbxDbFlags where
  succ MdbxDbDefaults = MdbxReversekey
  succ MdbxReversekey = MdbxDupsort
  succ MdbxDupsort = MdbxIntegerkey
  succ MdbxIntegerkey = MdbxDupfixed
  succ MdbxDupfixed = MdbxIntegerdup
  succ MdbxIntegerdup = MdbxReversedup
  succ MdbxReversedup = MdbxCreate
  succ MdbxCreate = MdbxDbAccede
  succ MdbxDbAccede = error "MdbxDbFlags.succ: MdbxDbAccede has no successor"

  pred MdbxReversekey = MdbxDbDefaults
  pred MdbxDupsort = MdbxReversekey
  pred MdbxIntegerkey = MdbxDupsort
  pred MdbxDupfixed = MdbxIntegerkey
  pred MdbxIntegerdup = MdbxDupfixed
  pred MdbxReversedup = MdbxIntegerdup
  pred MdbxCreate = MdbxReversedup
  pred MdbxDbAccede = MdbxCreate
  pred MdbxDbDefaults = error "MdbxDbFlags.pred: MdbxDbDefaults has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from MdbxDbAccede

  fromEnum MdbxDbDefaults = 0
  fromEnum MdbxReversekey = 2
  fromEnum MdbxDupsort = 4
  fromEnum MdbxIntegerkey = 8
  fromEnum MdbxDupfixed = 16
  fromEnum MdbxIntegerdup = 32
  fromEnum MdbxReversedup = 64
  fromEnum MdbxCreate = 262144
  fromEnum MdbxDbAccede = 1073741824

  toEnum 0 = MdbxDbDefaults
  toEnum 2 = MdbxReversekey
  toEnum 4 = MdbxDupsort
  toEnum 8 = MdbxIntegerkey
  toEnum 16 = MdbxDupfixed
  toEnum 32 = MdbxIntegerdup
  toEnum 64 = MdbxReversedup
  toEnum 262144 = MdbxCreate
  toEnum 1073741824 = MdbxDbAccede
  toEnum unmatched = error ("MdbxDbFlags.toEnum: Cannot match " ++ show unmatched)

{-# LINE 220 "src/Mdbx/FFI.chs" #-}


{-|
Opens a database.

Arguments:

- Transaction.
- Name.
- Flags.
-}
mdbx_dbi_open :: (MdbxTxn) -> (Maybe String) -> ([MdbxDbFlags]) -> IO ((Int), (MdbxDbi))
mdbx_dbi_open a1 a2 a3 =
  let {a1' = id a1} in 
  maybeString a2 $ \a2' -> 
  let {a3' = bitMask a3} in 
  alloca $ \a4' -> 
  mdbx_dbi_open'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a4'>>= \a4'' -> 
  return (res', a4'')

{-# LINE 231 "src/Mdbx/FFI.chs" #-}


-- | Closes a database.
mdbx_dbi_close :: (MdbxEnv) -> (MdbxDbi) -> IO ((Int))
mdbx_dbi_close a1 a2 =
  let {a1' = id a1} in 
  let {a2' = id a2} in 
  mdbx_dbi_close'_ a1' a2' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 234 "src/Mdbx/FFI.chs" #-}


-- CRUD

-- | Binary blob representing a key or value in the database.
data MdbxVal = MdbxVal {
  mvlSize :: {-# UNPACK #-} !(C2HSImp.CULong),
  mvlData :: {-# UNPACK #-} !(Ptr ())
} deriving (Eq, Show)

--instance Show MdbxVal where
--  show (MdbxVal sz dt) = "MdbxVal { size = " ++ show sz ++ ", data = " ++ show dt ++ " }"

instance Storable MdbxVal where
  sizeOf _ = 16
{-# LINE 248 "src/Mdbx/FFI.chs" #-}

  alignment _ = 8
{-# LINE 249 "src/Mdbx/FFI.chs" #-}

  peek ptr = do
    sz <- (\ptr -> do {C2HSImp.peekByteOff ptr 8 :: IO C2HSImp.CULong}) ptr
    pd <- (\ptr -> do {C2HSImp.peekByteOff ptr 0 :: IO (C2HSImp.Ptr ())}) ptr
    return $! MdbxVal sz pd
  poke ptr (MdbxVal sz pd) = do
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 8 (val :: C2HSImp.CULong)}) ptr sz
    (\ptr val -> do {C2HSImp.pokeByteOff ptr 0 (val :: (C2HSImp.Ptr ()))}) ptr pd

-- | Sample empty value
emptyMdbxVal :: MdbxVal
emptyMdbxVal = MdbxVal 0 nullPtr

type MdbxValPtr = C2HSImp.Ptr (MdbxVal)
{-# LINE 262 "src/Mdbx/FFI.chs" #-}


-- | Flags for all data related operations.
data MdbxPutFlags
  = MdbxUpsert
  | MdbxNooverwrite
  | MdbxNodupdata
  | MdbxCurrent
  | MdbxAlldups
  | MdbxReserve
  | MdbxAppend
  | MdbxAppenddup
  | MdbxMultiple
  deriving (Show, Eq, Ord)

--{# enum MDBX_put_flags_t as MdbxPutFlags {underscoreToCase} deriving (Show, Eq, Ord) #}

instance Enum MdbxPutFlags where
  succ MdbxUpsert = MdbxNooverwrite
  succ MdbxNooverwrite = MdbxNodupdata
  succ MdbxNodupdata = MdbxCurrent
  succ MdbxCurrent = MdbxAlldups
  succ MdbxAlldups = MdbxReserve
  succ MdbxReserve = MdbxAppend
  succ MdbxAppend = MdbxAppenddup
  succ MdbxAppenddup = MdbxMultiple
  succ MdbxMultiple = error "MdbxPutFlags.succ: MdbxMultiple has no successor"

  pred MdbxNooverwrite = MdbxUpsert
  pred MdbxNodupdata = MdbxNooverwrite
  pred MdbxCurrent = MdbxNodupdata
  pred MdbxAlldups = MdbxCurrent
  pred MdbxReserve = MdbxAlldups
  pred MdbxAppend = MdbxReserve
  pred MdbxAppenddup = MdbxAppend
  pred MdbxMultiple = MdbxAppenddup
  pred MdbxUpsert = error "MdbxPutFlags.pred: MdbxUpsert has no predecessor"

  enumFromTo from to = go from
    where
      end = fromEnum to
      go v = case compare (fromEnum v) end of
                 LT -> v : go (succ v)
                 EQ -> [v]
                 GT -> []

  enumFrom from = enumFromTo from MdbxMultiple

  fromEnum MdbxUpsert = 0
  fromEnum MdbxNooverwrite = 16
  fromEnum MdbxNodupdata = 32
  fromEnum MdbxCurrent = 64
  fromEnum MdbxAlldups = 128
  fromEnum MdbxReserve = 65536
  fromEnum MdbxAppend = 131072
  fromEnum MdbxAppenddup = 262144
  fromEnum MdbxMultiple = 524288

  toEnum 0 = MdbxUpsert
  toEnum 16 = MdbxNooverwrite
  toEnum 32 = MdbxNodupdata
  toEnum 64 = MdbxCurrent
  toEnum 128 = MdbxAlldups
  toEnum 65536 = MdbxReserve
  toEnum 131072 = MdbxAppend
  toEnum 262144 = MdbxAppenddup
  toEnum 524288 = MdbxMultiple
  toEnum unmatched = error ("MdbxPutFlags.toEnum: Cannot match " ++ show unmatched)

{-# LINE 278 "src/Mdbx/FFI.chs" #-}


{-|
Stores a key/value pair.

Arguments:

- Transaction.
- Database.
- Key.
- Value.
-}
mdbx_put :: (MdbxTxn) -> (MdbxDbi) -> (MdbxVal) -> (MdbxVal) -> ([MdbxPutFlags]) -> IO ((Int))
mdbx_put a1 a2 a3 a4 a5 =
  let {a1' = id a1} in 
  let {a2' = id a2} in 
  with a3 $ \a3' -> 
  with a4 $ \a4' -> 
  let {a5' = bitMask a5} in 
  mdbx_put'_ a1' a2' a3' a4' a5' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 290 "src/Mdbx/FFI.chs" #-}


{-|
Gets a value with the given key.

Arguments:

- Transaction.
- Database.
- Key.
-}
mdbx_get :: (MdbxTxn) -> (MdbxDbi) -> (MdbxVal) -> IO ((Int), (MdbxVal))
mdbx_get a1 a2 a3 =
  let {a1' = id a1} in 
  let {a2' = id a2} in 
  with a3 $ \a3' -> 
  alloca $ \a4' -> 
  mdbx_get'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a4'>>= \a4'' -> 
  return (res', a4'')

{-# LINE 301 "src/Mdbx/FFI.chs" #-}


{-|
Gets a value with the given key.

Arguments:

- Transaction.
- Database.
- Key.
-}
mdbx_del :: (MdbxTxn) -> (MdbxDbi) -> (MdbxVal) -> (Maybe MdbxVal) -> IO ((Int))
mdbx_del a1 a2 a3 a4 =
  let {a1' = id a1} in 
  let {a2' = id a2} in 
  with a3 $ \a3' -> 
  withMaybe a4 $ \a4' -> 
  mdbx_del'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 312 "src/Mdbx/FFI.chs" #-}


-- Cursor

-- | Cursor instance. Used for efficient navigation in a database.
newtype MdbxCursor = MdbxCursor (C2HSImp.Ptr (MdbxCursor))
{-# LINE 317 "src/Mdbx/FFI.chs" #-}

deriving instance Storable MdbxCursor

-- | Flags for cursor operations.
data MdbxCursorOp
  = MdbxFirst
  | MdbxFirstDup
  | MdbxGetBoth
  | MdbxGetBothRange
  | MdbxGetCurrent
  | MdbxGetMultiple
  | MdbxLast
  | MdbxLastDup
  | MdbxNext
  | MdbxNextDup
  | MdbxNextMultiple
  | MdbxNextNodup
  | MdbxPrev
  | MdbxPrevDup
  | MdbxPrevNodup
  | MdbxSet
  | MdbxSetKey
  | MdbxSetRange
  | MdbxPrevMultiple
  | MdbxSetLowerbound
  deriving (Int -> MdbxCursorOp -> ShowS
[MdbxCursorOp] -> ShowS
MdbxCursorOp -> String
(Int -> MdbxCursorOp -> ShowS)
-> (MdbxCursorOp -> String)
-> ([MdbxCursorOp] -> ShowS)
-> Show MdbxCursorOp
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [MdbxCursorOp] -> ShowS
$cshowList :: [MdbxCursorOp] -> ShowS
show :: MdbxCursorOp -> String
$cshow :: MdbxCursorOp -> String
showsPrec :: Int -> MdbxCursorOp -> ShowS
$cshowsPrec :: Int -> MdbxCursorOp -> ShowS
Show, MdbxCursorOp -> MdbxCursorOp -> Bool
(MdbxCursorOp -> MdbxCursorOp -> Bool)
-> (MdbxCursorOp -> MdbxCursorOp -> Bool) -> Eq MdbxCursorOp
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: MdbxCursorOp -> MdbxCursorOp -> Bool
$c/= :: MdbxCursorOp -> MdbxCursorOp -> Bool
== :: MdbxCursorOp -> MdbxCursorOp -> Bool
$c== :: MdbxCursorOp -> MdbxCursorOp -> Bool
Eq, Eq MdbxCursorOp
Eq MdbxCursorOp
-> (MdbxCursorOp -> MdbxCursorOp -> Ordering)
-> (MdbxCursorOp -> MdbxCursorOp -> Bool)
-> (MdbxCursorOp -> MdbxCursorOp -> Bool)
-> (MdbxCursorOp -> MdbxCursorOp -> Bool)
-> (MdbxCursorOp -> MdbxCursorOp -> Bool)
-> (MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp)
-> (MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp)
-> Ord MdbxCursorOp
MdbxCursorOp -> MdbxCursorOp -> Bool
MdbxCursorOp -> MdbxCursorOp -> Ordering
MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp
$cmin :: MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp
max :: MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp
$cmax :: MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp
>= :: MdbxCursorOp -> MdbxCursorOp -> Bool
$c>= :: MdbxCursorOp -> MdbxCursorOp -> Bool
> :: MdbxCursorOp -> MdbxCursorOp -> Bool
$c> :: MdbxCursorOp -> MdbxCursorOp -> Bool
<= :: MdbxCursorOp -> MdbxCursorOp -> Bool
$c<= :: MdbxCursorOp -> MdbxCursorOp -> Bool
< :: MdbxCursorOp -> MdbxCursorOp -> Bool
$c< :: MdbxCursorOp -> MdbxCursorOp -> Bool
compare :: MdbxCursorOp -> MdbxCursorOp -> Ordering
$ccompare :: MdbxCursorOp -> MdbxCursorOp -> Ordering
$cp1Ord :: Eq MdbxCursorOp
Ord)

--{# enum MDBX_cursor_op as MdbxCursorOp {underscoreToCase} deriving (Show, Eq, Ord) #}

  deriving (Int -> MdbxCursorOp
MdbxCursorOp -> Int
MdbxCursorOp -> [MdbxCursorOp]
MdbxCursorOp -> MdbxCursorOp
MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
(MdbxCursorOp -> MdbxCursorOp)
-> (MdbxCursorOp -> MdbxCursorOp)
-> (Int -> MdbxCursorOp)
-> (MdbxCursorOp -> Int)
-> (MdbxCursorOp -> [MdbxCursorOp])
-> (MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp])
-> (MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp])
-> (MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp])
-> Enum MdbxCursorOp
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
$cenumFromThenTo :: MdbxCursorOp -> MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
enumFromTo :: MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
$cenumFromTo :: MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
enumFromThen :: MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
$cenumFromThen :: MdbxCursorOp -> MdbxCursorOp -> [MdbxCursorOp]
enumFrom :: MdbxCursorOp -> [MdbxCursorOp]
$cenumFrom :: MdbxCursorOp -> [MdbxCursorOp]
fromEnum :: MdbxCursorOp -> Int
$cfromEnum :: MdbxCursorOp -> Int
toEnum :: Int -> MdbxCursorOp
$ctoEnum :: Int -> MdbxCursorOp
pred :: MdbxCursorOp -> MdbxCursorOp
$cpred :: MdbxCursorOp -> MdbxCursorOp
succ :: MdbxCursorOp -> MdbxCursorOp
$csucc :: MdbxCursorOp -> MdbxCursorOp
Enum)

{-# LINE 345 "src/Mdbx/FFI.chs" #-}


{-|
Opens a new cursor.

Arguments:

- Transaction.
- Database.
-}
mdbx_cursor_open :: (MdbxTxn) -> (MdbxDbi) -> IO ((Int), (MdbxCursor))
mdbx_cursor_open :: MdbxTxn -> MdbxEnvMode -> IO (Int, MdbxCursor)
mdbx_cursor_open MdbxTxn
a1 MdbxEnvMode
a2 =
  let {a1' :: MdbxTxn
a1' = MdbxTxn -> MdbxTxn
forall a. a -> a
id MdbxTxn
a1} in 
  let {a2' :: MdbxEnvMode
a2' = MdbxEnvMode -> MdbxEnvMode
forall a. a -> a
id MdbxEnvMode
a2} in 
  (Ptr MdbxCursor -> IO (Int, MdbxCursor)) -> IO (Int, MdbxCursor)
forall a b. Storable a => (Ptr a -> IO b) -> IO b
alloca ((Ptr MdbxCursor -> IO (Int, MdbxCursor)) -> IO (Int, MdbxCursor))
-> (Ptr MdbxCursor -> IO (Int, MdbxCursor)) -> IO (Int, MdbxCursor)
forall a b. (a -> b) -> a -> b
$ \Ptr MdbxCursor
a3' -> 
  MdbxTxn -> MdbxEnvMode -> Ptr MdbxCursor -> IO CInt
mdbx_cursor_open'_ MdbxTxn
a1' MdbxEnvMode
a2' a3' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a3'>>= \a3'' -> 
  return (res', a3'')

{-# LINE 355 "src/Mdbx/FFI.chs" #-}


-- | Closes a cursor.
mdbx_cursor_close :: (MdbxCursor) -> IO ()
mdbx_cursor_close a1 =
  let {a1' = id a1} in 
  mdbx_cursor_close'_ a1' >>
  return ()

{-# LINE 358 "src/Mdbx/FFI.chs" #-}


-- | Removes the current key/value pair.
mdbx_cursor_del :: (MdbxCursor) -> ([MdbxPutFlags]) -> IO ((Int))
mdbx_cursor_del a1 a2 =
  let {a1' = id a1} in 
  let {a2' = bitMask a2} in 
  mdbx_cursor_del'_ a1' a2' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 361 "src/Mdbx/FFI.chs" #-}


-- | Returns the current key/value pair.
mdbx_cursor_get :: (MdbxCursor) -> (MdbxVal) -> (MdbxCursorOp) -> IO ((Int), (MdbxVal), (MdbxVal))
mdbx_cursor_get a1 a2 a4 =
  let {a1' = id a1} in 
  with a2 $ \a2' -> 
  alloca $ \a3' -> 
  let {a4' = (fromIntegral . fromEnum) a4} in 
  mdbx_cursor_get'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a2'>>= \a2'' -> 
  peek  a3'>>= \a3'' -> 
  return (res', a2'', a3'')

{-# LINE 364 "src/Mdbx/FFI.chs" #-}


{-| Sets the value for the current key.

Arguments:

- Cursor.
- Key.
- Value.
- FLags.
-}
mdbx_cursor_put :: (MdbxCursor) -> (MdbxVal) -> (MdbxVal) -> ([MdbxPutFlags]) -> IO ((Int))
mdbx_cursor_put a1 a2 a3 a4 =
  let {a1' = id a1} in 
  with a2 $ \a2' -> 
  with a3 $ \a3' -> 
  let {a4' = bitMask a4} in 
  mdbx_cursor_put'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 375 "src/Mdbx/FFI.chs" #-}


-- | Returns the count of duplicates in the current key.
mdbx_cursor_count :: (MdbxCursor) -> IO ((Int), (CSize))
mdbx_cursor_count a1 =
  let {a1' = id a1} in 
  alloca $ \a2' -> 
  mdbx_cursor_count'_ a1' a2' >>= \res ->
  let {res' = fromIntegral res} in
  peek  a2'>>= \a2'' -> 
  return (res', a2'')

mdbx_cmp :: MdbxTxn -> MdbxEnvMode -> MdbxVal -> MdbxVal -> IO Int
{-# LINE 378 "src/Mdbx/FFI.chs" #-}


-- Helpers

-- | Returns the description of a given error number.
mdbx_strerror :: (Int) -> IO ((String))
mdbx_strerror a1 =
  let {a1' = fromIntegral a1} in 
  mdbx_strerror'_ a1' >>= \res ->
  C2HSImp.peekCString res >>= \res' ->
  return (res')

{-# LINE 383 "src/Mdbx/FFI.chs" #-}


-- | Compares two values as a binary blob.
mdbx_cmp :: (MdbxTxn) -> (MdbxDbi) -> (MdbxVal) -> (MdbxVal) -> IO ((Int))
mdbx_cmp a1 a2 a3 a4 =
  let {a1' = id a1} in 
  let {a2' = id a2} in 
  with a3 $ \a3' -> 
  with a4 $ \a4' -> 
  mdbx_cmp'_ a1' a2' a3' a4' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

maybeTxn :: Maybe MdbxTxn -> (MdbxTxn -> IO c) -> IO c
{-# LINE 386 "src/Mdbx/FFI.chs" #-}


bitMask :: Enum a => [a] -> C2HSImp.CInt
bitMask = foldl (.|.) 0 . fmap (fromIntegral . fromEnum)

maybeString :: Maybe String -> (Ptr CChar -> IO c) -> IO c
maybeString Nothing fn = fn nullPtr
maybeString (Just val) fn = withCString val fn

maybeTxn :: Maybe MdbxTxn -> (MdbxTxn -> IO c) -> IO c
maybeTxn Nothing fn = fn (MdbxTxn nullPtr)
maybeTxn (Just val) fn = fn val

withMaybe :: Storable a => Maybe a -> (Ptr a -> IO c) -> IO c
withMaybe :: Maybe a -> (Ptr a -> IO c) -> IO c
withMaybe Maybe a
Nothing Ptr a -> IO c
fn = Ptr a -> IO c
fn Ptr a
forall a. Ptr a
nullPtr
withMaybe (Just a
val) Ptr a -> IO c
fn = a -> (Ptr a -> IO c) -> IO c
forall a b. Storable a => a -> (Ptr a -> IO b) -> IO b
with a
val Ptr a -> IO c
fn

-- Conversion for types used in keys

-- | Converts a Float value to an unsigned Word that can be used by libmdbx's compare function.
mdbx_key_from_float :: (Float) -> (Word32)
mdbx_key_from_float :: Float -> Word32
mdbx_key_from_float Float
a1 =
  IO Word32 -> Word32
forall a. IO a -> a
C2HSImp.unsafePerformIO (IO Word32 -> Word32) -> IO Word32 -> Word32
forall a b. (a -> b) -> a -> b
$
  let {a1' :: CFloat
a1' = Float -> CFloat
forall a b. (Real a, Fractional b) => a -> b
realToFrac Float
a1} in 
  CFloat -> IO MdbxEnvMode
mdbx_key_from_float'_ CFloat
a1' IO MdbxEnvMode -> (MdbxEnvMode -> IO Word32) -> IO Word32
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \MdbxEnvMode
res ->
  let {res' :: Word32
res' = MdbxEnvMode -> Word32
forall a b. (Integral a, Num b) => a -> b
fromIntegral MdbxEnvMode
res} in
  Word32 -> IO Word32
forall (m :: * -> *) a. Monad m => a -> m a
return (Word32
res')

{-# LINE 406 "src/Mdbx/FFI.chs" #-}

-- | Converts a Double value to an unsigned Word that can be used by libmdbx's compare function.
mdbx_key_from_double :: (Double) -> (Word64)
mdbx_key_from_double a1 =
  C2HSImp.unsafePerformIO $
  let {a1' = realToFrac a1} in 
  mdbx_key_from_double'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 408 "src/Mdbx/FFI.chs" #-}

-- | Converts a 32bits signed Int value to an unsigned Word that can be used by libmdbx's compare function.
mdbx_key_from_int32 :: (Int32) -> (Word32)
mdbx_key_from_int32 a1 =
  C2HSImp.unsafePerformIO $
  let {a1' = fromIntegral a1} in 
  mdbx_key_from_int32'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 410 "src/Mdbx/FFI.chs" #-}

-- | Converts a 64bits signed Int value to an unsigned Word that can be used by libmdbx's compare function.
mdbx_key_from_int64 :: (Int64) -> (Word64)
mdbx_key_from_int64 a1 =
  C2HSImp.unsafePerformIO $
  let {a1' = fromIntegral a1} in 
  mdbx_key_from_int64'_ a1' >>= \res ->
  let {res' = fromIntegral res} in
  return (res')

{-# LINE 412 "src/Mdbx/FFI.chs" #-}


-- These functions are re-implemented locally because they are not exported by libmdbx.

-- | Converts an unsigned Word to a Float value.
mdbx_float_from_key :: Word32 -> Float
mdbx_float_from_key val = value where
  intVal :: Int32 = fromIntegral val
  value
    | intVal < 0 = castWord32ToFloat $ val + 0x80000000
    | otherwise = castWord32ToFloat $ 0xffffFFFF - val

-- | Converts an unsigned Word to a Double value.
mdbx_double_from_key :: Word64 -> Double
mdbx_double_from_key :: Word64 -> Double
mdbx_double_from_key Word64
val = Double
value where
  Int64
intVal :: Int64 = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word64
val
  value :: Double
value
    | Int64
intVal Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
< Int64
0 = Word64 -> Double
castWord64ToDouble (Word64 -> Double) -> Word64 -> Double
forall a b. (a -> b) -> a -> b
$ Word64
val Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
+ Word64
0x8000000000000000
    | Bool
otherwise = Word64 -> Double
castWord64ToDouble (Word64 -> Double) -> Word64 -> Double
forall a b. (a -> b) -> a -> b
$ Word64
0xffffFFFFffffFFFF Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
val

-- | Converts an unsigned Word value to a 32bits signed Int.
mdbx_int32_from_key :: Word32 -> Int32
mdbx_int32_from_key :: Word32 -> Int32
mdbx_int32_from_key Word32
val = Word32 -> Int32
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word32 -> Int32) -> Word32 -> Int32
forall a b. (a -> b) -> a -> b
$ Word32
val Word32 -> Word32 -> Word32
forall a. Num a => a -> a -> a
- Word32
0x80000000;

-- | Converts an unsigned Word value to a 64bits signed Int.
mdbx_int64_from_key :: Word64 -> Int64
mdbx_int64_from_key :: Word64 -> Int64
mdbx_int64_from_key Word64
val = Word64 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Word64 -> Int64) -> Word64 -> Int64
forall a b. (a -> b) -> a -> b
$ Word64
val Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
- Word64
0x8000000000000000;

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_env_create"
  mdbx_env_create'_ :: ((C2HSImp.Ptr (MdbxEnv)) -> (IO C2HSImp.CInt))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_env_set_geometry"
  mdbx_env_set_geometry'_ :: ((MdbxEnv) -> (C2HSImp.CLong -> (C2HSImp.CLong -> (C2HSImp.CLong -> (C2HSImp.CLong -> (C2HSImp.CLong -> (C2HSImp.CLong -> (IO C2HSImp.CInt))))))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_env_open"
  mdbx_env_open'_ :: ((MdbxEnv) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (C2HSImp.CInt -> (MdbxEnvMode -> (IO C2HSImp.CInt)))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_env_close"
  mdbx_env_close'_ :: ((MdbxEnv) -> (IO C2HSImp.CInt))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_txn_begin"
  mdbx_txn_begin'_ :: ((MdbxEnv) -> ((MdbxTxn) -> (C2HSImp.CInt -> ((C2HSImp.Ptr (MdbxTxn)) -> (IO C2HSImp.CInt)))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_txn_commit"
  mdbx_txn_commit'_ :: ((MdbxTxn) -> (IO C2HSImp.CInt))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_txn_abort"
  mdbx_txn_abort'_ :: ((MdbxTxn) -> (IO C2HSImp.CInt))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_txn_env"
  mdbx_txn_env'_ :: ((MdbxTxn) -> (IO (MdbxEnv)))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_dbi_open"
  mdbx_dbi_open'_ :: ((MdbxTxn) -> ((C2HSImp.Ptr C2HSImp.CChar) -> (C2HSImp.CInt -> ((C2HSImp.Ptr MdbxDbi) -> (IO C2HSImp.CInt)))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_dbi_close"
  mdbx_dbi_close'_ :: ((MdbxEnv) -> (MdbxDbi -> (IO C2HSImp.CInt)))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_put"
  mdbx_put'_ :: ((MdbxTxn) -> (MdbxDbi -> ((MdbxValPtr) -> ((MdbxValPtr) -> (C2HSImp.CInt -> (IO C2HSImp.CInt))))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_get"
  mdbx_get'_ :: ((MdbxTxn) -> (MdbxDbi -> ((MdbxValPtr) -> ((MdbxValPtr) -> (IO C2HSImp.CInt)))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_del"
  mdbx_del'_ :: ((MdbxTxn) -> (MdbxDbi -> ((MdbxValPtr) -> ((MdbxValPtr) -> (IO C2HSImp.CInt)))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_cursor_open"
  mdbx_cursor_open'_ :: ((MdbxTxn) -> (MdbxDbi -> ((C2HSImp.Ptr (MdbxCursor)) -> (IO C2HSImp.CInt))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_cursor_close"
  mdbx_cursor_close'_ :: ((MdbxCursor) -> (IO ()))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_cursor_del"
  mdbx_cursor_del'_ :: ((MdbxCursor) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_cursor_get"
  mdbx_cursor_get'_ :: ((MdbxCursor) -> ((MdbxValPtr) -> ((MdbxValPtr) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_cursor_put"
  mdbx_cursor_put'_ :: ((MdbxCursor) -> ((MdbxValPtr) -> ((MdbxValPtr) -> (C2HSImp.CInt -> (IO C2HSImp.CInt)))))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_cursor_count"
  mdbx_cursor_count'_ :: ((MdbxCursor) -> ((C2HSImp.Ptr CSize) -> (IO C2HSImp.CInt)))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_strerror"
  mdbx_strerror'_ :: (C2HSImp.CInt -> (IO (C2HSImp.Ptr C2HSImp.CChar)))

foreign import ccall unsafe "Mdbx/FFI.chs.h mdbx_cmp"
  mdbx_cmp'_ :: ((MdbxTxn) -> (MdbxDbi -> ((MdbxValPtr) -> ((MdbxValPtr) -> (IO C2HSImp.CInt)))))

foreign import ccall safe "Mdbx/FFI.chs.h mdbx_key_from_float"
  mdbx_key_from_float'_ :: (C2HSImp.CFloat -> (IO C2HSImp.CUInt))

foreign import ccall safe "Mdbx/FFI.chs.h mdbx_key_from_double"
  mdbx_key_from_double'_ :: (C2HSImp.CDouble -> (IO C2HSImp.CULong))

foreign import ccall safe "Mdbx/FFI.chs.h mdbx_key_from_int32"
  mdbx_key_from_int32'_ :: (C2HSImp.CInt -> (IO C2HSImp.CUInt))

foreign import ccall safe "Mdbx/FFI.chs.h mdbx_key_from_int64"
  mdbx_key_from_int64'_ :: (C2HSImp.CLong -> (IO C2HSImp.CULong))