bytes 0.11.5 → 0.12
raw patch · 2 files changed
+209/−35 lines, 2 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Data.Bytes.Serial: class GSerialEndian f where gserializeBE = gserialize gdeserializeBE = gdeserialize gserializeLE = gserialize gdeserializeLE = gdeserialize
+ Data.Bytes.Serial: class SerialEndian a where serializeBE = gserializeBE . from deserializeBE = liftM to gdeserializeBE serializeLE = gserializeLE . from deserializeLE = liftM to gdeserializeLE serializeHost = serializeLE deserializeHost = deserializeLE
+ Data.Bytes.Serial: deserializeBE :: (SerialEndian a, MonadGet m) => m a
+ Data.Bytes.Serial: deserializeHost :: (SerialEndian a, MonadGet m) => m a
+ Data.Bytes.Serial: deserializeLE :: (SerialEndian a, MonadGet m) => m a
+ Data.Bytes.Serial: gdeserializeBE :: (GSerialEndian f, MonadGet m) => m (f a)
+ Data.Bytes.Serial: gdeserializeLE :: (GSerialEndian f, MonadGet m) => m (f a)
+ Data.Bytes.Serial: gserializeBE :: (GSerialEndian f, MonadPut m) => f a -> m ()
+ Data.Bytes.Serial: gserializeLE :: (GSerialEndian f, MonadPut m) => f a -> m ()
+ Data.Bytes.Serial: instance SerialEndian Char
+ Data.Bytes.Serial: instance SerialEndian Double
+ Data.Bytes.Serial: instance SerialEndian Float
+ Data.Bytes.Serial: instance SerialEndian Int16
+ Data.Bytes.Serial: instance SerialEndian Int32
+ Data.Bytes.Serial: instance SerialEndian Int64
+ Data.Bytes.Serial: instance SerialEndian Word16
+ Data.Bytes.Serial: instance SerialEndian Word32
+ Data.Bytes.Serial: instance SerialEndian Word64
+ Data.Bytes.Serial: instance SerialEndian a => GSerialEndian (K1 i a)
+ Data.Bytes.Serial: serializeBE :: (SerialEndian a, MonadPut m) => a -> m ()
+ Data.Bytes.Serial: serializeHost :: (SerialEndian a, MonadPut m) => a -> m ()
+ Data.Bytes.Serial: serializeLE :: (SerialEndian a, MonadPut m) => a -> m ()
Files
- bytes.cabal +1/−1
- src/Data/Bytes/Serial.hs +208/−34
bytes.cabal view
@@ -1,6 +1,6 @@ name: bytes category: Data, Serialization-version: 0.11.5+version: 0.12 license: BSD3 cabal-version: >= 1.8 license-file: LICENSE
src/Data/Bytes/Serial.hs view
@@ -18,20 +18,31 @@ -- Stability : experimental -- Portability: non-portable ----- This module generalizes the @binary@ 'B.PutM' and @cereal@ 'S.PutM'--- monads in an ad hoc fashion to permit code to be written that is--- compatible across them.------ Moreover, this class permits code to be written to be portable over--- various monad transformers applied to these as base monads.+-- This module contains two main classes, each providing methods to+-- serialize and deserialize types. 'Serial' is the primary class,+-- to be used for the canonical way to serialize a specific+-- type. 'SerialEndian' is used to provide endian-specific methods+-- for serializing a type. -------------------------------------------------------------------- module Data.Bytes.Serial- ( Serial(..)+ (+ -- * Serialization+ Serial(..)+ -- * Specifying endianness+ , SerialEndian(..)+ -- * Higher-order+ -- $higher+ , Serial1(..)+ , serialize1, deserialize1+ , Serial2(..)+ , serialize2, deserialize2+ -- * Storable+ , store, restore+ -- * Generics+ -- $generics , GSerial(..)- , Serial1(..), serialize1, deserialize1+ , GSerialEndian(..) , GSerial1(..)- , Serial2(..), serialize2, deserialize2- , store, restore ) where import Control.Monad@@ -59,10 +70,129 @@ import GHC.Generics import System.IO.Unsafe +foreign import ccall floatToWord32 :: Float -> Word32+foreign import ccall word32ToFloat :: Word32 -> Float+foreign import ccall doubleToWord64 :: Double -> Word64+foreign import ccall word64ToDouble :: Word64 -> Double+ ------------------------------------------------------------------------------+-- Endianness-Dependant Serialization+------------------------------------------------------------------------------++{-| Methods to serialize and deserialize type 'a' to a big and little endian+binary representations. Methods suffixed with "host" are automatically defined+to use equal the methods corresponding to the current machine's native+endianness, but they can be overridden.+-}+class SerialEndian a where+ serializeBE :: MonadPut m => a -> m ()+#ifndef HLINT+ default serializeBE :: (MonadPut m, GSerialEndian (Rep a), Generic a) => a -> m ()+ serializeBE = gserializeBE . from+#endif++ deserializeBE :: MonadGet m => m a+#ifndef HLINT+ default deserializeBE :: (MonadGet m, GSerialEndian (Rep a), Generic a) => m a+ deserializeBE = liftM to gdeserializeBE+#endif++ serializeLE :: MonadPut m => a -> m ()+#ifndef HLINT+ default serializeLE :: (MonadPut m, GSerialEndian (Rep a), Generic a) => a -> m ()+ serializeLE = gserializeLE . from+#endif++ deserializeLE :: MonadGet m => m a+#ifndef HLINT+ default deserializeLE :: (MonadGet m, GSerialEndian (Rep a), Generic a) => m a+ deserializeLE = liftM to gdeserializeLE+#endif++ serializeHost :: MonadPut m => a -> m ()+ deserializeHost :: MonadGet m => m a+#ifdef WORDS_BIGENDIAN+ serializeHost = serializeBE+ deserializeHost = deserializeBE+#else+ serializeHost = serializeLE+ deserializeHost = deserializeLE+#endif++instance SerialEndian Double where+ serializeBE = serializeBE . doubleToWord64+ deserializeBE = liftM word64ToDouble deserializeBE++ serializeLE = serializeLE . doubleToWord64+ deserializeLE = liftM word64ToDouble deserializeLE++instance SerialEndian Float where+ serializeBE = serializeBE . floatToWord32+ deserializeBE = liftM word32ToFloat deserializeBE++ serializeLE = serializeLE . floatToWord32+ deserializeLE = liftM word32ToFloat deserializeLE++instance SerialEndian Char where+ serializeBE = putWord32be . fromIntegral . fromEnum+ deserializeBE = liftM (toEnum . fromIntegral) getWord32be++ serializeLE = putWord32le . fromIntegral . fromEnum+ deserializeLE = liftM (toEnum . fromIntegral) getWord32le++instance SerialEndian Word64 where+ serializeBE = putWord64be+ deserializeBE = getWord64be++ serializeLE = putWord64le+ deserializeLE = getWord64le++instance SerialEndian Word32 where+ serializeBE = putWord32be+ deserializeBE = getWord32be++ serializeLE = putWord32le+ deserializeLE = getWord32le++instance SerialEndian Word16 where+ serializeBE = putWord16be+ deserializeBE = getWord16be++ serializeLE = putWord16le+ deserializeLE = getWord16le++instance SerialEndian Int64 where+ serializeBE = putWord64be . fromIntegral+ deserializeBE = liftM fromIntegral getWord64be++ serializeLE = putWord64le . fromIntegral+ deserializeLE = liftM fromIntegral getWord64le++instance SerialEndian Int32 where+ serializeBE = putWord32be . fromIntegral+ deserializeBE = liftM fromIntegral getWord32be++ serializeLE = putWord32le . fromIntegral+ deserializeLE = liftM fromIntegral getWord32le++instance SerialEndian Int16 where+ serializeBE = putWord16be . fromIntegral+ deserializeBE = liftM fromIntegral getWord16be++ serializeLE = putWord16le . fromIntegral+ deserializeLE = liftM fromIntegral getWord16le++------------------------------------------------------------------------------ -- Serialization ------------------------------------------------------------------------------ +{-| Methods to serialize and deserialize type 'a' to a binary representation++Instances provided here for fixed-with Integers and Words are big endian.+Instances for strict and lazy bytestrings store also the length of bytestring+big endian. Instances for Word and Int are host endian as they are+machine-specific types.+-} class Serial a where serialize :: MonadPut m => a -> m () #ifndef HLINT@@ -72,7 +202,7 @@ deserialize :: MonadGet m => m a #ifndef HLINT- default deserialize :: (MonadGet m, Generic a, GSerial (Rep a)) => m a+ default deserialize :: (MonadGet m, GSerial (Rep a), Generic a) => m a deserialize = liftM to gdeserialize #endif @@ -107,10 +237,12 @@ instance Serial Bool +-- | serialize any 'Storable' in a host-specific format. store :: (MonadPut m, Storable a) => a -> m () store a = putByteString bs where bs = unsafePerformIO $ create (sizeOf a) $ \ p -> poke (castPtr p) a +-- | deserialize any 'Storable' in a host-specific format. restore :: forall m a. (MonadGet m, Storable a) => m a restore = do let required = sizeOf (undefined :: a)@@ -118,58 +250,55 @@ unless (n >= required) $ fail "restore: Required more bytes" return $ unsafePerformIO $ withForeignPtr fp $ \p -> peekByteOff p o -foreign import ccall floatToWord32 :: Float -> Word32-foreign import ccall word32ToFloat :: Word32 -> Float-foreign import ccall doubleToWord64 :: Double -> Word64-foreign import ccall word64ToDouble :: Word64 -> Double- instance Serial Double where- serialize = serialize . doubleToWord64- deserialize = liftM word64ToDouble deserialize+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Float where- serialize = serialize . floatToWord32- deserialize = liftM word32ToFloat deserialize+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Char where- serialize = putWord32be . fromIntegral . fromEnum- deserialize = liftM (toEnum . fromIntegral) getWord32be+ serialize = serializeBE+ deserialize = deserializeBE + -- host endian instance Serial Word where serialize = putWordhost deserialize = getWordhost instance Serial Word64 where- serialize = putWord64be- deserialize = getWord64be+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Word32 where- serialize = putWord32be- deserialize = getWord32be+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Word16 where- serialize = putWord16be- deserialize = getWord16be+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Word8 where serialize = putWord8 deserialize = getWord8 + -- host endian instance Serial Int where serialize = putWordhost . fromIntegral deserialize = liftM fromIntegral getWordhost instance Serial Int64 where- serialize = putWord64be . fromIntegral- deserialize = liftM fromIntegral getWord64be+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Int32 where- serialize = putWord32be . fromIntegral- deserialize = liftM fromIntegral getWord32be+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Int16 where- serialize = putWord16be . fromIntegral- deserialize = liftM fromIntegral getWord16be+ serialize = serializeBE+ deserialize = deserializeBE instance Serial Int8 where serialize = putWord8 . fromIntegral@@ -203,6 +332,11 @@ -- Generic Serialization ------------------------------------------------------------------------------ +-- $generics+--+-- You probably will never need to care that these exist except they+-- provide us with default definitions for 'Serial' and 'SerialEndian'+ -- | Used internally to provide generic serialization class GSerial f where gserialize :: MonadPut m => f a -> m ()@@ -238,9 +372,49 @@ gserialize (K1 x) = serialize x gdeserialize = liftM K1 deserialize ++-- | Used internally to provide generic big-endian serialization+class GSerialEndian f where+ gserializeBE :: MonadPut m => f a -> m ()+#ifndef HLINT+ default gserializeBE :: (MonadPut m, GSerial f) => f a -> m ()+ gserializeBE = gserialize+#endif++ gdeserializeBE :: MonadGet m => m (f a)+#ifndef HLINT+ default gdeserializeBE :: (MonadGet m, GSerial f) => m (f a)+ gdeserializeBE = gdeserialize+#endif++ gserializeLE :: MonadPut m => f a -> m ()+#ifndef HLINT+ default gserializeLE :: (MonadPut m, GSerial f) => f a -> m ()+ gserializeLE = gserialize+#endif++ gdeserializeLE :: MonadGet m => m (f a)+#ifndef HLINT+ default gdeserializeLE :: (MonadGet m, GSerial f) => m (f a)+ gdeserializeLE = gdeserialize+#endif++-- only difference between GSerialEndian and GSerial+instance SerialEndian a => GSerialEndian (K1 i a) where+ gserializeBE (K1 x) = serializeBE x+ gdeserializeBE = liftM K1 deserializeBE++ gserializeLE (K1 x) = serializeLE x+ gdeserializeLE = liftM K1 deserializeLE+ ------------------------------------------------------------------------------ -- Higher-Rank Serialization ------------------------------------------------------------------------------++-- $higher+--+-- These classes provide us with the ability to serialize containers that need+-- polymorphic recursion. class Serial1 f where serializeWith :: MonadPut m => (a -> m ()) -> f a -> m ()