{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE RankNTypes #-}
module Lmdb.Types where
import Database.LMDB.Raw
import Foreign.C.Types (CSize(..),CInt)
import Foreign.Ptr (Ptr,FunPtr)
import Data.Word
import Data.Primitive.ByteArray (ByteArray)
import qualified Data.Vector.Unboxed as UVector
import qualified Data.Vector.Primitive as PVector
-- | We only use the promoted version of this data type.
data Mode = ReadOnly | ReadWrite
class ModeBool (x :: Mode) where
modeIsReadOnly :: proxy x -> Bool
instance ModeBool 'ReadOnly where
modeIsReadOnly _ = True
instance ModeBool 'ReadWrite where
modeIsReadOnly _ = False
newtype Environment (x :: Mode) = Environment
{ getEnvironment :: MDB_env
}
newtype Transaction (t :: Mode) = Transaction
{ getTransaction :: MDB_txn
}
data Cursor (t :: Mode) k v = Cursor
{ cursorRef :: !CursorByFfi
, cursorDatabaseSettings :: !(DatabaseSettings k v)
}
data MultiCursor (t :: Mode) k v = MultiCursor
{ multiCursorRef :: !CursorByFfi
, multiCursorDatabaseSettings :: !(MultiDatabaseSettings k v)
}
data KeyValue k v = KeyValue
{ keyValueKey :: !k
, keyValueValue :: !v
}
data CursorByFfi
= CursorSafe !MDB_cursor
| CursorUnsafe !MDB_cursor'
data DbiByFfi
= DbiSafe !MDB_dbi
| DbiUnsafe !MDB_dbi'
data Database k v = Database
{ databaseRef :: !DbiByFfi
, databaseTheSettings :: !(DatabaseSettings k v)
}
data MultiDatabase k v = MultiDatabase
{ multiDatabaseRef :: DbiByFfi
, multiDatabaseTheSettings :: !(MultiDatabaseSettings k v)
}
data DatabaseSettings k v = forall ks vs. DatabaseSettings
{ databaseSettingsSort :: !(Sort ks k) -- ^ Sorting
, databaseSettingsEncodeKey :: !(Encoding ks k)
, databaseSettingsDecodeKey :: !(Decoding k)
, databaseSettingsEncodeValue :: !(Encoding vs v)
, databaseSettingsDecodeValue :: !(Decoding v)
}
data MultiDatabaseSettings k v = forall ks vs. MultiDatabaseSettings
{ multiDatabaseSettingsSortKey :: Sort ks k
, multiDatabaseSettingsSortValue :: Sort vs v
, multiDatabaseSettingsEncodeKey :: !(Encoding ks k)
, multiDatabaseSettingsDecodeKey :: !(Decoding k)
, multiDatabaseSettingsEncodeValue :: !(Encoding vs v)
, multiDatabaseSettingsDecodeValue :: !(Decoding v)
}
data Codec s a = Codec
{ codecEncode :: !(Encoding s a)
, codecDecode :: !(Decoding a)
-- , codecMultiEncode :: !(MultiEncoding s a)
-- , codecMultiDecode :: !(MultiDecoding s a)
}
newtype Decoding a = Decoding { getDecoding :: CSize -> Ptr Word8 -> IO a }
-- newtype Encoding a = Encoding { getEncoding :: a -> SizedPoke }
-- data SomeFixedSize (s :: Size) where
-- SomeFixedSizeFixed :: CSize -> SomeFixedSize 'Fixed
-- SomeFixedSizeMachineWord :: SomeFixedSize 'MachineWord
--
-- data MultiEncoding (s :: Size) a where
-- MultiEncodingNone :: MultiEncoding 'Variable a
-- MultiEncodingUnboxedVector :: SomeFixedSize s
-- -> (ByteArray -> Ptr Word8 -> IO ()) -- todo: remove this entirely
-- -> MultiEncoding s a
-- -- MultiEncodingIndexedTraversal :: CSize
-- -- -> (forall f b. ((Int -> a -> IO b) -> f a -> IO ()) -> f a -> Ptr Word8 -> IO ())
-- -- -> MultiEncoding 'Fixed a
--
-- data MultiDecoding (s :: Size) a where
-- MultiDecodingNone :: MultiDecoding 'Variable a
-- MultiDecodingUnboxedVector :: SomeFixedSize s
-- -> (Int -> Ptr Word8 -> IO ByteArray) -- todo: remove this entirely
-- -> (forall m b. Monad m => (a -> m b) -> ByteArray -> m ()) -- maybe get rid of this too...
-- -> MultiDecoding s a
data Encoding (s :: Size) a where
EncodingVariable :: (a -> SizedPoke) -> Encoding 'Variable a
EncodingFixed :: CSize -> (a -> FixedPoke) -> Encoding 'Fixed a
EncodingMachineWord :: (a -> FixedPoke) -> Encoding 'MachineWord a
data SizedPoke = SizedPoke
{ sizedPokeSize :: {-# UNPACK #-} !CSize -- ^ size in bytes
, sizedPokePoke :: !(Ptr Word8 -> IO ())
}
newtype FixedPoke = FixedPoke { getFixedPoke :: Ptr Word8 -> IO () }
data Size
= Variable
| Fixed
| MachineWord
data NativeSort (s :: Size) where
NativeSortLexographic :: NativeSort 'Variable
NativeSortLexographicBackward :: NativeSort 'Variable
NativeSortInteger :: NativeSort 'MachineWord
data CustomSort a
= CustomSortSafe (a -> a -> Ordering)
| CustomSortUnsafe (FunPtr (Ptr MDB_val -> Ptr MDB_val -> IO CInt))
data Sort (s :: Size) a where
SortNative :: NativeSort s -> Sort s a
SortCustom :: CustomSort a -> Sort 'Variable a
data Movement k
= MovementNext
| MovementPrev
| MovementFirst
| MovementLast
| MovementAt !k
| MovementAtGte !k
| MovementCurrent
-- data SingMode (x :: Mode) where
-- SingReadOnly :: SingMode 'ReadOnly
-- SingReadWrite :: SingMode 'ReadWrite
-- class ImplicitMode (x :: Mode) where
-- implicitMode :: SingMode x
--
-- instance ImplicitMode 'ReadOnly where
-- implicitMode = SingReadOnly
--
-- instance ImplicitMode 'ReadWrite where
-- implicitMode = SingReadWrite
-- equivalent to logical implication
-- type family Implies (a :: Mode) (b :: Mode) :: Bool where
-- Implies 'ReadOnly 'ReadOnly = 'True
-- Implies 'ReadOnly 'ReadWrite = 'False
-- Implies 'ReadWrite 'ReadOnly = 'True
-- Implies 'ReadWrite 'ReadWrite = 'True
--
-- type SubMode a b = Implies a b ~ 'True