module Control.Distributed.Process.Serializable
( Serializable
, encodeFingerprint
, decodeFingerprint
, fingerprint
, sizeOfFingerprint
, Fingerprint
, showFingerprint
, SerializableDict(SerializableDict)
) where
import Data.Binary (Binary)
import Data.Typeable (Typeable(..))
import Data.Typeable.Internal (TypeRep(TypeRep))
import Numeric (showHex)
import Control.Exception (throw)
import GHC.Fingerprint.Type (Fingerprint(..))
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Internal as BSI ( unsafeCreate
, inlinePerformIO
, toForeignPtr
)
import Foreign.Storable (pokeByteOff, peekByteOff, sizeOf)
import Foreign.ForeignPtr (withForeignPtr)
data SerializableDict a where
SerializableDict :: Serializable a => SerializableDict a
deriving (Typeable)
class (Binary a, Typeable a) => Serializable a
instance (Binary a, Typeable a) => Serializable a
encodeFingerprint :: Fingerprint -> ByteString
encodeFingerprint fp =
BSI.unsafeCreate sizeOfFingerprint $ \p -> pokeByteOff p 0 fp
decodeFingerprint :: ByteString -> Fingerprint
decodeFingerprint bs
| BS.length bs /= sizeOfFingerprint =
throw $ userError "decodeFingerprint: Invalid length"
| otherwise = BSI.inlinePerformIO $ do
let (fp, offset, _) = BSI.toForeignPtr bs
withForeignPtr fp $ \p -> peekByteOff p offset
sizeOfFingerprint :: Int
sizeOfFingerprint = sizeOf (undefined :: Fingerprint)
fingerprint :: Typeable a => a -> Fingerprint
fingerprint a = let TypeRep fp _ _ = typeOf a in fp
showFingerprint :: Fingerprint -> ShowS
showFingerprint (Fingerprint hi lo) =
showString "(" . showHex hi . showString "," . showHex lo . showString ")"