Merge branch 'master' of github.com:msgpack/msgpack

This commit is contained in:
tokuhirom 2010-09-27 08:32:10 +09:00
commit ec9659ff25
49 changed files with 2719 additions and 328 deletions

View File

@ -38,7 +38,7 @@ test -f ChangeLog || touch ChangeLog
test -f NEWS || touch NEWS
test -f README || cp -f README.md README
if ! ./preprocess; then
if test ! ./preprocess; then
exit 1
fi

View File

@ -28,9 +28,13 @@ class sbuffer : public msgpack_sbuffer {
public:
sbuffer(size_t initsz = MSGPACK_SBUFFER_INIT_SIZE)
{
base::data = (char*)::malloc(initsz);
if(!base::data) {
throw std::bad_alloc();
if(initsz == 0) {
base::data = NULL;
} else {
base::data = (char*)::malloc(initsz);
if(!base::data) {
throw std::bad_alloc();
}
}
base::size = 0;
@ -80,7 +84,7 @@ public:
private:
void expand_buffer(size_t len)
{
size_t nsize = (base::alloc) ?
size_t nsize = (base::alloc > 0) ?
base::alloc * 2 : MSGPACK_SBUFFER_INIT_SIZE;
while(nsize < base::size + len) { nsize *= 2; }

View File

@ -1,7 +1,7 @@
/*
* MessagePack for C memory pool implementation
*
* Copyright (C) 2008-2009 FURUHASHI Sadayuki
* Copyright (C) 2008-2010 FURUHASHI Sadayuki
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -73,6 +73,8 @@ static inline void* msgpack_zone_malloc_no_align(msgpack_zone* zone, size_t size
static inline bool msgpack_zone_push_finalizer(msgpack_zone* zone,
void (*func)(void* data), void* data);
static inline void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b);
bool msgpack_zone_is_empty(msgpack_zone* zone);
void msgpack_zone_clear(msgpack_zone* zone);
@ -129,6 +131,13 @@ bool msgpack_zone_push_finalizer(msgpack_zone* zone,
return true;
}
void msgpack_zone_swap(msgpack_zone* a, msgpack_zone* b)
{
msgpack_zone tmp = *a;
*a = *b;
*b = tmp;
}
#ifdef __cplusplus
}

View File

@ -1,7 +1,7 @@
//
// MessagePack for C++ memory pool
//
// Copyright (C) 2008-2009 FURUHASHI Sadayuki
// Copyright (C) 2008-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -43,6 +43,8 @@ public:
void clear();
void swap(zone& o);
<%0.upto(GENERATION_LIMIT) {|i|%>
template <typename T<%1.upto(i) {|j|%>, typename A<%=j%><%}%>>
T* allocate(<%=(1..i).map{|j|"A#{j} a#{j}"}.join(', ')%>);
@ -111,6 +113,11 @@ inline void zone::clear()
msgpack_zone_clear(this);
}
inline void zone::swap(zone& o)
{
msgpack_zone_swap(this, &o);
}
template <typename T>
void zone::object_destructor(void* obj)
{

View File

@ -1,5 +1,5 @@
Name: msgpack
Version: 0.3.1.1
Version: 0.4.0.1
Synopsis: A Haskell binding to MessagePack
Description:
A Haskell binding to MessagePack <http://msgpack.org/>
@ -15,6 +15,10 @@ Stability: Experimental
Cabal-Version: >= 1.6
Build-Type: Simple
Extra-source-files:
test/Test.hs
test/UserData.hs
Library
Build-depends: base >=4 && <5,
transformers >= 0.2.1 && < 0.2.2,
@ -25,17 +29,19 @@ Library
attoparsec >= 0.8.1 && < 0.8.2,
binary >= 0.5.0 && < 0.5.1,
data-binary-ieee754 >= 0.4 && < 0.5,
deepseq >= 1.1 && <1.2
deepseq >= 1.1 && <1.2,
template-haskell >= 2.4 && < 2.5
Ghc-options: -Wall
Hs-source-dirs: src
Exposed-modules:
Data.MessagePack
Data.MessagePack.Pack
Data.MessagePack.Unpack
Data.MessagePack.Object
Data.MessagePack.Put
Data.MessagePack.Parser
Data.MessagePack.Iteratee
Data.MessagePack.Derive
Source-repository head
Type: git

View File

@ -13,14 +13,11 @@
--------------------------------------------------------------------
module Data.MessagePack(
module Data.MessagePack.Pack,
module Data.MessagePack.Unpack,
module Data.MessagePack.Object,
module Data.MessagePack.Put,
module Data.MessagePack.Parser,
module Data.MessagePack.Iteratee,
-- * Simple functions of Pack and Unpack
pack,
unpack,
module Data.MessagePack.Derive,
-- * Pack functions
packToString,
@ -44,38 +41,18 @@ import qualified Data.Attoparsec as A
import Data.Binary.Put
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as L
import Data.Functor.Identity
import qualified Data.Iteratee as I
import System.IO
import Data.MessagePack.Pack
import Data.MessagePack.Unpack
import Data.MessagePack.Object
import Data.MessagePack.Put
import Data.MessagePack.Parser
import Data.MessagePack.Iteratee
import Data.MessagePack.Derive
bufferSize :: Int
bufferSize = 4 * 1024
class IsByteString s where
toBS :: s -> B.ByteString
instance IsByteString B.ByteString where
toBS = id
instance IsByteString L.ByteString where
toBS = B.concat . L.toChunks
-- | Pack Haskell data to MessagePack string.
pack :: ObjectPut a => a -> L.ByteString
pack = packToString . put
-- | Unpack MessagePack string to Haskell data.
unpack :: (ObjectGet a, IsByteString s) => s -> a
unpack bs =
runIdentity $ I.run $ I.joinIM $ I.enumPure1Chunk (toBS bs) getI
-- TODO: tryUnpack
-- | Pack to ByteString.
packToString :: Put -> L.ByteString
packToString = runPut

View File

@ -0,0 +1,106 @@
{-# Language TemplateHaskell #-}
module Data.MessagePack.Derive (
derivePack,
deriveUnpack,
deriveObject,
) where
import Control.Applicative
import Control.Monad
import Language.Haskell.TH
import Data.MessagePack.Pack
import Data.MessagePack.Unpack
import Data.MessagePack.Object
deriveUnpack :: Name -> Q [Dec]
deriveUnpack typName = do
TyConI (DataD _ name _ cons _) <- reify typName
return
[ InstanceD [] (AppT (ConT ''Unpackable) (ConT name))
[ FunD 'get [Clause [] (NormalB $ ch $ map body cons) []]
]]
where
body (NormalC conName elms) =
DoE $
tupOrListP (map VarP names) (VarE 'get) ++
[ NoBindS $ AppE (VarE 'return) $ foldl AppE (ConE conName) $ map VarE names ]
where
names = zipWith (\ix _ -> mkName $ "a" ++ show (ix :: Int)) [1..] elms
body (RecC conName elms) =
body (NormalC conName $ map (\(_, b, c) -> (b, c)) elms)
ch = foldl1 (\e f -> AppE (AppE (VarE '(<|>)) e) f)
derivePack :: Name -> Q [Dec]
derivePack typName = do
TyConI (DataD _ name _ cons _) <- reify typName
return
[ InstanceD [] (AppT (ConT ''Packable) (ConT name))
[ FunD 'put (map body cons)
]]
where
body (NormalC conName elms) =
Clause
[ ConP conName $ map VarP names ]
(NormalB $ AppE (VarE 'put) $ tupOrListE $ map VarE names) []
where
names = zipWith (\ix _ -> mkName $ "a" ++ show (ix :: Int)) [1..] elms
body (RecC conName elms) =
body (NormalC conName $ map (\(_, b, c) -> (b, c)) elms)
deriveObject :: Name -> Q [Dec]
deriveObject typName = do
g <- derivePack typName
p <- deriveUnpack typName
TyConI (DataD _ name _ cons _) <- reify typName
let o = InstanceD [] (AppT (ConT ''OBJECT) (ConT name))
[ FunD 'toObject (map toObjectBody cons),
FunD 'tryFromObject [Clause [ VarP oname ]
(NormalB $ ch $ map tryFromObjectBody cons) []]]
return $ g ++ p ++ [o]
where
toObjectBody (NormalC conName elms) =
Clause
[ ConP conName $ map VarP names ]
(NormalB $ AppE (VarE 'toObject) $ tupOrListE $ map VarE names) []
where
names = zipWith (\ix _ -> mkName $ "a" ++ show (ix :: Int)) [1..] elms
toObjectBody (RecC conName elms) =
toObjectBody (NormalC conName $ map (\(_, b, c) -> (b, c)) elms)
tryFromObjectBody (NormalC conName elms) =
DoE $
tupOrListP (map VarP names) (AppE (VarE 'tryFromObject) (VarE oname)) ++
[ NoBindS $ AppE (VarE 'return) $ foldl AppE (ConE conName) $ map VarE names ]
where
names = zipWith (\ix _ -> mkName $ "a" ++ show (ix :: Int)) [1..] elms
tryFromObjectBody (RecC conName elms) =
tryFromObjectBody (NormalC conName $ map (\(_, b, c) -> (b, c)) elms)
oname = mkName "o"
ch = foldl1 (\e f -> AppE (AppE (VarE '(<|>)) e) f)
tupOrListP :: [Pat] -> Exp -> [Stmt]
tupOrListP ls e
| length ls == 0 =
let lsname = mkName "ls" in
[ BindS (VarP lsname) e
, NoBindS $ AppE (VarE 'guard) $ AppE (VarE 'null) $ SigE (VarE lsname) (AppT ListT (ConT ''())) ]
| length ls == 1 = [ BindS (ListP ls) e ]
| otherwise = [ BindS (TupP ls) e ]
tupOrListE :: [Exp] -> Exp
tupOrListE ls
| length ls == 0 = SigE (ListE []) (AppT ListT (ConT ''()))
| length ls == 1 = ListE ls
| otherwise = TupE ls

View File

@ -28,10 +28,10 @@ import qualified Data.ByteString as B
import qualified Data.Iteratee as I
import System.IO
import Data.MessagePack.Parser
import Data.MessagePack.Unpack
-- | Deserialize a value
getI :: (Monad m, ObjectGet a) => I.Iteratee B.ByteString m a
getI :: (Monad m, Unpackable a) => I.Iteratee B.ByteString m a
getI = parserToIteratee get
-- | Enumerator

View File

@ -1,6 +1,7 @@
{-# Language TypeSynonymInstances #-}
{-# Language FlexibleInstances #-}
{-# Language OverlappingInstances #-}
{-# Language IncoherentInstances #-}
{-# Language DeriveDataTypeable #-}
--------------------------------------------------------------------
@ -23,16 +24,21 @@ module Data.MessagePack.Object(
-- * Serialization to and from Object
OBJECT(..),
Result,
-- Result,
) where
import Control.DeepSeq
import Control.Exception
import Control.Monad
import Control.Monad.Trans.Error ()
import qualified Data.Attoparsec as A
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as C8
import Data.Typeable
import Data.MessagePack.Pack
import Data.MessagePack.Unpack
-- | Object Representation of MessagePack data.
data Object =
ObjectNil
@ -55,70 +61,241 @@ instance NFData Object where
ObjectArray a -> rnf a
ObjectMap m -> rnf m
instance Unpackable Object where
get =
A.choice
[ liftM ObjectInteger get
, liftM (\() -> ObjectNil) get
, liftM ObjectBool get
, liftM ObjectDouble get
, liftM ObjectRAW get
, liftM ObjectArray get
, liftM ObjectMap get
]
instance Packable Object where
put obj =
case obj of
ObjectInteger n ->
put n
ObjectNil ->
put ()
ObjectBool b ->
put b
ObjectDouble d ->
put d
ObjectRAW raw ->
put raw
ObjectArray arr ->
put arr
ObjectMap m ->
put m
-- | The class of types serializable to and from MessagePack object
class OBJECT a where
class (Unpackable a, Packable a) => OBJECT a where
-- | Encode a value to MessagePack object
toObject :: a -> Object
toObject = unpack . pack
-- | Decode a value from MessagePack object
fromObject :: Object -> Result a
fromObject :: Object -> a
fromObject a =
case tryFromObject a of
Left err ->
throw $ UnpackError err
Right ret ->
ret
-- | A type for parser results
type Result a = Either String a
-- | Decode a value from MessagePack object
tryFromObject :: Object -> Either String a
tryFromObject = tryUnpack . pack
instance OBJECT Object where
toObject = id
fromObject = Right
tryFromObject = Right
fromObjectError :: String
fromObjectError = "fromObject: cannot cast"
tryFromObjectError :: Either String a
tryFromObjectError = Left "tryFromObject: cannot cast"
instance OBJECT () where
toObject = const ObjectNil
fromObject ObjectNil = Right ()
fromObject _ = Left fromObjectError
tryFromObject ObjectNil = Right ()
tryFromObject _ = tryFromObjectError
instance OBJECT Int where
toObject = ObjectInteger
fromObject (ObjectInteger n) = Right n
fromObject _ = Left fromObjectError
tryFromObject (ObjectInteger n) = Right n
tryFromObject _ = tryFromObjectError
instance OBJECT Bool where
toObject = ObjectBool
fromObject (ObjectBool b) = Right b
fromObject _ = Left fromObjectError
tryFromObject (ObjectBool b) = Right b
tryFromObject _ = tryFromObjectError
instance OBJECT Double where
toObject = ObjectDouble
fromObject (ObjectDouble d) = Right d
fromObject _ = Left fromObjectError
tryFromObject (ObjectDouble d) = Right d
tryFromObject _ = tryFromObjectError
instance OBJECT B.ByteString where
toObject = ObjectRAW
fromObject (ObjectRAW bs) = Right bs
fromObject _ = Left fromObjectError
tryFromObject (ObjectRAW bs) = Right bs
tryFromObject _ = tryFromObjectError
instance OBJECT String where
toObject = toObject . C8.pack
fromObject obj = liftM C8.unpack $ fromObject obj
tryFromObject obj = liftM C8.unpack $ tryFromObject obj
instance OBJECT a => OBJECT [a] where
toObject = ObjectArray . map toObject
fromObject (ObjectArray arr) =
mapM fromObject arr
fromObject _ =
Left fromObjectError
tryFromObject (ObjectArray arr) =
mapM tryFromObject arr
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2) => OBJECT (a1, a2) where
toObject (a1, a2) = ObjectArray [toObject a1, toObject a2]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
return (v1, v2)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2, OBJECT a3) => OBJECT (a1, a2, a3) where
toObject (a1, a2, a3) = ObjectArray [toObject a1, toObject a2, toObject a3]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2, o3] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
v3 <- tryFromObject o3
return (v1, v2, v3)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4) => OBJECT (a1, a2, a3, a4) where
toObject (a1, a2, a3, a4) = ObjectArray [toObject a1, toObject a2, toObject a3, toObject a4]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2, o3, o4] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
v3 <- tryFromObject o3
v4 <- tryFromObject o4
return (v1, v2, v3, v4)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5) => OBJECT (a1, a2, a3, a4, a5) where
toObject (a1, a2, a3, a4, a5) = ObjectArray [toObject a1, toObject a2, toObject a3, toObject a4, toObject a5]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2, o3, o4, o5] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
v3 <- tryFromObject o3
v4 <- tryFromObject o4
v5 <- tryFromObject o5
return (v1, v2, v3, v4, v5)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5, OBJECT a6) => OBJECT (a1, a2, a3, a4, a5, a6) where
toObject (a1, a2, a3, a4, a5, a6) = ObjectArray [toObject a1, toObject a2, toObject a3, toObject a4, toObject a5, toObject a6]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2, o3, o4, o5, o6] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
v3 <- tryFromObject o3
v4 <- tryFromObject o4
v5 <- tryFromObject o5
v6 <- tryFromObject o6
return (v1, v2, v3, v4, v5, v6)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5, OBJECT a6, OBJECT a7) => OBJECT (a1, a2, a3, a4, a5, a6, a7) where
toObject (a1, a2, a3, a4, a5, a6, a7) = ObjectArray [toObject a1, toObject a2, toObject a3, toObject a4, toObject a5, toObject a6, toObject a7]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2, o3, o4, o5, o6, o7] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
v3 <- tryFromObject o3
v4 <- tryFromObject o4
v5 <- tryFromObject o5
v6 <- tryFromObject o6
v7 <- tryFromObject o7
return (v1, v2, v3, v4, v5, v6, v7)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5, OBJECT a6, OBJECT a7, OBJECT a8) => OBJECT (a1, a2, a3, a4, a5, a6, a7, a8) where
toObject (a1, a2, a3, a4, a5, a6, a7, a8) = ObjectArray [toObject a1, toObject a2, toObject a3, toObject a4, toObject a5, toObject a6, toObject a7, toObject a8]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2, o3, o4, o5, o6, o7, o8] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
v3 <- tryFromObject o3
v4 <- tryFromObject o4
v5 <- tryFromObject o5
v6 <- tryFromObject o6
v7 <- tryFromObject o7
v8 <- tryFromObject o8
return (v1, v2, v3, v4, v5, v6, v7, v8)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5, OBJECT a6, OBJECT a7, OBJECT a8, OBJECT a9) => OBJECT (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
toObject (a1, a2, a3, a4, a5, a6, a7, a8, a9) = ObjectArray [toObject a1, toObject a2, toObject a3, toObject a4, toObject a5, toObject a6, toObject a7, toObject a8, toObject a9]
tryFromObject (ObjectArray arr) =
case arr of
[o1, o2, o3, o4, o5, o6, o7, o8, o9] -> do
v1 <- tryFromObject o1
v2 <- tryFromObject o2
v3 <- tryFromObject o3
v4 <- tryFromObject o4
v5 <- tryFromObject o5
v6 <- tryFromObject o6
v7 <- tryFromObject o7
v8 <- tryFromObject o8
v9 <- tryFromObject o9
return (v1, v2, v3, v4, v5, v6, v7, v8, v9)
_ ->
tryFromObjectError
tryFromObject _ =
tryFromObjectError
instance (OBJECT a, OBJECT b) => OBJECT [(a, b)] where
toObject =
ObjectMap . map (\(a, b) -> (toObject a, toObject b))
fromObject (ObjectMap mem) = do
mapM (\(a, b) -> liftM2 (,) (fromObject a) (fromObject b)) mem
fromObject _ =
Left fromObjectError
tryFromObject (ObjectMap mem) = do
mapM (\(a, b) -> liftM2 (,) (tryFromObject a) (tryFromObject b)) mem
tryFromObject _ =
tryFromObjectError
instance OBJECT a => OBJECT (Maybe a) where
toObject (Just a) = toObject a
toObject Nothing = ObjectNil
fromObject ObjectNil = return Nothing
fromObject obj = liftM Just $ fromObject obj
tryFromObject ObjectNil = return Nothing
tryFromObject obj = liftM Just $ tryFromObject obj

View File

@ -5,7 +5,7 @@
--------------------------------------------------------------------
-- |
-- Module : Data.MessagePack.Put
-- Module : Data.MessagePack.Pack
-- Copyright : (c) Hideyuki Tanaka, 2009-2010
-- License : BSD3
--
@ -13,13 +13,15 @@
-- Stability : experimental
-- Portability: portable
--
-- MessagePack Serializer using @Data.Binary.Put@
-- MessagePack Serializer using @Data.Binary.Pack@
--
--------------------------------------------------------------------
module Data.MessagePack.Put(
module Data.MessagePack.Pack (
-- * Serializable class
ObjectPut(..),
Packable(..),
-- * Simple function to pack a Haskell value
pack,
) where
import Data.Binary.Put
@ -30,32 +32,16 @@ import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as L
import qualified Data.Vector as V
import Data.MessagePack.Object
-- | Serializable class
class ObjectPut a where
class Packable a where
-- | Serialize a value
put :: a -> Put
instance ObjectPut Object where
put obj =
case obj of
ObjectInteger n ->
put n
ObjectNil ->
put ()
ObjectBool b ->
put b
ObjectDouble d ->
put d
ObjectRAW raw ->
put raw
ObjectArray arr ->
put arr
ObjectMap m ->
put m
-- | Pack Haskell data to MessagePack string.
pack :: Packable a => a -> L.ByteString
pack = runPut . put
instance ObjectPut Int where
instance Packable Int where
put n =
case n of
_ | n >= 0 && n <= 127 ->
@ -87,26 +73,26 @@ instance ObjectPut Int where
putWord8 0xD3
putWord64be $ fromIntegral n
instance ObjectPut () where
instance Packable () where
put _ =
putWord8 0xC0
instance ObjectPut Bool where
instance Packable Bool where
put True = putWord8 0xC3
put False = putWord8 0xC2
instance ObjectPut Double where
instance Packable Double where
put d = do
putWord8 0xCB
putFloat64be d
instance ObjectPut String where
instance Packable String where
put = putString length (putByteString . B8.pack)
instance ObjectPut B.ByteString where
instance Packable B.ByteString where
put = putString B.length putByteString
instance ObjectPut L.ByteString where
instance Packable L.ByteString where
put = putString (fromIntegral . L.length) putLazyByteString
putString :: (s -> Int) -> (s -> Put) -> s -> Put
@ -122,41 +108,41 @@ putString lf pf str = do
putWord32be $ fromIntegral len
pf str
instance ObjectPut a => ObjectPut [a] where
instance Packable a => Packable [a] where
put = putArray length (mapM_ put)
instance ObjectPut a => ObjectPut (V.Vector a) where
instance Packable a => Packable (V.Vector a) where
put = putArray V.length (V.mapM_ put)
instance (ObjectPut a1, ObjectPut a2) => ObjectPut (a1, a2) where
instance (Packable a1, Packable a2) => Packable (a1, a2) where
put = putArray (const 2) f where
f (a1, a2) = put a1 >> put a2
instance (ObjectPut a1, ObjectPut a2, ObjectPut a3) => ObjectPut (a1, a2, a3) where
instance (Packable a1, Packable a2, Packable a3) => Packable (a1, a2, a3) where
put = putArray (const 3) f where
f (a1, a2, a3) = put a1 >> put a2 >> put a3
instance (ObjectPut a1, ObjectPut a2, ObjectPut a3, ObjectPut a4) => ObjectPut (a1, a2, a3, a4) where
instance (Packable a1, Packable a2, Packable a3, Packable a4) => Packable (a1, a2, a3, a4) where
put = putArray (const 4) f where
f (a1, a2, a3, a4) = put a1 >> put a2 >> put a3 >> put a4
instance (ObjectPut a1, ObjectPut a2, ObjectPut a3, ObjectPut a4, ObjectPut a5) => ObjectPut (a1, a2, a3, a4, a5) where
instance (Packable a1, Packable a2, Packable a3, Packable a4, Packable a5) => Packable (a1, a2, a3, a4, a5) where
put = putArray (const 5) f where
f (a1, a2, a3, a4, a5) = put a1 >> put a2 >> put a3 >> put a4 >> put a5
instance (ObjectPut a1, ObjectPut a2, ObjectPut a3, ObjectPut a4, ObjectPut a5, ObjectPut a6) => ObjectPut (a1, a2, a3, a4, a5, a6) where
instance (Packable a1, Packable a2, Packable a3, Packable a4, Packable a5, Packable a6) => Packable (a1, a2, a3, a4, a5, a6) where
put = putArray (const 6) f where
f (a1, a2, a3, a4, a5, a6) = put a1 >> put a2 >> put a3 >> put a4 >> put a5 >> put a6
instance (ObjectPut a1, ObjectPut a2, ObjectPut a3, ObjectPut a4, ObjectPut a5, ObjectPut a6, ObjectPut a7) => ObjectPut (a1, a2, a3, a4, a5, a6, a7) where
instance (Packable a1, Packable a2, Packable a3, Packable a4, Packable a5, Packable a6, Packable a7) => Packable (a1, a2, a3, a4, a5, a6, a7) where
put = putArray (const 7) f where
f (a1, a2, a3, a4, a5, a6, a7) = put a1 >> put a2 >> put a3 >> put a4 >> put a5 >> put a6 >> put a7
instance (ObjectPut a1, ObjectPut a2, ObjectPut a3, ObjectPut a4, ObjectPut a5, ObjectPut a6, ObjectPut a7, ObjectPut a8) => ObjectPut (a1, a2, a3, a4, a5, a6, a7, a8) where
instance (Packable a1, Packable a2, Packable a3, Packable a4, Packable a5, Packable a6, Packable a7, Packable a8) => Packable (a1, a2, a3, a4, a5, a6, a7, a8) where
put = putArray (const 8) f where
f (a1, a2, a3, a4, a5, a6, a7, a8) = put a1 >> put a2 >> put a3 >> put a4 >> put a5 >> put a6 >> put a7 >> put a8
instance (ObjectPut a1, ObjectPut a2, ObjectPut a3, ObjectPut a4, ObjectPut a5, ObjectPut a6, ObjectPut a7, ObjectPut a8, ObjectPut a9) => ObjectPut (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
instance (Packable a1, Packable a2, Packable a3, Packable a4, Packable a5, Packable a6, Packable a7, Packable a8, Packable a9) => Packable (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
put = putArray (const 9) f where
f (a1, a2, a3, a4, a5, a6, a7, a8, a9) = put a1 >> put a2 >> put a3 >> put a4 >> put a5 >> put a6 >> put a7 >> put a8 >> put a9
@ -173,13 +159,13 @@ putArray lf pf arr = do
putWord32be $ fromIntegral len
pf arr
instance (ObjectPut k, ObjectPut v) => ObjectPut [(k, v)] where
instance (Packable k, Packable v) => Packable [(k, v)] where
put = putMap length (mapM_ putPair)
instance (ObjectPut k, ObjectPut v) => ObjectPut (V.Vector (k, v)) where
instance (Packable k, Packable v) => Packable (V.Vector (k, v)) where
put = putMap V.length (V.mapM_ putPair)
putPair :: (ObjectPut a, ObjectPut b) => (a, b) -> Put
putPair :: (Packable a, Packable b) => (a, b) -> Put
putPair (a, b) = put a >> put b
putMap :: (a -> Int) -> (a -> Put) -> a -> Put
@ -194,3 +180,7 @@ putMap lf pf m = do
putWord8 0xDF
putWord32be $ fromIntegral len
pf m
instance Packable a => Packable (Maybe a) where
put Nothing = put ()
put (Just a) = put a

View File

@ -2,10 +2,11 @@
{-# Language IncoherentInstances #-}
{-# Language OverlappingInstances #-}
{-# Language TypeSynonymInstances #-}
{-# Language DeriveDataTypeable #-}
--------------------------------------------------------------------
-- |
-- Module : Data.MessagePack.Parser
-- Module : Data.MessagePack.Unpack
-- Copyright : (c) Hideyuki Tanaka, 2009-2010
-- License : BSD3
--
@ -17,11 +18,19 @@
--
--------------------------------------------------------------------
module Data.MessagePack.Parser(
module Data.MessagePack.Unpack(
-- * MessagePack deserializer
ObjectGet(..),
Unpackable(..),
-- * Simple function to unpack a Haskell value
unpack,
tryUnpack,
-- * Unpack exception
UnpackError(..),
-- * ByteString utils
IsByteString(..),
) where
import Control.Exception
import Control.Monad
import qualified Data.Attoparsec as A
import Data.Binary.Get
@ -31,30 +40,53 @@ import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as L
import Data.Int
import Data.Typeable
import qualified Data.Vector as V
import Data.Word
import Text.Printf
import Data.MessagePack.Object
-- | Deserializable class
class ObjectGet a where
class Unpackable a where
-- | Deserialize a value
get :: A.Parser a
instance ObjectGet Object where
get =
A.choice
[ liftM ObjectInteger get
, liftM (\() -> ObjectNil) get
, liftM ObjectBool get
, liftM ObjectDouble get
, liftM ObjectRAW get
, liftM ObjectArray get
, liftM ObjectMap get
]
class IsByteString s where
toBS :: s -> B.ByteString
instance ObjectGet Int where
instance IsByteString B.ByteString where
toBS = id
instance IsByteString L.ByteString where
toBS = B.concat . L.toChunks
-- | The exception of unpack
data UnpackError =
UnpackError String
deriving (Show, Typeable)
instance Exception UnpackError
-- | Unpack MessagePack string to Haskell data.
unpack :: (Unpackable a, IsByteString s) => s -> a
unpack bs =
case tryUnpack bs of
Left err ->
throw $ UnpackError err
Right ret ->
ret
-- | Unpack MessagePack string to Haskell data.
tryUnpack :: (Unpackable a, IsByteString s) => s -> Either String a
tryUnpack bs =
case A.parse get (toBS bs) of
A.Fail _ _ err ->
Left err
A.Partial _ ->
Left "not enough input"
A.Done _ ret ->
Right ret
instance Unpackable Int where
get = do
c <- A.anyWord8
case c of
@ -81,7 +113,7 @@ instance ObjectGet Int where
_ ->
fail $ printf "invlid integer tag: 0x%02X" c
instance ObjectGet () where
instance Unpackable () where
get = do
c <- A.anyWord8
case c of
@ -90,7 +122,7 @@ instance ObjectGet () where
_ ->
fail $ printf "invlid nil tag: 0x%02X" c
instance ObjectGet Bool where
instance Unpackable Bool where
get = do
c <- A.anyWord8
case c of
@ -101,7 +133,7 @@ instance ObjectGet Bool where
_ ->
fail $ printf "invlid bool tag: 0x%02X" c
instance ObjectGet Double where
instance Unpackable Double where
get = do
c <- A.anyWord8
case c of
@ -112,13 +144,13 @@ instance ObjectGet Double where
_ ->
fail $ printf "invlid double tag: 0x%02X" c
instance ObjectGet String where
instance Unpackable String where
get = parseString (\n -> return . B8.unpack =<< A.take n)
instance ObjectGet B.ByteString where
instance Unpackable B.ByteString where
get = parseString A.take
instance ObjectGet L.ByteString where
instance Unpackable L.ByteString where
get = parseString (\n -> do bs <- A.take n; return $ L.fromChunks [bs])
parseString :: (Int -> A.Parser a) -> A.Parser a
@ -134,48 +166,48 @@ parseString aget = do
_ ->
fail $ printf "invlid raw tag: 0x%02X" c
instance ObjectGet a => ObjectGet [a] where
instance Unpackable a => Unpackable [a] where
get = parseArray (flip replicateM get)
instance ObjectGet a => ObjectGet (V.Vector a) where
instance Unpackable a => Unpackable (V.Vector a) where
get = parseArray (flip V.replicateM get)
instance (ObjectGet a1, ObjectGet a2) => ObjectGet (a1, a2) where
instance (Unpackable a1, Unpackable a2) => Unpackable (a1, a2) where
get = parseArray f where
f 2 = get >>= \a1 -> get >>= \a2 -> return (a1, a2)
f n = fail $ printf "wrong tupple size: expected 2 but got " n
instance (ObjectGet a1, ObjectGet a2, ObjectGet a3) => ObjectGet (a1, a2, a3) where
instance (Unpackable a1, Unpackable a2, Unpackable a3) => Unpackable (a1, a2, a3) where
get = parseArray f where
f 3 = get >>= \a1 -> get >>= \a2 -> get >>= \a3 -> return (a1, a2, a3)
f n = fail $ printf "wrong tupple size: expected 3 but got " n
instance (ObjectGet a1, ObjectGet a2, ObjectGet a3, ObjectGet a4) => ObjectGet (a1, a2, a3, a4) where
instance (Unpackable a1, Unpackable a2, Unpackable a3, Unpackable a4) => Unpackable (a1, a2, a3, a4) where
get = parseArray f where
f 4 = get >>= \a1 -> get >>= \a2 -> get >>= \a3 -> get >>= \a4 -> return (a1, a2, a3, a4)
f n = fail $ printf "wrong tupple size: expected 4 but got " n
instance (ObjectGet a1, ObjectGet a2, ObjectGet a3, ObjectGet a4, ObjectGet a5) => ObjectGet (a1, a2, a3, a4, a5) where
instance (Unpackable a1, Unpackable a2, Unpackable a3, Unpackable a4, Unpackable a5) => Unpackable (a1, a2, a3, a4, a5) where
get = parseArray f where
f 5 = get >>= \a1 -> get >>= \a2 -> get >>= \a3 -> get >>= \a4 -> get >>= \a5 -> return (a1, a2, a3, a4, a5)
f n = fail $ printf "wrong tupple size: expected 5 but got " n
instance (ObjectGet a1, ObjectGet a2, ObjectGet a3, ObjectGet a4, ObjectGet a5, ObjectGet a6) => ObjectGet (a1, a2, a3, a4, a5, a6) where
instance (Unpackable a1, Unpackable a2, Unpackable a3, Unpackable a4, Unpackable a5, Unpackable a6) => Unpackable (a1, a2, a3, a4, a5, a6) where
get = parseArray f where
f 6 = get >>= \a1 -> get >>= \a2 -> get >>= \a3 -> get >>= \a4 -> get >>= \a5 -> get >>= \a6 -> return (a1, a2, a3, a4, a5, a6)
f n = fail $ printf "wrong tupple size: expected 6 but got " n
instance (ObjectGet a1, ObjectGet a2, ObjectGet a3, ObjectGet a4, ObjectGet a5, ObjectGet a6, ObjectGet a7) => ObjectGet (a1, a2, a3, a4, a5, a6, a7) where
instance (Unpackable a1, Unpackable a2, Unpackable a3, Unpackable a4, Unpackable a5, Unpackable a6, Unpackable a7) => Unpackable (a1, a2, a3, a4, a5, a6, a7) where
get = parseArray f where
f 7 = get >>= \a1 -> get >>= \a2 -> get >>= \a3 -> get >>= \a4 -> get >>= \a5 -> get >>= \a6 -> get >>= \a7 -> return (a1, a2, a3, a4, a5, a6, a7)
f n = fail $ printf "wrong tupple size: expected 7 but got " n
instance (ObjectGet a1, ObjectGet a2, ObjectGet a3, ObjectGet a4, ObjectGet a5, ObjectGet a6, ObjectGet a7, ObjectGet a8) => ObjectGet (a1, a2, a3, a4, a5, a6, a7, a8) where
instance (Unpackable a1, Unpackable a2, Unpackable a3, Unpackable a4, Unpackable a5, Unpackable a6, Unpackable a7, Unpackable a8) => Unpackable (a1, a2, a3, a4, a5, a6, a7, a8) where
get = parseArray f where
f 8 = get >>= \a1 -> get >>= \a2 -> get >>= \a3 -> get >>= \a4 -> get >>= \a5 -> get >>= \a6 -> get >>= \a7 -> get >>= \a8 -> return (a1, a2, a3, a4, a5, a6, a7, a8)
f n = fail $ printf "wrong tupple size: expected 8 but got " n
instance (ObjectGet a1, ObjectGet a2, ObjectGet a3, ObjectGet a4, ObjectGet a5, ObjectGet a6, ObjectGet a7, ObjectGet a8, ObjectGet a9) => ObjectGet (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
instance (Unpackable a1, Unpackable a2, Unpackable a3, Unpackable a4, Unpackable a5, Unpackable a6, Unpackable a7, Unpackable a8, Unpackable a9) => Unpackable (a1, a2, a3, a4, a5, a6, a7, a8, a9) where
get = parseArray f where
f 9 = get >>= \a1 -> get >>= \a2 -> get >>= \a3 -> get >>= \a4 -> get >>= \a5 -> get >>= \a6 -> get >>= \a7 -> get >>= \a8 -> get >>= \a9 -> return (a1, a2, a3, a4, a5, a6, a7, a8, a9)
f n = fail $ printf "wrong tupple size: expected 9 but got " n
@ -193,13 +225,13 @@ parseArray aget = do
_ ->
fail $ printf "invlid array tag: 0x%02X" c
instance (ObjectGet k, ObjectGet v) => ObjectGet [(k, v)] where
instance (Unpackable k, Unpackable v) => Unpackable [(k, v)] where
get = parseMap (flip replicateM parsePair)
instance (ObjectGet k, ObjectGet v) => ObjectGet (V.Vector (k, v)) where
instance (Unpackable k, Unpackable v) => Unpackable (V.Vector (k, v)) where
get = parseMap (flip V.replicateM parsePair)
parsePair :: (ObjectGet k, ObjectGet v) => A.Parser (k, v)
parsePair :: (Unpackable k, Unpackable v) => A.Parser (k, v)
parsePair = do
a <- get
b <- get
@ -218,6 +250,12 @@ parseMap aget = do
_ ->
fail $ printf "invlid map tag: 0x%02X" c
instance Unpackable a => Unpackable (Maybe a) where
get =
A.choice
[ liftM Just get
, liftM (\() -> Nothing) get ]
parseUint16 :: A.Parser Word16
parseUint16 = do
b0 <- A.anyWord8

View File

@ -7,7 +7,7 @@ import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as L
import Data.MessagePack
mid :: (ObjectGet a, ObjectPut a) => a -> a
mid :: (Packable a, Unpackable a) => a -> a
mid = unpack . pack
prop_mid_int a = a == mid a

43
haskell/test/UserData.hs Normal file
View File

@ -0,0 +1,43 @@
{-# Language TemplateHaskell #-}
import Data.MessagePack
import Data.MessagePack.Derive
data T
= A Int String
| B Double
deriving (Show, Eq)
$(deriveObject ''T)
data U
= C { c1 :: Int, c2 :: String }
| D { d1 :: Double }
deriving (Show, Eq)
$(deriveObject ''U)
data V
= E String | F
deriving (Show, Eq)
$(deriveObject ''V)
test :: (OBJECT a, Show a, Eq a) => a -> IO ()
test v = do
let bs = pack v
print bs
print (unpack bs == v)
let oa = toObject v
print oa
print (fromObject oa == v)
main = do
test $ A 123 "hoge"
test $ B 3.14
test $ C 123 "hoge"
test $ D 3.14
test $ E "hello"
test $ F
return ()

View File

@ -0,0 +1,27 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
public abstract class AbstractTemplate implements Template {
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return convert(pac.unpackObject());
}
}

View File

@ -0,0 +1,39 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.util.Map;
import java.util.HashMap;
// FIXME package private?
public class CustomConverter {
public static void register(Class target, MessageConverter converter) {
map.put(target, converter);
}
public static MessageConverter get(Class target) {
return map.get(target);
}
public static boolean isRegistered(Class target) {
return map.containsKey(target);
}
private static Map<Class, MessageConverter> map = new HashMap<Class, MessageConverter>();
}

View File

@ -0,0 +1,30 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
public class CustomMessage {
public static void registerPacker(Class target, MessagePacker packer) {
CustomPacker.register(target, packer);
}
public static void registerTemplate(Class target, Template tmpl) {
CustomUnpacker.register(target, tmpl);
CustomConverter.register(target, tmpl);
}
}

View File

@ -0,0 +1,39 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.util.Map;
import java.util.HashMap;
// FIXME package private?
public class CustomPacker {
public static void register(Class target, MessagePacker converter) {
map.put(target, converter);
}
public static MessagePacker get(Class target) {
return map.get(target);
}
public static boolean isRegistered(Class target) {
return map.containsKey(target);
}
private static Map<Class, MessagePacker> map = new HashMap<Class, MessagePacker>();
}

View File

@ -0,0 +1,39 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.util.Map;
import java.util.HashMap;
// FIXME package private?
public class CustomUnpacker {
public static void register(Class target, MessageUnpacker converter) {
map.put(target, converter);
}
public static MessageUnpacker get(Class target) {
return map.get(target);
}
public static boolean isRegistered(Class target) {
return map.containsKey(target);
}
private static Map<Class, MessageUnpacker> map = new HashMap<Class, MessageUnpacker>();
}

View File

@ -0,0 +1,25 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
public interface MessageConverter {
public Object convert(MessagePackObject from) throws MessageTypeException;
}

View File

@ -132,5 +132,9 @@ public abstract class MessagePackObject implements Cloneable, MessagePackable {
}
abstract public Object clone();
public Object convert(Template tmpl) throws MessageTypeException {
return tmpl.convert(this);
}
}

View File

@ -0,0 +1,25 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
public interface MessagePacker {
public void pack(Packer pk, Object target) throws IOException;
}

View File

@ -0,0 +1,25 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
public interface MessageUnpacker {
public Object unpack(Unpacker pac) throws IOException, MessageTypeException;
}

View File

@ -473,9 +473,19 @@ public class Packer {
return packDouble((Double)o);
} else if(o instanceof BigInteger) {
return packBigInteger((BigInteger)o);
} else {
throw new MessageTypeException("unknown object "+o+" ("+o.getClass()+")");
}
Class klass = o.getClass();
MessagePacker packer = CustomPacker.get(klass);
if(packer != null) {
packer.pack(this, o);
return this;
}
// FIXME check annotations -> code generation -> CustomMessage.registerPacker
throw new MessageTypeException("unknown object "+o+" ("+o.getClass()+")");
}
}

View File

@ -0,0 +1,26 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
import java.lang.reflect.*;
// FIXME mock-up
abstract class ReflectionBase {
}

View File

@ -0,0 +1,49 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
import java.lang.reflect.*;
// FIXME mock-up
public class ReflectionPacker extends ReflectionBase implements MessagePacker {
private Class<?> klass;
private ReflectionPacker(Class<?> klass) {
this.klass = klass;
}
static public ReflectionPacker create(Class klass) {
// FIXME code generation: generates subclass of ReflectionPacker
// returned instance will be cached by Packer into CustomPacker
return new ReflectionPacker(klass);
}
public void pack(Packer pk, Object target) throws IOException {
Field[] fields = klass.getDeclaredFields();
pk.packArray(fields.length);
try {
for(int i=0; i < fields.length; i++) {
pk.pack(fields[i].get(target));
}
} catch(IllegalAccessException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
}
}
}

View File

@ -0,0 +1,74 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import java.io.IOException;
import java.lang.reflect.*;
import org.msgpack.template.ClassTemplate;
// FIXME mock-up
public class ReflectionTemplate extends ReflectionBase implements Template {
private Class klass;
private ReflectionTemplate(Class klass) {
this.klass = klass;
}
static public ReflectionTemplate create(Class klass) {
// FIXME code generation: generates subclass of ReflectionPacker
// returned instance will be cached by ClassTemplate into CustomUnpacker/CustomConverter
return new ReflectionTemplate(klass);
}
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
// FIXME optimize it
return convert(pac.unpackObject());
}
public Object convert(MessagePackObject from) throws MessageTypeException {
Object obj;
try {
obj = klass.newInstance();
} catch (IllegalAccessException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
} catch (InstantiationException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
}
// FIXME check Requred/Optional
Field[] fields = klass.getDeclaredFields();
MessagePackObject[] array = from.asArray();
if(fields.length < array.length) {
throw new MessageTypeException();
}
try {
for(int i=0; i < fields.length; i++) {
// FIXME generics getDeclaringClass
Object value = new ClassTemplate(fields[i].getType()).convert(array[i]);
fields[i].set(obj, value);
}
} catch(IllegalAccessException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
}
return obj;
}
}

View File

@ -0,0 +1,22 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
public interface Template extends MessageUnpacker, MessageConverter {
}

View File

@ -0,0 +1,86 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack;
import org.msgpack.template.*;
public class Templates {
public static Template tList(Template elementTemplate) {
return new ListTemplate(elementTemplate);
}
public static Template tMap(Template keyTemplate, Template valueTemplate) {
return new MapTemplate(keyTemplate, valueTemplate);
}
public static Template tClass(Class target) {
return new ClassTemplate(target);
}
public static final Template TByte = ByteTemplate.getInstance();
public static Template tByte() {
return TByte;
}
public static final Template TShort = ShortTemplate.getInstance();
public static Template tShort() {
return TShort;
}
public static final Template TInteger = IntegerTemplate.getInstance();
public static Template tInteger() {
return TInteger;
}
public static final Template TLong = LongTemplate.getInstance();
public static Template tLong() {
return TLong;
}
public static final Template TBigInteger = BigIntegerTemplate.getInstance();
public static Template tBigInteger() {
return TBigInteger;
}
public static final Template TFloat = FloatTemplate.getInstance();
public static Template tFloat() {
return TFloat;
}
public static final Template TDouble = DoubleTemplate.getInstance();
public static Template tDouble() {
return TDouble;
}
public static final Template TBoolean = BooleanTemplate.getInstance();
public static Template tBoolean() {
return TBoolean;
}
public static final Template TString = StringTemplate.getInstance();
public static Template tString() {
return TString;
}
public static final Template TByteArray = ByteArrayTemplate.getInstance();
public static Template tByteArray() {
return TByteArray;
}
}

View File

@ -561,12 +561,38 @@ public class Unpacker implements Iterable<MessagePackObject> {
return impl.unpackObject();
}
final public boolean tryUnpackNull() throws IOException {
return impl.tryUnpackNull();
}
final public Object unpack(MessageUnpacker unpacker) throws IOException, MessageTypeException {
return unpacker.unpack(this);
}
final public void unpack(MessageUnpackable obj) throws IOException, MessageTypeException {
obj.messageUnpack(this);
}
final public boolean tryUnpackNull() throws IOException {
return impl.tryUnpackNull();
final public Object unpack(Class klass) throws IOException, MessageTypeException, InstantiationException, IllegalAccessException {
if(MessageUnpackable.class.isAssignableFrom(klass)) {
Object obj = klass.newInstance();
((MessageUnpackable)obj).messageUnpack(this);
return obj;
}
MessageUnpacker unpacker = CustomUnpacker.get(klass);
if(unpacker != null) {
return unpacker.unpack(this);
}
// FIXME check annotations -> code generation -> CustomMessage.registerTemplate
MessageConverter converter = CustomConverter.get(klass);
if(converter != null) {
return converter.convert(unpackObject());
}
throw new MessageTypeException();
}
}

View File

@ -0,0 +1,45 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import java.math.BigInteger;
import org.msgpack.*;
public class BigIntegerTemplate implements Template {
private BigIntegerTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackBigInteger();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asBigInteger();
}
static public BigIntegerTemplate getInstance() {
return instance;
}
static final BigIntegerTemplate instance = new BigIntegerTemplate();
static {
CustomMessage.registerTemplate(BigInteger.class, instance);
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class BooleanTemplate implements Template {
private BooleanTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackBoolean();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asBoolean();
}
static public BooleanTemplate getInstance() {
return instance;
}
static final BooleanTemplate instance = new BooleanTemplate();
static {
CustomMessage.registerTemplate(Boolean.class, instance);
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class ByteArrayTemplate implements Template {
private ByteArrayTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackByteArray();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asByteArray();
}
static public ByteArrayTemplate getInstance() {
return instance;
}
static final ByteArrayTemplate instance = new ByteArrayTemplate();
static {
CustomMessage.registerTemplate(byte[].class, instance);
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class ByteTemplate implements Template {
private ByteTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackByte();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asByte();
}
static public ByteTemplate getInstance() {
return instance;
}
static final ByteTemplate instance = new ByteTemplate();
static {
CustomMessage.registerTemplate(Byte.class, instance);
}
}

View File

@ -0,0 +1,64 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class ClassTemplate implements Template {
private Class klass;
public ClassTemplate(Class klass) {
this.klass = klass;
}
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
try {
return pac.unpack(klass);
} catch (IllegalAccessException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
} catch (InstantiationException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
}
}
public Object convert(MessagePackObject from) throws MessageTypeException {
if(MessageConvertable.class.isAssignableFrom(klass)) {
Object obj;
try {
obj = klass.newInstance();
} catch (IllegalAccessException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
} catch (InstantiationException e) {
throw new MessageTypeException(e.getMessage()); // FIXME
}
((MessageConvertable)obj).messageConvert(from);
return obj;
}
MessageConverter converter = CustomConverter.get(klass);
if(converter != null) {
return converter.convert(from);
}
// FIXME check annotations -> code generation -> CustomMessage.registerTemplate
throw new MessageTypeException();
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class DoubleTemplate implements Template {
private DoubleTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackDouble();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asDouble();
}
static public DoubleTemplate getInstance() {
return instance;
}
static final DoubleTemplate instance = new DoubleTemplate();
static {
CustomMessage.registerTemplate(Double.class, instance);
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class FloatTemplate implements Template {
private FloatTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackFloat();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asFloat();
}
static public FloatTemplate getInstance() {
return instance;
}
static final FloatTemplate instance = new FloatTemplate();
static {
CustomMessage.registerTemplate(Float.class, instance);
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class IntegerTemplate implements Template {
private IntegerTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackInt();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asInt();
}
static public IntegerTemplate getInstance() {
return instance;
}
static final IntegerTemplate instance = new IntegerTemplate();
static {
CustomMessage.registerTemplate(Integer.class, instance);
}
}

View File

@ -0,0 +1,50 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.util.List;
import java.util.ArrayList;
import java.io.IOException;
import org.msgpack.*;
public class ListTemplate implements Template {
private Template elementTemplate;
public ListTemplate(Template elementTemplate) {
this.elementTemplate = elementTemplate;
}
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
int length = pac.unpackArray();
List<Object> list = new ArrayList<Object>(length);
for(; length > 0; length--) {
list.add( elementTemplate.unpack(pac) );
}
return list;
}
public Object convert(MessagePackObject from) throws MessageTypeException {
MessagePackObject[] array = from.asArray();
List<Object> list = new ArrayList<Object>(array.length);
for(MessagePackObject element : array) {
list.add( elementTemplate.convert(element) );
}
return list;
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class LongTemplate implements Template {
private LongTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackLong();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asLong();
}
static public LongTemplate getInstance() {
return instance;
}
static final LongTemplate instance = new LongTemplate();
static {
CustomMessage.registerTemplate(Long.class, instance);
}
}

View File

@ -0,0 +1,56 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.util.Map;
import java.util.HashMap;
import java.io.IOException;
import org.msgpack.*;
public class MapTemplate implements Template {
private Template keyTemplate;
private Template valueTemplate;
public MapTemplate(Template keyTemplate, Template valueTemplate) {
this.keyTemplate = keyTemplate;
this.valueTemplate = valueTemplate;
}
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
int length = pac.unpackMap();
Map<Object,Object> map = new HashMap<Object,Object>(length);
for(; length > 0; length--) {
Object key = keyTemplate.unpack(pac);
Object value = valueTemplate.unpack(pac);
map.put(key, value);
}
return map;
}
public Object convert(MessagePackObject from) throws MessageTypeException {
Map<MessagePackObject,MessagePackObject> src = from.asMap();
Map<Object,Object> map = new HashMap();
for(Map.Entry<MessagePackObject,MessagePackObject> pair : src.entrySet()) {
Object key = keyTemplate.convert(pair.getKey());
Object value = valueTemplate.convert(pair.getValue());
map.put(key, value);
}
return map;
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class ShortTemplate implements Template {
private ShortTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackShort();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asShort();
}
static public ShortTemplate getInstance() {
return instance;
}
static final ShortTemplate instance = new ShortTemplate();
static {
CustomMessage.registerTemplate(Short.class, instance);
}
}

View File

@ -0,0 +1,44 @@
//
// MessagePack for Java
//
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package org.msgpack.template;
import java.io.IOException;
import org.msgpack.*;
public class StringTemplate implements Template {
private StringTemplate() { }
public Object unpack(Unpacker pac) throws IOException, MessageTypeException {
return pac.unpackString();
}
public Object convert(MessagePackObject from) throws MessageTypeException {
return from.asString();
}
static public StringTemplate getInstance() {
return instance;
}
static final StringTemplate instance = new StringTemplate();
static {
CustomMessage.registerTemplate(String.class, instance);
}
}

View File

@ -0,0 +1,46 @@
package org.msgpack;
import static org.msgpack.Templates.*;
import java.util.*;
import java.io.*;
import org.junit.Test;
import static org.junit.Assert.*;
public class TestReflectionPackerTemplate {
public static class StringFieldClass {
public String s1;
public String s2;
public StringFieldClass() { }
}
@Test
public void testPackConvert() throws Exception {
tString(); // FIXME link StringTemplate
ByteArrayOutputStream out = new ByteArrayOutputStream();
MessagePacker packer = ReflectionPacker.create(StringFieldClass.class);
StringFieldClass src = new StringFieldClass();
src.s1 = "kumofs";
src.s2 = "frsyuki";
packer.pack(new Packer(out), src);
Template tmpl = ReflectionTemplate.create(StringFieldClass.class);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Object obj = tmpl.unpack(new Unpacker(in));
assertEquals(obj.getClass(), StringFieldClass.class);
StringFieldClass dst = (StringFieldClass)obj;
assertEquals(src.s1, dst.s1);
assertEquals(src.s2, dst.s2);
}
}

View File

@ -12,6 +12,7 @@ import java.util.Map;
import junit.framework.TestCase;
import org.junit.Test;
import org.msgpack.MessagePackObject;
import org.msgpack.MessageUnpackable;
import org.msgpack.Packer;
import org.msgpack.Unpacker;
@ -19,7 +20,7 @@ import org.msgpack.Unpacker;
public class TestMessagePackUnpackable extends TestCase {
@Test
public void testPrimitiveTypeFields() throws Exception {
public void testPrimitiveTypeFields01() throws Exception {
PrimitiveTypeFieldsClass src = (PrimitiveTypeFieldsClass) PackUnpackUtil
.newEnhancedInstance(PrimitiveTypeFieldsClass.class);
src.f0 = (byte) 0;
@ -45,6 +46,36 @@ public class TestMessagePackUnpackable extends TestCase {
assertEquals(src.f6, dst.f6);
}
@Test
public void testPrimitiveTypeFields02() throws Exception {
PrimitiveTypeFieldsClass src = (PrimitiveTypeFieldsClass) PackUnpackUtil
.newEnhancedInstance(PrimitiveTypeFieldsClass.class);
src.f0 = (byte) 0;
src.f1 = 1;
src.f2 = 2;
src.f3 = 3;
src.f4 = 4;
src.f5 = 5;
src.f6 = false;
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
Iterator<MessagePackObject> it = pac.iterator();
assertTrue(it.hasNext());
MessagePackObject mpo = it.next();
PrimitiveTypeFieldsClass dst = (PrimitiveTypeFieldsClass) PackUnpackUtil
.initEnhancedInstance(mpo, PrimitiveTypeFieldsClass.class);
assertEquals(src.f0, dst.f0);
assertEquals(src.f1, dst.f1);
assertEquals(src.f2, dst.f2);
assertEquals(src.f3, dst.f3);
assertEquals(src.f4, dst.f4);
assertEquals(src.f5, dst.f5);
assertEquals(src.f6, dst.f6);
assertFalse(it.hasNext());
}
@MessagePackUnpackable
public static class PrimitiveTypeFieldsClass {
public byte f0;
@ -60,7 +91,7 @@ public class TestMessagePackUnpackable extends TestCase {
}
@Test
public void testGeneralReferenceTypeFieldsClass() throws Exception {
public void testGeneralReferenceTypeFieldsClass01() throws Exception {
GeneralReferenceTypeFieldsClass src = (GeneralReferenceTypeFieldsClass) PackUnpackUtil
.newEnhancedInstance(GeneralReferenceTypeFieldsClass.class);
src.f0 = 0;
@ -93,6 +124,44 @@ public class TestMessagePackUnpackable extends TestCase {
assertEquals(src.f9[1], dst.f9[1]);
}
@Test
public void testGeneralReferenceTypeFieldsClass02() throws Exception {
GeneralReferenceTypeFieldsClass src = (GeneralReferenceTypeFieldsClass) PackUnpackUtil
.newEnhancedInstance(GeneralReferenceTypeFieldsClass.class);
src.f0 = 0;
src.f1 = 1;
src.f2 = 2;
src.f3 = (long) 3;
src.f4 = (float) 4;
src.f5 = (double) 5;
src.f6 = false;
src.f7 = new BigInteger("7");
src.f8 = "8";
src.f9 = new byte[] { 0x01, 0x02 };
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
Iterator<MessagePackObject> it = pac.iterator();
assertTrue(it.hasNext());
MessagePackObject mpo = it.next();
GeneralReferenceTypeFieldsClass dst = (GeneralReferenceTypeFieldsClass) PackUnpackUtil
.initEnhancedInstance(mpo,
GeneralReferenceTypeFieldsClass.class);
assertEquals(src.f0, dst.f0);
assertEquals(src.f1, dst.f1);
assertEquals(src.f2, dst.f2);
assertEquals(src.f3, dst.f3);
assertEquals(src.f4, dst.f4);
assertEquals(src.f5, dst.f5);
assertEquals(src.f6, dst.f6);
assertEquals(src.f7, dst.f7);
assertEquals(src.f8, dst.f8);
assertEquals(src.f9[0], dst.f9[0]);
assertEquals(src.f9[1], dst.f9[1]);
assertFalse(it.hasNext());
}
@MessagePackUnpackable
public static class GeneralReferenceTypeFieldsClass {
public Byte f0;
@ -110,7 +179,7 @@ public class TestMessagePackUnpackable extends TestCase {
}
}
public void testListTypes() throws Exception {
public void testListTypes01() throws Exception {
SampleListTypes src = (SampleListTypes) PackUnpackUtil
.newEnhancedInstance(SampleListTypes.class);
src.f0 = new ArrayList<Integer>();
@ -140,6 +209,39 @@ public class TestMessagePackUnpackable extends TestCase {
}
}
public void testListTypes02() throws Exception {
SampleListTypes src = (SampleListTypes) PackUnpackUtil
.newEnhancedInstance(SampleListTypes.class);
src.f0 = new ArrayList<Integer>();
src.f1 = new ArrayList<Integer>();
src.f1.add(1);
src.f1.add(2);
src.f1.add(3);
src.f2 = new ArrayList<String>();
src.f2.add("e1");
src.f2.add("e2");
src.f2.add("e3");
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
Iterator<MessagePackObject> it = pac.iterator();
assertTrue(it.hasNext());
MessagePackObject mpo = it.next();
SampleListTypes dst = (SampleListTypes) PackUnpackUtil
.initEnhancedInstance(mpo, SampleListTypes.class);
assertEquals(src.f0.size(), dst.f0.size());
assertEquals(src.f1.size(), dst.f1.size());
for (int i = 0; i < src.f1.size(); ++i) {
assertEquals(src.f1.get(i), dst.f1.get(i));
}
assertEquals(src.f2.size(), dst.f2.size());
for (int i = 0; i < src.f2.size(); ++i) {
assertEquals(src.f2.get(i), dst.f2.get(i));
}
assertFalse(it.hasNext());
}
@MessagePackUnpackable
public static class SampleListTypes {
public List<Integer> f0;
@ -150,7 +252,7 @@ public class TestMessagePackUnpackable extends TestCase {
}
}
public void testMapTypes() throws Exception {
public void testMapTypes01() throws Exception {
SampleMapTypes src = (SampleMapTypes) PackUnpackUtil
.newEnhancedInstance(SampleMapTypes.class);
src.f0 = new HashMap<Integer, Integer>();
@ -190,6 +292,49 @@ public class TestMessagePackUnpackable extends TestCase {
}
}
public void testMapTypes02() throws Exception {
SampleMapTypes src = (SampleMapTypes) PackUnpackUtil
.newEnhancedInstance(SampleMapTypes.class);
src.f0 = new HashMap<Integer, Integer>();
src.f1 = new HashMap<Integer, Integer>();
src.f1.put(1, 1);
src.f1.put(2, 2);
src.f1.put(3, 3);
src.f2 = new HashMap<String, Integer>();
src.f2.put("k1", 1);
src.f2.put("k2", 2);
src.f2.put("k3", 3);
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
Iterator<MessagePackObject> it = pac.iterator();
assertTrue(it.hasNext());
MessagePackObject mpo = it.next();
SampleMapTypes dst = (SampleMapTypes) PackUnpackUtil
.initEnhancedInstance(mpo, SampleMapTypes.class);
assertEquals(src.f0.size(), dst.f0.size());
assertEquals(src.f1.size(), dst.f1.size());
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
while (srcf1.hasNext()) {
Integer s1 = srcf1.next();
Integer d1 = dstf1.next();
assertEquals(s1, d1);
assertEquals(src.f1.get(s1), dst.f1.get(d1));
}
assertEquals(src.f2.size(), dst.f2.size());
Iterator<String> srcf2 = src.f2.keySet().iterator();
Iterator<String> dstf2 = dst.f2.keySet().iterator();
while (srcf2.hasNext()) {
String s2 = srcf2.next();
String d2 = dstf2.next();
assertEquals(s2, d2);
assertEquals(src.f2.get(s2), dst.f2.get(d2));
}
assertFalse(it.hasNext());
}
@MessagePackUnpackable
public static class SampleMapTypes {
public Map<Integer, Integer> f0;
@ -351,7 +496,7 @@ public class TestMessagePackUnpackable extends TestCase {
}
@Test
public void testFieldModifiers() throws Exception {
public void testFieldModifiers01() throws Exception {
FieldModifiersClass src = (FieldModifiersClass) PackUnpackUtil
.newEnhancedInstance(FieldModifiersClass.class);
src.f0 = 0;
@ -372,6 +517,31 @@ public class TestMessagePackUnpackable extends TestCase {
assertTrue(src.f4 != dst.f4);
}
@Test
public void testFieldModifiers02() throws Exception {
FieldModifiersClass src = (FieldModifiersClass) PackUnpackUtil
.newEnhancedInstance(FieldModifiersClass.class);
src.f0 = 0;
src.f2 = 2;
src.f3 = 3;
src.f4 = 4;
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
Iterator<MessagePackObject> it = pac.iterator();
assertTrue(it.hasNext());
MessagePackObject mpo = it.next();
FieldModifiersClass dst = (FieldModifiersClass) PackUnpackUtil
.initEnhancedInstance(mpo, FieldModifiersClass.class);
assertTrue(src.f0 == dst.f0);
assertTrue(src.f1 == dst.f1);
assertTrue(src.f2 != dst.f2);
assertTrue(src.f3 == dst.f3);
assertTrue(src.f4 != dst.f4);
assertFalse(it.hasNext());
}
@MessagePackUnpackable
public static class FieldModifiersClass {
public int f0;
@ -385,7 +555,7 @@ public class TestMessagePackUnpackable extends TestCase {
}
@Test
public void testNestedAnnotatedFieldClass() throws Exception {
public void testNestedAnnotatedFieldClass01() throws Exception {
NestedClass src2 = (NestedClass) PackUnpackUtil
.newEnhancedInstance(NestedClass.class);
BaseClass src = (BaseClass) PackUnpackUtil
@ -395,11 +565,8 @@ public class TestMessagePackUnpackable extends TestCase {
src.f1 = src2;
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
NestedClass dst2 = (NestedClass) PackUnpackUtil
.newEnhancedInstance(NestedClass.class);
BaseClass dst = (BaseClass) PackUnpackUtil
.newEnhancedInstance(BaseClass.class);
dst.f1 = dst2;
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
pac.unpack((MessageUnpackable) dst);
@ -407,6 +574,29 @@ public class TestMessagePackUnpackable extends TestCase {
assertTrue(src2.f2 == dst.f1.f2);
}
@Test
public void testNestedAnnotatedFieldClass02() throws Exception {
NestedClass src2 = (NestedClass) PackUnpackUtil
.newEnhancedInstance(NestedClass.class);
BaseClass src = (BaseClass) PackUnpackUtil
.newEnhancedInstance(BaseClass.class);
src.f0 = 0;
src2.f2 = 2;
src.f1 = src2;
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
Iterator<MessagePackObject> it = pac.iterator();
assertTrue(it.hasNext());
MessagePackObject mpo = it.next();
BaseClass dst = (BaseClass) PackUnpackUtil.initEnhancedInstance(mpo,
BaseClass.class);
assertTrue(src.f0 == dst.f0);
assertTrue(src2.f2 == dst.f1.f2);
assertFalse(it.hasNext());
}
@MessagePackUnpackable
public static class BaseClass {
public int f0;
@ -425,7 +615,7 @@ public class TestMessagePackUnpackable extends TestCase {
}
@Test
public void testExtendedClass() throws Exception {
public void testExtendedClass01() throws Exception {
SampleSubClass src = (SampleSubClass) PackUnpackUtil
.newEnhancedInstance(SampleSubClass.class);
src.f0 = 0;
@ -453,6 +643,38 @@ public class TestMessagePackUnpackable extends TestCase {
assertTrue(src.f9 != dst.f9);
}
@Test
public void testExtendedClass02() throws Exception {
SampleSubClass src = (SampleSubClass) PackUnpackUtil
.newEnhancedInstance(SampleSubClass.class);
src.f0 = 0;
src.f2 = 2;
src.f3 = 3;
src.f4 = 4;
src.f5 = 5;
src.f8 = 8;
src.f9 = 9;
ByteArrayOutputStream out = new ByteArrayOutputStream();
new Packer(out).pack(src);
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
Unpacker pac = new Unpacker(in);
Iterator<MessagePackObject> it = pac.iterator();
assertTrue(it.hasNext());
MessagePackObject mpo = it.next();
SampleSubClass dst = (SampleSubClass) PackUnpackUtil
.initEnhancedInstance(mpo, SampleSubClass.class);
assertTrue(src.f0 == dst.f0);
assertTrue(src.f1 == dst.f1);
assertTrue(src.f2 != dst.f2);
assertTrue(src.f3 == dst.f3);
assertTrue(src.f4 != dst.f4);
assertTrue(src.f5 == dst.f5);
assertTrue(src.f6 == dst.f6);
assertTrue(src.f8 == dst.f8);
assertTrue(src.f9 != dst.f9);
assertFalse(it.hasNext());
}
@MessagePackUnpackable
public static class SampleSubClass extends SampleSuperClass {
public int f0;

View File

@ -1,20 +1,17 @@
package Data::MessagePack::PP;
use 5.008001;
use strict;
use warnings;
no warnings 'recursion';
use Carp ();
use B ();
# See also
# http://redmine.msgpack.org/projects/msgpack/wiki/FormatSpec
# http://cpansearch.perl.org/src/YAPPO/Data-Model-0.00006/lib/Data/Model/Driver/Memcached.pm
# http://frox25.no-ip.org/~mtve/wiki/MessagePack.html : reference to using CORE::pack, CORE::unpack
package
Data::MessagePack;
use strict;
use B ();
BEGIN {
my $unpack_int64_slow;
my $unpack_uint64_slow;
@ -120,6 +117,18 @@ BEGIN {
*unpack_int64 = $unpack_int64_slow || sub { return unpack( 'q>', substr( $_[0], $_[1], 8 ) ); };
*unpack_uint64 = $unpack_uint64_slow || sub { return unpack( 'Q>', substr( $_[0], $_[1], 8 ) ); };
}
# fixin package symbols
no warnings 'once';
sub pack :method;
sub unpack :method;
*Data::MessagePack::pack = \&pack;
*Data::MessagePack::unpack = \&unpack;
@Data::MessagePack::Unpacker::ISA = qw(Data::MessagePack::PP::Unpacker);
*true = \&Data::MessagePack::true;
*false = \&Data::MessagePack::false;
}
sub _unexpected {
@ -130,10 +139,7 @@ sub _unexpected {
# PACK
#
{
no warnings 'recursion';
our $_max_depth;
our $_max_depth;
sub pack :method {
Carp::croak('Usage: Data::MessagePack->pack($dat [,$max_depth])') if @_ < 2;
@ -238,20 +244,19 @@ sub _pack {
}
} # PACK
#
# UNPACK
#
{
my $p; # position variables for speed.
my $p; # position variables for speed.
sub unpack :method {
$p = 0; # init
_unpack( $_[1] );
my $data = _unpack( $_[1] );
if($p < length($_[1])) {
Carp::croak("Data::MessagePack->unpack: extra bytes");
}
return $data;
}
@ -383,17 +388,12 @@ sub _unpack {
}
} # UNPACK
#
# Data::MessagePack::Unpacker
#
package
Data::MessagePack::Unpacker;
use strict;
Data::MessagePack::PP::Unpacker;
sub new {
bless { pos => 0 }, shift;
@ -404,10 +404,6 @@ sub execute_limit {
execute( @_ );
}
{
my $p;
sub execute {
my ( $self, $data, $offset, $limit ) = @_;
$offset ||= 0;
@ -542,8 +538,6 @@ sub _count {
return 0;
}
} # execute
sub data {
return Data::MessagePack->unpack( substr($_[0]->{ data }, 0, $_[0]->{pos}) );

12
perl/t/13_booleans.t Executable file
View File

@ -0,0 +1,12 @@
#!perl -w
use strict;
use Test::More tests => 6;
use Data::MessagePack;
ok defined(Data::MessagePack::true()), 'true (1)';
ok defined(Data::MessagePack::true()), 'true (2)';
ok Data::MessagePack::true(), 'true is true';
ok defined(Data::MessagePack::false()), 'false (1)';
ok defined(Data::MessagePack::false()), 'false (2)';
ok !Data::MessagePack::false(), 'false is false';

18
perl/t/14_invalid_data.t Executable file
View File

@ -0,0 +1,18 @@
use strict;
use warnings;
use Data::MessagePack;
use Test::More;
use t::Util;
my $nil = Data::MessagePack->pack(undef);
my @data = do 't/data.pl';
while(my($dump, $data) = splice @data, 0, 2) {
my $s = Data::MessagePack->pack($data);
eval {
Data::MessagePack->unpack($s . $nil);
};
like $@, qr/extra bytes/, "dump $dump";
}
done_testing;

View File

@ -31,6 +31,7 @@ typedef struct {
#define msgpack_unpack_user unpack_user
void init_Data__MessagePack_unpack(pTHX_ bool const cloning) {
// booleans are load on demand (lazy load).
if(!cloning) {
MY_CXT_INIT;
MY_CXT.msgpack_true = NULL;
@ -52,11 +53,17 @@ static SV*
load_bool(pTHX_ const char* const name) {
CV* const cv = get_cv(name, GV_ADD);
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
call_sv((SV*)cv, G_SCALAR);
SPAGAIN;
SV* const sv = newSVsv(POPs);
PUTBACK;
FREETMPS;
LEAVE;
assert(sv);
assert(sv_isobject(sv));
return sv;
}