mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-21 07:45:02 +02:00
157 lines
4.1 KiB
Haskell
157 lines
4.1 KiB
Haskell
--------------------------------------------------------------------
|
|
-- |
|
|
-- Module : Data.MessagePack.Monad
|
|
-- Copyright : (c) Hideyuki Tanaka, 2009
|
|
-- License : BSD3
|
|
--
|
|
-- Maintainer: tanaka.hideyuki@gmail.com
|
|
-- Stability : experimental
|
|
-- Portability: portable
|
|
--
|
|
-- Monadic Stream Serializers and Deserializers
|
|
--
|
|
--------------------------------------------------------------------
|
|
|
|
module Data.MessagePack.Monad(
|
|
-- * Classes
|
|
MonadPacker(..),
|
|
MonadUnpacker(..),
|
|
|
|
-- * Packer and Unpacker type
|
|
PackerT(..),
|
|
UnpackerT(..),
|
|
|
|
-- * Packers
|
|
packToString,
|
|
packToHandle,
|
|
packToFile,
|
|
|
|
-- * Unpackers
|
|
unpackFrom,
|
|
unpackFromString,
|
|
unpackFromHandle,
|
|
unpackFromFile,
|
|
) where
|
|
|
|
import Control.Monad
|
|
import Control.Monad.Trans
|
|
import Data.ByteString (ByteString)
|
|
import qualified Data.ByteString as BS
|
|
import System.IO
|
|
|
|
import Data.MessagePack.Base hiding (Unpacker)
|
|
import qualified Data.MessagePack.Base as Base
|
|
import Data.MessagePack.Class
|
|
import Data.MessagePack.Feed
|
|
|
|
class Monad m => MonadPacker m where
|
|
-- | Serialize a object
|
|
put :: OBJECT a => a -> m ()
|
|
|
|
class Monad m => MonadUnpacker m where
|
|
-- | Deserialize a object
|
|
get :: OBJECT a => m a
|
|
|
|
-- | Serializer Type
|
|
newtype PackerT m r = PackerT { runPackerT :: Base.Packer -> m r }
|
|
|
|
instance Monad m => Monad (PackerT m) where
|
|
a >>= b =
|
|
PackerT $ \pc -> do
|
|
r <- runPackerT a pc
|
|
runPackerT (b r) pc
|
|
|
|
return r =
|
|
PackerT $ \_ -> return r
|
|
|
|
instance MonadTrans PackerT where
|
|
lift m = PackerT $ \_ -> m
|
|
|
|
instance MonadIO m => MonadIO (PackerT m) where
|
|
liftIO = lift . liftIO
|
|
|
|
instance MonadIO m => MonadPacker (PackerT m) where
|
|
put v = PackerT $ \pc -> liftIO $ do
|
|
pack pc v
|
|
|
|
-- | Execute given serializer and returns byte sequence.
|
|
packToString :: MonadIO m => PackerT m r -> m ByteString
|
|
packToString m = do
|
|
sb <- liftIO $ newSimpleBuffer
|
|
pc <- liftIO $ newPacker sb
|
|
_ <- runPackerT m pc
|
|
liftIO $ simpleBufferData sb
|
|
|
|
-- | Execute given serializer and write byte sequence to Handle.
|
|
packToHandle :: MonadIO m => Handle -> PackerT m r -> m ()
|
|
packToHandle h m = do
|
|
sb <- packToString m
|
|
liftIO $ BS.hPut h sb
|
|
liftIO $ hFlush h
|
|
|
|
-- | Execute given serializer and write byte sequence to file.
|
|
packToFile :: MonadIO m => FilePath -> PackerT m r -> m ()
|
|
packToFile p m = do
|
|
sb <- packToString m
|
|
liftIO $ BS.writeFile p sb
|
|
|
|
-- | Deserializer type
|
|
newtype UnpackerT m r = UnpackerT { runUnpackerT :: Base.Unpacker -> Feeder -> m r }
|
|
|
|
instance Monad m => Monad (UnpackerT m) where
|
|
a >>= b =
|
|
UnpackerT $ \up feed -> do
|
|
r <- runUnpackerT a up feed
|
|
runUnpackerT (b r) up feed
|
|
|
|
return r =
|
|
UnpackerT $ \_ _ -> return r
|
|
|
|
instance MonadTrans UnpackerT where
|
|
lift m = UnpackerT $ \_ _ -> m
|
|
|
|
instance MonadIO m => MonadIO (UnpackerT m) where
|
|
liftIO = lift . liftIO
|
|
|
|
instance MonadIO m => MonadUnpacker (UnpackerT m) where
|
|
get = UnpackerT $ \up feed -> liftIO $ do
|
|
executeOne up feed
|
|
obj <- unpackerData up
|
|
freeZone =<< unpackerReleaseZone up
|
|
unpackerReset up
|
|
let Right r = fromObject obj
|
|
return r
|
|
|
|
where
|
|
executeOne up feed = do
|
|
resp <- unpackerExecute up
|
|
guard $ resp>=0
|
|
when (resp==0) $ do
|
|
Just bs <- feed
|
|
unpackerFeed up bs
|
|
executeOne up feed
|
|
|
|
-- | Execute deserializer using given feeder.
|
|
unpackFrom :: MonadIO m => Feeder -> UnpackerT m r -> m r
|
|
unpackFrom f m = do
|
|
up <- liftIO $ newUnpacker defaultInitialBufferSize
|
|
runUnpackerT m up f
|
|
|
|
-- | Execute deserializer using given handle.
|
|
unpackFromHandle :: MonadIO m => Handle -> UnpackerT m r -> m r
|
|
unpackFromHandle h m =
|
|
flip unpackFrom m =<< liftIO (feederFromHandle h)
|
|
|
|
-- | Execute deserializer using given file content.
|
|
unpackFromFile :: MonadIO m => FilePath -> UnpackerT m r -> m r
|
|
unpackFromFile p m = do
|
|
h <- liftIO $ openFile p ReadMode
|
|
r <- flip unpackFrom m =<< liftIO (feederFromHandle h)
|
|
liftIO $ hClose h
|
|
return r
|
|
|
|
-- | Execute deserializer from given byte sequence.
|
|
unpackFromString :: MonadIO m => ByteString -> UnpackerT m r -> m r
|
|
unpackFromString bs m = do
|
|
flip unpackFrom m =<< liftIO (feederFromString bs)
|