{-# 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