module Data.HMemDb.Bin
(
Bin(Bin, binGet, binPut),
Proxy(Proxy, unProxy),
TableGetData(TableGetData),
TableRefs(TRNil, TRPair, TRProxy, TRVar),
binUnit, binProxy, binCRef, binPair
) where
import Control.Applicative (liftA2, (<$>))
import Control.Compose ((:.))
import Control.Concurrent.STM (TVar)
import Data.Binary (Binary(get, put), Get, Put)
import Data.Map (Map)
import Data.HMemDb.MapTVar (MS)
import Data.HMemDb.References (CRef, cRefIndex, readCRef)
import Data.HMemDb.Utils (oBind, pureO)
data Proxy a = Proxy {unProxy :: a}
data TableGetData a where
TableGetData :: (r -> MS a) -> TVar (Map Integer (TVar (Maybe r))) -> TableGetData a
data TableRefs r where
TRNil :: TableRefs ()
TRProxy :: TableRefs (Proxy r)
TRVar :: TableGetData a -> TableRefs (CRef a)
TRPair :: TableRefs r1 -> TableRefs r2 -> TableRefs (r1, r2)
data Bin r =
Bin
{
binPut :: r -> Put,
binGet :: TableRefs r -> (Get :. MS) r
}
binUnit :: Bin ()
binUnit = Bin {binPut = put, binGet = \TRNil -> pureO $ return ()}
binProxy :: Binary r => Bin (Proxy r)
binProxy = Bin {binPut = put . unProxy, binGet = \TRProxy -> pureO $ Proxy <$> get}
tableVarBinGet :: TableRefs (CRef a) -> Integer -> MS (CRef a)
tableVarBinGet (TRVar (TableGetData to cnt)) n = readCRef to cnt n
binCRef :: Bin (CRef a)
binCRef =
Bin
{
binPut = put . cRefIndex,
binGet = \tref -> pureO get `oBind` tableVarBinGet tref
}
binPair :: Bin r1 -> Bin r2 -> Bin (r1, r2)
binPair b1 b2 =
Bin
{
binPut = \ ~(r1, r2) -> binPut b1 r1 >> binPut b2 r2,
binGet = \(TRPair tr1 tr2) -> liftA2 (,) (binGet b1 tr1) (binGet b2 tr2)
}