module Data.Persistent.IDynamic where
import Data.Typeable
import Unsafe.Coerce
import System.IO.Unsafe
import Data.TCache
import Data.TCache.Defs
import Data.Char (showLitChar)
import Data.ByteString.Lazy.Char8 as B
import Data.Word
import Numeric (showHex, readHex)
import Control.Exception(handle, SomeException, ErrorCall)
import Control.Monad(replicateM)
import Data.Word
import Control.Concurrent.MVar
import Data.IORef
import Data.Map as M(empty)
import Data.RefSerialize
data IDynamic = IDyn (IORef IDynType) deriving Typeable
data IDynType= forall a w r.(Typeable a, Serialize a)
=> DRight !a
| DLeft !(ByteString ,(Context, ByteString))
deriving Typeable
newtype Save= Save ByteString deriving Typeable
tosave d@(IDyn r)= unsafePerformIO $ do
mr<- readIORef r
case mr of
DRight _ -> return d
DLeft (s,_) -> writeIORef r (DRight $ Save s) >> return d
instance Serialize Save where
showp (Save s)= insertString s
readp = error "readp not impremented for Save"
errorfied str str2= error $ str ++ ": IDynamic object not reified: "++ str2
dynPrefix= "Dyn"
dynPrefixSp= append (pack dynPrefix) " "
notreified = pack $ dynPrefix ++" 0"
instance Serialize IDynamic where
showp (IDyn t)=
case unsafePerformIO $ readIORef t of
DRight x -> do
c <- getWContext
showpx <- rshowps x
showp $ unpack showpx
DLeft (showpx,_) ->
insertString $ encode showpx
where
encode = pack . show . unpack
readp = lexeme (do
s <- rreadp :: STR String
c <- getRContext
return . IDyn . unsafePerformIO . newIORef $ DLeft ( pack s, c))
<?> "IDynamic"
instance Show IDynamic where
show (IDyn r) =
let t= unsafePerformIO $ readIORef r
in case t of
DRight x -> "IDyn " ++ ( unpack . runW $ showp x)
DLeft (s, _) -> "IDyns \"" ++ unpack s ++ "\""
toIDyn x= IDyn . unsafePerformIO . newIORef $ DRight x
serializedEqual (IDyn r) str= unsafePerformIO $ do
t <- readIORef r
case t of
DRight x -> return $ runW (showp x) == str
DLeft (str', _) -> return $ str== str'
fromIDyn :: (Typeable a , Serialize a)=> IDynamic -> a
fromIDyn x= case safeFromIDyn x of
Left s -> error s
Right v -> v
safeFromIDyn :: (Typeable a, Serialize a) => IDynamic -> Either String a
safeFromIDyn (d@(IDyn r))= final where
final= unsafePerformIO $ do
t <- readIORef r
case t of
DRight x -> return $ case cast x of
Nothing -> Left $ "fromIDyn: unable to extract from "
++ show d ++ " something of type: "
++ (show . typeOf $ fromRight final)
Just x -> Right x
where
fromRight (Right x)= x
DLeft (str, c) ->
handle (\(e :: SomeException) -> return $ Left (show e)) $
do
let v= runRC c rreadp str
writeIORef r $! DRight v
return $! Right v
reifyM :: (Typeable a,Serialize a) => IDynamic -> a -> IO a
reifyM dyn v = do
let v'= fromIDyn dyn
return $ v' `seq` v'