mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-10-23 16:48:07 +02:00
forgot to add file
This commit is contained in:
259
haskell/src/Data/MessagePack/Parser.hs
Normal file
259
haskell/src/Data/MessagePack/Parser.hs
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
{-# Language FlexibleInstances #-}
|
||||||
|
{-# Language IncoherentInstances #-}
|
||||||
|
{-# Language OverlappingInstances #-}
|
||||||
|
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
-- |
|
||||||
|
-- Module : Data.MessagePack.Parser
|
||||||
|
-- Copyright : (c) Hideyuki Tanaka, 2009-2010
|
||||||
|
-- License : BSD3
|
||||||
|
--
|
||||||
|
-- Maintainer: tanaka.hideyuki@gmail.com
|
||||||
|
-- Stability : experimental
|
||||||
|
-- Portability: portable
|
||||||
|
--
|
||||||
|
-- MessagePack Deserializer using @Data.Attoparsec@
|
||||||
|
--
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
module Data.MessagePack.Parser(
|
||||||
|
-- * MessagePack deserializer
|
||||||
|
ObjectGet(..),
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
import qualified Data.Attoparsec as A
|
||||||
|
import Data.Binary.Get
|
||||||
|
import Data.Binary.IEEE754
|
||||||
|
import Data.Bits
|
||||||
|
import qualified Data.ByteString as B
|
||||||
|
import qualified Data.ByteString.Lazy as L
|
||||||
|
import Data.Int
|
||||||
|
import qualified Data.Vector as V
|
||||||
|
import Data.Word
|
||||||
|
import Text.Printf
|
||||||
|
|
||||||
|
import Data.MessagePack.Object
|
||||||
|
|
||||||
|
-- | Deserializable class
|
||||||
|
class ObjectGet a where
|
||||||
|
-- | Deserialize a value
|
||||||
|
get :: A.Parser a
|
||||||
|
|
||||||
|
instance ObjectGet Int where
|
||||||
|
get = parseInt
|
||||||
|
|
||||||
|
instance ObjectGet () where
|
||||||
|
get = parseNil
|
||||||
|
|
||||||
|
instance ObjectGet Bool where
|
||||||
|
get = parseBool
|
||||||
|
|
||||||
|
instance ObjectGet Double where
|
||||||
|
get = parseDouble
|
||||||
|
|
||||||
|
instance ObjectGet B.ByteString where
|
||||||
|
get = parseRAW
|
||||||
|
|
||||||
|
instance ObjectGet a => ObjectGet [a] where
|
||||||
|
get = parseArray
|
||||||
|
|
||||||
|
instance ObjectGet a => ObjectGet (V.Vector a) where
|
||||||
|
get = parseArrayVector
|
||||||
|
|
||||||
|
instance (ObjectGet k, ObjectGet v) => ObjectGet [(k, v)] where
|
||||||
|
get = parseMap
|
||||||
|
|
||||||
|
instance (ObjectGet k, ObjectGet v) => ObjectGet (V.Vector (k, v)) where
|
||||||
|
get = parseMapVector
|
||||||
|
|
||||||
|
instance ObjectGet Object where
|
||||||
|
get = parseObject
|
||||||
|
|
||||||
|
parseInt :: A.Parser Int
|
||||||
|
parseInt = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
_ | c .&. 0x80 == 0x00 ->
|
||||||
|
return $ fromIntegral c
|
||||||
|
_ | c .&. 0xE0 == 0xE0 ->
|
||||||
|
return $ fromIntegral (fromIntegral c :: Int8)
|
||||||
|
0xCC ->
|
||||||
|
return . fromIntegral =<< A.anyWord8
|
||||||
|
0xCD ->
|
||||||
|
return . fromIntegral =<< parseUint16
|
||||||
|
0xCE ->
|
||||||
|
return . fromIntegral =<< parseUint32
|
||||||
|
0xCF ->
|
||||||
|
return . fromIntegral =<< parseUint64
|
||||||
|
0xD0 ->
|
||||||
|
return . fromIntegral =<< parseInt8
|
||||||
|
0xD1 ->
|
||||||
|
return . fromIntegral =<< parseInt16
|
||||||
|
0xD2 ->
|
||||||
|
return . fromIntegral =<< parseInt32
|
||||||
|
0xD3 ->
|
||||||
|
return . fromIntegral =<< parseInt64
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid integer tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseNil :: A.Parser ()
|
||||||
|
parseNil = do
|
||||||
|
_ <- A.word8 0xC0
|
||||||
|
return ()
|
||||||
|
|
||||||
|
parseBool :: A.Parser Bool
|
||||||
|
parseBool = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
0xC3 ->
|
||||||
|
return True
|
||||||
|
0xC2 ->
|
||||||
|
return False
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid bool tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseDouble :: A.Parser Double
|
||||||
|
parseDouble = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
0xCA ->
|
||||||
|
return . realToFrac . runGet getFloat32be . toLBS =<< A.take 4
|
||||||
|
0xCB ->
|
||||||
|
return . runGet getFloat64be . toLBS =<< A.take 8
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid double tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseRAW :: A.Parser B.ByteString
|
||||||
|
parseRAW = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
_ | c .&. 0xE0 == 0xA0 ->
|
||||||
|
A.take . fromIntegral $ c .&. 0x1F
|
||||||
|
0xDA ->
|
||||||
|
A.take . fromIntegral =<< parseUint16
|
||||||
|
0xDB ->
|
||||||
|
A.take . fromIntegral =<< parseUint32
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid raw tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseArray :: ObjectGet a => A.Parser [a]
|
||||||
|
parseArray = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
_ | c .&. 0xF0 == 0x90 ->
|
||||||
|
flip replicateM get . fromIntegral $ c .&. 0x0F
|
||||||
|
0xDC ->
|
||||||
|
flip replicateM get . fromIntegral =<< parseUint16
|
||||||
|
0xDD ->
|
||||||
|
flip replicateM get . fromIntegral =<< parseUint32
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid array tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseArrayVector :: ObjectGet a => A.Parser (V.Vector a)
|
||||||
|
parseArrayVector = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
_ | c .&. 0xF0 == 0x90 ->
|
||||||
|
flip V.replicateM get . fromIntegral $ c .&. 0x0F
|
||||||
|
0xDC ->
|
||||||
|
flip V.replicateM get . fromIntegral =<< parseUint16
|
||||||
|
0xDD ->
|
||||||
|
flip V.replicateM get . fromIntegral =<< parseUint32
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid array tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseMap :: (ObjectGet k, ObjectGet v) => A.Parser [(k, v)]
|
||||||
|
parseMap = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
_ | c .&. 0xF0 == 0x80 ->
|
||||||
|
flip replicateM parsePair . fromIntegral $ c .&. 0x0F
|
||||||
|
0xDE ->
|
||||||
|
flip replicateM parsePair . fromIntegral =<< parseUint16
|
||||||
|
0xDF ->
|
||||||
|
flip replicateM parsePair . fromIntegral =<< parseUint32
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid map tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseMapVector :: (ObjectGet k, ObjectGet v) => A.Parser (V.Vector (k, v))
|
||||||
|
parseMapVector = do
|
||||||
|
c <- A.anyWord8
|
||||||
|
case c of
|
||||||
|
_ | c .&. 0xF0 == 0x80 ->
|
||||||
|
flip V.replicateM parsePair . fromIntegral $ c .&. 0x0F
|
||||||
|
0xDE ->
|
||||||
|
flip V.replicateM parsePair . fromIntegral =<< parseUint16
|
||||||
|
0xDF ->
|
||||||
|
flip V.replicateM parsePair . fromIntegral =<< parseUint32
|
||||||
|
_ ->
|
||||||
|
fail $ printf "invlid map tag: 0x%02X" c
|
||||||
|
|
||||||
|
parseObject :: A.Parser Object
|
||||||
|
parseObject =
|
||||||
|
A.choice
|
||||||
|
[ liftM ObjectInteger parseInt
|
||||||
|
, liftM (const ObjectNil) parseNil
|
||||||
|
, liftM ObjectBool parseBool
|
||||||
|
, liftM ObjectDouble parseDouble
|
||||||
|
, liftM ObjectRAW parseRAW
|
||||||
|
, liftM ObjectArray parseArray
|
||||||
|
, liftM ObjectMap parseMap
|
||||||
|
]
|
||||||
|
|
||||||
|
parsePair :: (ObjectGet k, ObjectGet v) => A.Parser (k, v)
|
||||||
|
parsePair = do
|
||||||
|
a <- get
|
||||||
|
b <- get
|
||||||
|
return (a, b)
|
||||||
|
|
||||||
|
parseUint16 :: A.Parser Word16
|
||||||
|
parseUint16 = do
|
||||||
|
b0 <- A.anyWord8
|
||||||
|
b1 <- A.anyWord8
|
||||||
|
return $ (fromIntegral b0 `shiftL` 8) .|. fromIntegral b1
|
||||||
|
|
||||||
|
parseUint32 :: A.Parser Word32
|
||||||
|
parseUint32 = do
|
||||||
|
b0 <- A.anyWord8
|
||||||
|
b1 <- A.anyWord8
|
||||||
|
b2 <- A.anyWord8
|
||||||
|
b3 <- A.anyWord8
|
||||||
|
return $ (fromIntegral b0 `shiftL` 24) .|.
|
||||||
|
(fromIntegral b1 `shiftL` 16) .|.
|
||||||
|
(fromIntegral b2 `shiftL` 8) .|.
|
||||||
|
fromIntegral b3
|
||||||
|
|
||||||
|
parseUint64 :: A.Parser Word64
|
||||||
|
parseUint64 = do
|
||||||
|
b0 <- A.anyWord8
|
||||||
|
b1 <- A.anyWord8
|
||||||
|
b2 <- A.anyWord8
|
||||||
|
b3 <- A.anyWord8
|
||||||
|
b4 <- A.anyWord8
|
||||||
|
b5 <- A.anyWord8
|
||||||
|
b6 <- A.anyWord8
|
||||||
|
b7 <- A.anyWord8
|
||||||
|
return $ (fromIntegral b0 `shiftL` 56) .|.
|
||||||
|
(fromIntegral b1 `shiftL` 48) .|.
|
||||||
|
(fromIntegral b2 `shiftL` 40) .|.
|
||||||
|
(fromIntegral b3 `shiftL` 32) .|.
|
||||||
|
(fromIntegral b4 `shiftL` 24) .|.
|
||||||
|
(fromIntegral b5 `shiftL` 16) .|.
|
||||||
|
(fromIntegral b6 `shiftL` 8) .|.
|
||||||
|
fromIntegral b7
|
||||||
|
|
||||||
|
parseInt8 :: A.Parser Int8
|
||||||
|
parseInt8 = return . fromIntegral =<< A.anyWord8
|
||||||
|
|
||||||
|
parseInt16 :: A.Parser Int16
|
||||||
|
parseInt16 = return . fromIntegral =<< parseUint16
|
||||||
|
|
||||||
|
parseInt32 :: A.Parser Int32
|
||||||
|
parseInt32 = return . fromIntegral =<< parseUint32
|
||||||
|
|
||||||
|
parseInt64 :: A.Parser Int64
|
||||||
|
parseInt64 = return . fromIntegral =<< parseUint64
|
||||||
|
|
||||||
|
toLBS :: B.ByteString -> L.ByteString
|
||||||
|
toLBS bs = L.fromChunks [bs]
|
Reference in New Issue
Block a user