module Control.Distributed.Process.Serializable
( Serializable
, encodeFingerprint
, decodeFingerprint
, fingerprint
, sizeOfFingerprint
, Fingerprint
, showFingerprint
, SerializableDict(SerializableDict)
, TypeableDict(TypeableDict)
) where
import Data.Binary (Binary)
#if MIN_VERSION_base(4,7,0)
import Data.Typeable (Typeable)
import Data.Typeable.Internal (TypeRep(TypeRep), typeOf)
#else
import Data.Typeable (Typeable(..))
import Data.Typeable.Internal (TypeRep(TypeRep))
#endif
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)
data TypeableDict a where
TypeableDict :: Typeable a => TypeableDict 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
#if MIN_VERSION_base(4,8,0)
fingerprint a = let TypeRep fp _ _ _ = typeOf a in fp
#else
fingerprint a = let TypeRep fp _ _ = typeOf a in fp
#endif
showFingerprint :: Fingerprint -> ShowS
showFingerprint (Fingerprint hi lo) =
showString "(" . showHex hi . showString "," . showHex lo . showString ")"