From d439b1495b744b0140da1ad2e890d820db3b4548 Mon Sep 17 00:00:00 2001 From: xanxys Date: Tue, 28 Dec 2010 19:19:49 +0900 Subject: [PATCH 01/53] haskell: add ObjectFloat to send floats, and Assoc to make map (un)packing explicit --- haskell/msgpack.cabal | 3 ++- haskell/src/Data/MessagePack.hs | 2 ++ haskell/src/Data/MessagePack/Assoc.hs | 28 ++++++++++++++++++++++++++ haskell/src/Data/MessagePack/Object.hs | 25 +++++++++++++++++------ haskell/src/Data/MessagePack/Pack.hs | 17 +++++++++++----- haskell/src/Data/MessagePack/Unpack.hs | 22 +++++++++++++------- haskell/test/Test.hs | 14 +++++++++---- 7 files changed, 88 insertions(+), 23 deletions(-) create mode 100644 haskell/src/Data/MessagePack/Assoc.hs diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index 98133a9e..ef56edc6 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -1,5 +1,5 @@ Name: msgpack -Version: 0.4.0.1 +Version: 0.5.0.0 Synopsis: A Haskell binding to MessagePack Description: A Haskell binding to MessagePack @@ -37,6 +37,7 @@ Library Exposed-modules: Data.MessagePack + Data.MessagePack.Assoc Data.MessagePack.Pack Data.MessagePack.Unpack Data.MessagePack.Object diff --git a/haskell/src/Data/MessagePack.hs b/haskell/src/Data/MessagePack.hs index b71190d6..1c77ca91 100644 --- a/haskell/src/Data/MessagePack.hs +++ b/haskell/src/Data/MessagePack.hs @@ -13,6 +13,7 @@ -------------------------------------------------------------------- module Data.MessagePack( + module Data.MessagePack.Assoc, module Data.MessagePack.Pack, module Data.MessagePack.Unpack, module Data.MessagePack.Object, @@ -44,6 +45,7 @@ import qualified Data.ByteString.Lazy as L import qualified Data.Iteratee as I import System.IO +import Data.MessagePack.Assoc import Data.MessagePack.Pack import Data.MessagePack.Unpack import Data.MessagePack.Object diff --git a/haskell/src/Data/MessagePack/Assoc.hs b/haskell/src/Data/MessagePack/Assoc.hs new file mode 100644 index 00000000..525cb77f --- /dev/null +++ b/haskell/src/Data/MessagePack/Assoc.hs @@ -0,0 +1,28 @@ +{-# Language DeriveDataTypeable #-} +{-# Language GeneralizedNewtypeDeriving #-} + +-------------------------------------------------------------------- +-- | +-- Module : Data.MessagePack.Assoc +-- Copyright : (c) Daiki Handa, 2010 +-- License : BSD3 +-- +-- Maintainer: tanaka.hideyuki@gmail.com +-- Stability : experimental +-- Portability: portable +-- +-- MessagePack map labeling type +-- +-------------------------------------------------------------------- + +module Data.MessagePack.Assoc ( + Assoc(..) + ) where + +import Control.DeepSeq +import Data.Typeable + +-- not defined for general Functor for performance reason. +-- (ie. you would want to write custom instances for each type using specialized mapM-like functions) +newtype Assoc a=Assoc{unAssoc :: a} deriving(Show,Eq,Ord,Typeable,NFData) + diff --git a/haskell/src/Data/MessagePack/Object.hs b/haskell/src/Data/MessagePack/Object.hs index 5111ebb6..421b05e2 100644 --- a/haskell/src/Data/MessagePack/Object.hs +++ b/haskell/src/Data/MessagePack/Object.hs @@ -1,6 +1,5 @@ {-# Language TypeSynonymInstances #-} {-# Language FlexibleInstances #-} -{-# Language OverlappingInstances #-} {-# Language IncoherentInstances #-} {-# Language DeriveDataTypeable #-} @@ -36,19 +35,22 @@ import qualified Data.ByteString as B import qualified Data.ByteString.Char8 as C8 import Data.Typeable +import Data.MessagePack.Assoc import Data.MessagePack.Pack import Data.MessagePack.Unpack -- | Object Representation of MessagePack data. -data Object = - ObjectNil +data Object + = ObjectNil | ObjectBool Bool | ObjectInteger Int + | ObjectFloat Float | ObjectDouble Double | ObjectRAW B.ByteString | ObjectArray [Object] | ObjectMap [(Object, Object)] deriving (Show, Eq, Ord, Typeable) + instance NFData Object where rnf obj = @@ -56,17 +58,20 @@ instance NFData Object where ObjectNil -> () ObjectBool b -> rnf b ObjectInteger n -> rnf n + ObjectFloat f -> rnf f ObjectDouble d -> rnf d ObjectRAW bs -> bs `seq` () 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 ObjectFloat get , liftM ObjectDouble get , liftM ObjectRAW get , liftM ObjectArray get @@ -82,6 +87,8 @@ instance Packable Object where put () ObjectBool b -> put b + ObjectFloat f -> + put f ObjectDouble d -> put d ObjectRAW raw -> @@ -137,6 +144,11 @@ instance OBJECT Double where tryFromObject (ObjectDouble d) = Right d tryFromObject _ = tryFromObjectError +instance OBJECT Float where + toObject = ObjectFloat + tryFromObject (ObjectFloat f) = Right f + tryFromObject _ = tryFromObjectError + instance OBJECT B.ByteString where toObject = ObjectRAW tryFromObject (ObjectRAW bs) = Right bs @@ -285,11 +297,11 @@ instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5, OBJECT a6, OBJE tryFromObject _ = tryFromObjectError -instance (OBJECT a, OBJECT b) => OBJECT [(a, b)] where +instance (OBJECT a, OBJECT b) => OBJECT (Assoc [(a,b)]) where toObject = - ObjectMap . map (\(a, b) -> (toObject a, toObject b)) + ObjectMap . map (\(a, b) -> (toObject a, toObject b)) . unAssoc tryFromObject (ObjectMap mem) = do - mapM (\(a, b) -> liftM2 (,) (tryFromObject a) (tryFromObject b)) mem + liftM Assoc $ mapM (\(a, b) -> liftM2 (,) (tryFromObject a) (tryFromObject b)) mem tryFromObject _ = tryFromObjectError @@ -299,3 +311,4 @@ instance OBJECT a => OBJECT (Maybe a) where tryFromObject ObjectNil = return Nothing tryFromObject obj = liftM Just $ tryFromObject obj + diff --git a/haskell/src/Data/MessagePack/Pack.hs b/haskell/src/Data/MessagePack/Pack.hs index 16243ad9..e943765a 100644 --- a/haskell/src/Data/MessagePack/Pack.hs +++ b/haskell/src/Data/MessagePack/Pack.hs @@ -1,6 +1,5 @@ {-# Language FlexibleInstances #-} {-# Language IncoherentInstances #-} -{-# Language OverlappingInstances #-} {-# Language TypeSynonymInstances #-} -------------------------------------------------------------------- @@ -32,6 +31,8 @@ import qualified Data.ByteString.Char8 as B8 import qualified Data.ByteString.Lazy as L import qualified Data.Vector as V +import Data.MessagePack.Assoc + -- | Serializable class class Packable a where -- | Serialize a value @@ -81,6 +82,11 @@ instance Packable Bool where put True = putWord8 0xC3 put False = putWord8 0xC2 +instance Packable Float where + put f = do + putWord8 0xCA + putFloat32be f + instance Packable Double where put d = do putWord8 0xCB @@ -159,11 +165,11 @@ putArray lf pf arr = do putWord32be $ fromIntegral len pf arr -instance (Packable k, Packable v) => Packable [(k, v)] where - put = putMap length (mapM_ putPair) +instance (Packable k, Packable v) => Packable (Assoc [(k,v)]) where + put = putMap length (mapM_ putPair) . unAssoc -instance (Packable k, Packable v) => Packable (V.Vector (k, v)) where - put = putMap V.length (V.mapM_ putPair) +instance (Packable k, Packable v) => Packable (Assoc (V.Vector (k,v))) where + put = putMap V.length (V.mapM_ putPair) . unAssoc putPair :: (Packable a, Packable b) => (a, b) -> Put putPair (a, b) = put a >> put b @@ -184,3 +190,4 @@ putMap lf pf m = do instance Packable a => Packable (Maybe a) where put Nothing = put () put (Just a) = put a + diff --git a/haskell/src/Data/MessagePack/Unpack.hs b/haskell/src/Data/MessagePack/Unpack.hs index a0d618ec..20deafad 100644 --- a/haskell/src/Data/MessagePack/Unpack.hs +++ b/haskell/src/Data/MessagePack/Unpack.hs @@ -1,6 +1,5 @@ {-# Language FlexibleInstances #-} {-# Language IncoherentInstances #-} -{-# Language OverlappingInstances #-} {-# Language TypeSynonymInstances #-} {-# Language DeriveDataTypeable #-} @@ -45,6 +44,8 @@ import qualified Data.Vector as V import Data.Word import Text.Printf +import Data.MessagePack.Assoc + -- | Deserializable class class Unpackable a where -- | Deserialize a value @@ -133,12 +134,19 @@ instance Unpackable Bool where _ -> fail $ printf "invlid bool tag: 0x%02X" c -instance Unpackable Double where +instance Unpackable Float where get = do c <- A.anyWord8 case c of 0xCA -> - return . realToFrac . runGet getFloat32be . toLBS =<< A.take 4 + return . runGet getFloat32be . toLBS =<< A.take 4 + _ -> + fail $ printf "invlid float tag: 0x%02X" c + +instance Unpackable Double where + get = do + c <- A.anyWord8 + case c of 0xCB -> return . runGet getFloat64be . toLBS =<< A.take 8 _ -> @@ -225,11 +233,11 @@ parseArray aget = do _ -> fail $ printf "invlid array tag: 0x%02X" c -instance (Unpackable k, Unpackable v) => Unpackable [(k, v)] where - get = parseMap (flip replicateM parsePair) +instance (Unpackable k, Unpackable v) => Unpackable (Assoc [(k,v)]) where + get = liftM Assoc $ parseMap (flip replicateM parsePair) -instance (Unpackable k, Unpackable v) => Unpackable (V.Vector (k, v)) where - get = parseMap (flip V.replicateM parsePair) +instance (Unpackable k, Unpackable v) => Unpackable (Assoc (V.Vector (k, v))) where + get = liftM Assoc $ parseMap (flip V.replicateM parsePair) parsePair :: (Unpackable k, Unpackable v) => A.Parser (k, v) parsePair = do diff --git a/haskell/test/Test.hs b/haskell/test/Test.hs index 43af2efc..d3089634 100644 --- a/haskell/test/Test.hs +++ b/haskell/test/Test.hs @@ -7,6 +7,9 @@ import qualified Data.ByteString.Char8 as B import qualified Data.ByteString.Lazy.Char8 as L import Data.MessagePack +instance Arbitrary a => Arbitrary (Assoc a) where + arbitrary = liftM Assoc arbitrary + mid :: (Packable a, Unpackable a) => a -> a mid = unpack . pack @@ -36,10 +39,12 @@ prop_mid_pair4 a = a == mid a where types = a :: (Int, Int, Int, Int) prop_mid_pair5 a = a == mid a where types = a :: (Int, Int, Int, Int, Int) -prop_mid_map_int_double a = a == mid a +prop_mid_list_int_double a = a == mid a where types = a :: [(Int, Double)] -prop_mid_map_string_string a = a == mid a +prop_mid_list_string_string a = a == mid a where types = a :: [(String, String)] +prop_mid_map_string_int a = a == mid a + where types = a :: Assoc [(String,Int)] tests = [ testGroup "simple" @@ -56,8 +61,9 @@ tests = , testProperty "(int, int, int)" prop_mid_pair3 , testProperty "(int, int, int, int)" prop_mid_pair4 , testProperty "(int, int, int, int, int)" prop_mid_pair5 - , testProperty "[(int, double)]" prop_mid_map_int_double - , testProperty "[(string, string)]" prop_mid_map_string_string + , testProperty "[(int, double)]" prop_mid_list_int_double + , testProperty "[(string, string)]" prop_mid_list_string_string + , testProperty "Assoc [(string, int)]" prop_mid_map_string_int ] ] From 5b1851ae22fdec09e8c69b7d1350541116500566 Mon Sep 17 00:00:00 2001 From: FURUHASHI Sadayuki Date: Thu, 24 Feb 2011 00:35:00 +0900 Subject: [PATCH 02/53] cpp: version 0.5.5 --- cpp/ChangeLog | 6 ++++++ cpp/configure.in | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cpp/ChangeLog b/cpp/ChangeLog index 71c7d5bf..6d7f486d 100644 --- a/cpp/ChangeLog +++ b/cpp/ChangeLog @@ -1,4 +1,10 @@ +2011-02-24 version 0.5.5: + + * eliminates dependency of winsock2.h header + * fixes msgpack_vc.postbuild.bat file + * fixes some implicit cast warnings + 2010-08-29 version 0.5.4: * includes msgpack_vc2008.vcproj file in source package diff --git a/cpp/configure.in b/cpp/configure.in index 23d7d6ee..f017b7cf 100644 --- a/cpp/configure.in +++ b/cpp/configure.in @@ -1,6 +1,6 @@ AC_INIT(src/object.cpp) AC_CONFIG_AUX_DIR(ac) -AM_INIT_AUTOMAKE(msgpack, 0.5.4) +AM_INIT_AUTOMAKE(msgpack, 0.5.5) AC_CONFIG_HEADER(config.h) AC_SUBST(CFLAGS) From 0b810683686427754025221c3431beccab5d178d Mon Sep 17 00:00:00 2001 From: Yuto Hayamizu Date: Thu, 3 Mar 2011 06:27:31 +0900 Subject: [PATCH 03/53] /cpp/preprocess: fix string comp. operator --- cpp/preprocess | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/preprocess b/cpp/preprocess index e51c61cf..17e8a05c 100755 --- a/cpp/preprocess +++ b/cpp/preprocess @@ -12,7 +12,7 @@ preprocess() { fi } -if [ "$1" == "clean" ];then +if [ "$1" = "clean" ];then rm -f src/msgpack/type/tuple.hpp rm -f src/msgpack/type/define.hpp rm -f src/msgpack/zone.hpp From 6990fe6f51c194db4619fd970b5588fadf34de7a Mon Sep 17 00:00:00 2001 From: Yuto Hayamizu Date: Thu, 3 Mar 2011 06:38:09 +0900 Subject: [PATCH 04/53] remove duplicated code --- cpp/src/msgpack/pack.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/cpp/src/msgpack/pack.h b/cpp/src/msgpack/pack.h index c1564963..f86e9299 100644 --- a/cpp/src/msgpack/pack.h +++ b/cpp/src/msgpack/pack.h @@ -105,9 +105,6 @@ int msgpack_pack_object(msgpack_packer* pk, msgpack_object d); #define msgpack_pack_inline_func_cint(name) \ inline int msgpack_pack ## name -#define msgpack_pack_inline_func_cint(name) \ - inline int msgpack_pack ## name - #define msgpack_pack_inline_func_fixint(name) \ inline int msgpack_pack_fix ## name From 5d3287f5aa3818272fe4a0e7af8cbe1e610a387d Mon Sep 17 00:00:00 2001 From: Yuto Hayamizu Date: Thu, 3 Mar 2011 06:42:14 +0900 Subject: [PATCH 05/53] gtest requires pthread --- cpp/test/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/test/Makefile.am b/cpp/test/Makefile.am index 5225f28b..5aeb8f19 100644 --- a/cpp/test/Makefile.am +++ b/cpp/test/Makefile.am @@ -1,7 +1,7 @@ AM_CPPFLAGS = -I../src AM_C_CPPFLAGS = -I../src -AM_LDFLAGS = ../src/libmsgpack.la -lgtest_main +AM_LDFLAGS = ../src/libmsgpack.la -lgtest_main -pthread check_PROGRAMS = \ zone \ From 80fd8e70f076bd10f1d7d36b77014ef76b247698 Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Wed, 9 Mar 2011 17:02:01 +0900 Subject: [PATCH 06/53] update library version. --- haskell/msgpack.cabal | 10 +++++----- haskell/src/Data/MessagePack/Iteratee.hs | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index ef56edc6..f2771ef3 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -21,16 +21,16 @@ Extra-source-files: Library Build-depends: base >=4 && <5, - transformers >= 0.2.1 && < 0.2.2, + transformers >= 0.2 && < 0.3, MonadCatchIO-transformers >= 0.2.2 && < 0.2.3, bytestring >= 0.9 && < 0.10, - vector >= 0.6.0 && < 0.6.1, - iteratee >= 0.4 && < 0.5, - attoparsec >= 0.8.1 && < 0.8.2, + vector >= 0.7 && < 0.8, + iteratee >= 0.8 && < 0.9, + attoparsec >= 0.8 && < 0.9, binary >= 0.5.0 && < 0.5.1, data-binary-ieee754 >= 0.4 && < 0.5, deepseq >= 1.1 && <1.2, - template-haskell >= 2.4 && < 2.5 + template-haskell >= 2.5 && < 2.6 Ghc-options: -Wall Hs-source-dirs: src diff --git a/haskell/src/Data/MessagePack/Iteratee.hs b/haskell/src/Data/MessagePack/Iteratee.hs index 6bc08980..553e2d17 100644 --- a/haskell/src/Data/MessagePack/Iteratee.hs +++ b/haskell/src/Data/MessagePack/Iteratee.hs @@ -37,18 +37,18 @@ getI = parserToIteratee get -- | Enumerator enumHandleNonBlocking :: MonadIO m => Int -> Handle -> I.Enumerator B.ByteString m a enumHandleNonBlocking bufSize h = - I.enumFromCallback $ readSome bufSize h + I.enumFromCallback (readSome bufSize h) () -readSome :: MonadIO m => Int -> Handle -> m (Either SomeException (Bool, B.ByteString)) -readSome bufSize h = liftIO $ do +readSome :: MonadIO m => Int -> Handle -> st -> m (Either SomeException ((Bool, st), B.ByteString)) +readSome bufSize h st = liftIO $ do ebs <- try $ hGetSome bufSize h case ebs of Left exc -> return $ Left (exc :: SomeException) Right bs | B.null bs -> - return $ Right (False, B.empty) + return $ Right ((False, st), B.empty) Right bs -> - return $ Right (True, bs) + return $ Right ((True, st), bs) hGetSome :: Int -> Handle -> IO B.ByteString hGetSome bufSize h = do From 83f1735fbbdb623ef6fb41d8e275b93207232459 Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Wed, 9 Mar 2011 18:05:04 +0900 Subject: [PATCH 07/53] fix description --- haskell/msgpack.cabal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index f2771ef3..ba305296 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -1,8 +1,8 @@ Name: msgpack Version: 0.5.0.0 -Synopsis: A Haskell binding to MessagePack +Synopsis: A Haskell implementation of MessagePack Description: - A Haskell binding to MessagePack + A Haskell implementation of MessagePack License: BSD3 License-File: LICENSE From 7201fcbe0f7bdd6fc218677e6600a8d430d6744e Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Thu, 10 Mar 2011 22:17:15 +0900 Subject: [PATCH 08/53] remove Iteratee dependency --- haskell/msgpack.cabal | 7 +- haskell/src/Data/MessagePack.hs | 78 ---------------------- haskell/src/Data/MessagePack/Iteratee.hs | 82 ------------------------ 3 files changed, 2 insertions(+), 165 deletions(-) delete mode 100644 haskell/src/Data/MessagePack/Iteratee.hs diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index ba305296..8d91b151 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -1,12 +1,12 @@ Name: msgpack -Version: 0.5.0.0 +Version: 0.6.0.0 Synopsis: A Haskell implementation of MessagePack Description: A Haskell implementation of MessagePack License: BSD3 License-File: LICENSE -Copyright: Copyright (c) 2009-2010, Hideyuki Tanaka +Copyright: Copyright (c) 2009-2011, Hideyuki Tanaka Category: Data Author: Hideyuki Tanaka Maintainer: Hideyuki Tanaka @@ -22,10 +22,8 @@ Extra-source-files: Library Build-depends: base >=4 && <5, transformers >= 0.2 && < 0.3, - MonadCatchIO-transformers >= 0.2.2 && < 0.2.3, bytestring >= 0.9 && < 0.10, vector >= 0.7 && < 0.8, - iteratee >= 0.8 && < 0.9, attoparsec >= 0.8 && < 0.9, binary >= 0.5.0 && < 0.5.1, data-binary-ieee754 >= 0.4 && < 0.5, @@ -41,7 +39,6 @@ Library Data.MessagePack.Pack Data.MessagePack.Unpack Data.MessagePack.Object - Data.MessagePack.Iteratee Data.MessagePack.Derive Source-repository head diff --git a/haskell/src/Data/MessagePack.hs b/haskell/src/Data/MessagePack.hs index 1c77ca91..801c2738 100644 --- a/haskell/src/Data/MessagePack.hs +++ b/haskell/src/Data/MessagePack.hs @@ -17,89 +17,11 @@ module Data.MessagePack( module Data.MessagePack.Pack, module Data.MessagePack.Unpack, module Data.MessagePack.Object, - module Data.MessagePack.Iteratee, module Data.MessagePack.Derive, - - -- * Pack functions - packToString, - packToHandle, - packToHandle', - packToFile, - - -- * Unpack functions - unpackFromString, - unpackFromHandle, - unpackFromFile, - unpackFromStringI, - unpackFromHandleI, - unpackFromFileI, - ) where -import qualified Control.Monad.CatchIO as CIO -import Control.Monad.IO.Class -import qualified Data.Attoparsec as A -import Data.Binary.Put -import qualified Data.ByteString as B -import qualified Data.ByteString.Lazy as L -import qualified Data.Iteratee as I -import System.IO - import Data.MessagePack.Assoc import Data.MessagePack.Pack import Data.MessagePack.Unpack import Data.MessagePack.Object -import Data.MessagePack.Iteratee import Data.MessagePack.Derive - -bufferSize :: Int -bufferSize = 4 * 1024 - --- | Pack to ByteString. -packToString :: Put -> L.ByteString -packToString = runPut - --- | Pack to Handle -packToHandle :: Handle -> Put -> IO () -packToHandle h = L.hPutStr h . packToString - --- | Pack to Handle and Flush Handle -packToHandle' :: Handle -> Put -> IO () -packToHandle' h p = packToHandle h p >> hFlush h - --- | Pack to File -packToFile :: FilePath -> Put -> IO () -packToFile path = L.writeFile path . packToString - --- | Unpack from ByteString -unpackFromString :: (Monad m, IsByteString s) => s -> A.Parser a -> m a -unpackFromString bs = - unpackFromStringI bs . parserToIteratee - --- | Unpack from Handle -unpackFromHandle :: CIO.MonadCatchIO m => Handle -> A.Parser a -> m a -unpackFromHandle h = - unpackFromHandleI h .parserToIteratee - --- | Unpack from File -unpackFromFile :: CIO.MonadCatchIO m => FilePath -> A.Parser a -> m a -unpackFromFile path = - unpackFromFileI path . parserToIteratee - --- | Iteratee interface to unpack from ByteString -unpackFromStringI :: (Monad m, IsByteString s) => s -> I.Iteratee B.ByteString m a -> m a -unpackFromStringI bs = - I.run . I.joinIM . I.enumPure1Chunk (toBS bs) - --- | Iteratee interface to unpack from Handle -unpackFromHandleI :: CIO.MonadCatchIO m => Handle -> I.Iteratee B.ByteString m a -> m a -unpackFromHandleI h = - I.run . I.joinIM . enumHandleNonBlocking bufferSize h - --- | Iteratee interface to unpack from File -unpackFromFileI :: CIO.MonadCatchIO m => FilePath -> I.Iteratee B.ByteString m a -> m a -unpackFromFileI path p = - CIO.bracket - (liftIO $ openBinaryFile path ReadMode) - (liftIO . hClose) - (flip unpackFromHandleI p) diff --git a/haskell/src/Data/MessagePack/Iteratee.hs b/haskell/src/Data/MessagePack/Iteratee.hs deleted file mode 100644 index 553e2d17..00000000 --- a/haskell/src/Data/MessagePack/Iteratee.hs +++ /dev/null @@ -1,82 +0,0 @@ --------------------------------------------------------------------- --- | --- Module : Data.MessagePack.Iteratee --- Copyright : (c) Hideyuki Tanaka, 2009-2010 --- License : BSD3 --- --- Maintainer: tanaka.hideyuki@gmail.com --- Stability : experimental --- Portability: portable --- --- MessagePack Deserializer interface to @Data.Iteratee@ --- --------------------------------------------------------------------- - -module Data.MessagePack.Iteratee( - -- * Iteratee version of deserializer - getI, - -- * Non Blocking Enumerator - enumHandleNonBlocking, - -- * Convert Parser to Iteratee - parserToIteratee, - ) where - -import Control.Exception -import Control.Monad.IO.Class -import qualified Data.Attoparsec as A -import qualified Data.ByteString as B -import qualified Data.Iteratee as I -import System.IO - -import Data.MessagePack.Unpack - --- | Deserialize a value -getI :: (Monad m, Unpackable a) => I.Iteratee B.ByteString m a -getI = parserToIteratee get - --- | Enumerator -enumHandleNonBlocking :: MonadIO m => Int -> Handle -> I.Enumerator B.ByteString m a -enumHandleNonBlocking bufSize h = - I.enumFromCallback (readSome bufSize h) () - -readSome :: MonadIO m => Int -> Handle -> st -> m (Either SomeException ((Bool, st), B.ByteString)) -readSome bufSize h st = liftIO $ do - ebs <- try $ hGetSome bufSize h - case ebs of - Left exc -> - return $ Left (exc :: SomeException) - Right bs | B.null bs -> - return $ Right ((False, st), B.empty) - Right bs -> - return $ Right ((True, st), bs) - -hGetSome :: Int -> Handle -> IO B.ByteString -hGetSome bufSize h = do - bs <- B.hGetNonBlocking h bufSize - if B.null bs - then do - hd <- B.hGet h 1 - if B.null hd - then do - return B.empty - else do - rest <- B.hGetNonBlocking h (bufSize - 1) - return $ B.cons (B.head hd) rest - else do - return bs - --- | Convert Parser to Iteratee -parserToIteratee :: Monad m => A.Parser a -> I.Iteratee B.ByteString m a -parserToIteratee p = I.icont (itr (A.parse p)) Nothing - where - itr pcont s = case s of - I.EOF _ -> - I.throwErr (I.setEOF s) - I.Chunk bs -> - case pcont bs of - A.Fail _ _ msg -> - I.throwErr (I.iterStrExc msg) - A.Partial cont -> - I.icont (itr cont) Nothing - A.Done remain ret -> - I.idone ret (I.Chunk remain) From 86917b0ba7e4068ce3465de01167aa1fca547cea Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Fri, 11 Mar 2011 12:24:09 +0900 Subject: [PATCH 09/53] improved constructor in JavassistTemplateBuilder class. This improvement is based on https://github.com/msgpack/msgpack-rpc/issues#issue/13. --- .../template/JavassistTemplateBuilder.java | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java index 38bb998f..a4d2e4db 100644 --- a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java @@ -55,7 +55,30 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } private JavassistTemplateBuilder() { - this.pool = ClassPool.getDefault(); + pool = new ClassPool(); + boolean appended = false; + ClassLoader cl = null; + try { + Thread.currentThread().getContextClassLoader(); + if (cl != null) { + pool.appendClassPath(new LoaderClassPath(cl)); + appended = true; + } + } catch (SecurityException e) { + LOG.debug("Cannot append a search path of context classloader", e); + } + try { + ClassLoader cl2 = getClass().getClassLoader(); + if (cl2 != null && cl2 != cl) { + pool.appendClassPath(new LoaderClassPath(cl2)); + appended = true; + } + } catch (SecurityException e) { + LOG.debug("Cannot append a search path of classloader", e); + } + if (!appended) { + pool.appendSystemPath(); + } } protected ClassPool pool; From f50855d5c0744fb1e571b12fe3ee3c2accb9b034 Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Fri, 18 Mar 2011 00:44:15 +0900 Subject: [PATCH 10/53] fix for packing and unpacking Object --- haskell/src/Data/MessagePack/Object.hs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haskell/src/Data/MessagePack/Object.hs b/haskell/src/Data/MessagePack/Object.hs index 421b05e2..3eb36587 100644 --- a/haskell/src/Data/MessagePack/Object.hs +++ b/haskell/src/Data/MessagePack/Object.hs @@ -75,7 +75,7 @@ instance Unpackable Object where , liftM ObjectDouble get , liftM ObjectRAW get , liftM ObjectArray get - , liftM ObjectMap get + , liftM (ObjectMap . unAssoc) get ] instance Packable Object where @@ -96,7 +96,7 @@ instance Packable Object where ObjectArray arr -> put arr ObjectMap m -> - put m + put $ Assoc m -- | The class of types serializable to and from MessagePack object class (Unpackable a, Packable a) => OBJECT a where From 5c5f16f148b2c4c97bc93088fea2ae158edc6214 Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Fri, 18 Mar 2011 00:46:43 +0900 Subject: [PATCH 11/53] haskell: version bump --- haskell/msgpack.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index 8d91b151..3afafd42 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -1,5 +1,5 @@ Name: msgpack -Version: 0.6.0.0 +Version: 0.6.0.1 Synopsis: A Haskell implementation of MessagePack Description: A Haskell implementation of MessagePack From ace4f1e7f0fb832d1c52ee3f64d547328264b83f Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Tue, 29 Mar 2011 16:15:29 +0900 Subject: [PATCH 12/53] fix encoding unicode strings, and Text support --- haskell/msgpack.cabal | 4 +++ haskell/src/Data/MessagePack/Internal/Utf8.hs | 28 ++++++++++++++++ haskell/src/Data/MessagePack/Object.hs | 28 +++++++++++++--- haskell/src/Data/MessagePack/Pack.hs | 33 ++++++++++++------- haskell/src/Data/MessagePack/Unpack.hs | 27 +++++++++------ 5 files changed, 95 insertions(+), 25 deletions(-) create mode 100644 haskell/src/Data/MessagePack/Internal/Utf8.hs diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index 3afafd42..14b37671 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -23,6 +23,7 @@ Library Build-depends: base >=4 && <5, transformers >= 0.2 && < 0.3, bytestring >= 0.9 && < 0.10, + text >= 0.11 && < 0.12, vector >= 0.7 && < 0.8, attoparsec >= 0.8 && < 0.9, binary >= 0.5.0 && < 0.5.1, @@ -41,6 +42,9 @@ Library Data.MessagePack.Object Data.MessagePack.Derive + Other-modules: + Data.MessagePack.Internal.Utf8 + Source-repository head Type: git Location: git://github.com/msgpack/msgpack.git diff --git a/haskell/src/Data/MessagePack/Internal/Utf8.hs b/haskell/src/Data/MessagePack/Internal/Utf8.hs new file mode 100644 index 00000000..c109faaa --- /dev/null +++ b/haskell/src/Data/MessagePack/Internal/Utf8.hs @@ -0,0 +1,28 @@ +module Data.MessagePack.Internal.Utf8 ( + encodeUtf8, + decodeUtf8, + skipChar, + toLBS, + fromLBS, + ) where + +import qualified Data.ByteString as B +import qualified Data.ByteString.Lazy as BL +import qualified Data.Text as T +import qualified Data.Text.Encoding as T +import qualified Data.Text.Encoding.Error as T + +encodeUtf8 :: String -> B.ByteString +encodeUtf8 = T.encodeUtf8 . T.pack + +decodeUtf8 :: B.ByteString -> String +decodeUtf8 = T.unpack . T.decodeUtf8With skipChar + +skipChar :: T.OnDecodeError +skipChar _ _ = Nothing + +toLBS :: B.ByteString -> BL.ByteString +toLBS bs = BL.fromChunks [bs] + +fromLBS :: BL.ByteString -> B.ByteString +fromLBS = B.concat . BL.toChunks diff --git a/haskell/src/Data/MessagePack/Object.hs b/haskell/src/Data/MessagePack/Object.hs index 3eb36587..aaad669c 100644 --- a/haskell/src/Data/MessagePack/Object.hs +++ b/haskell/src/Data/MessagePack/Object.hs @@ -32,12 +32,17 @@ 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 qualified Data.ByteString.Lazy as BL +import qualified Data.Text as T +import qualified Data.Text.Encoding as T +import qualified Data.Text.Lazy as TL +import qualified Data.Text.Lazy.Encoding as TL import Data.Typeable import Data.MessagePack.Assoc import Data.MessagePack.Pack import Data.MessagePack.Unpack +import Data.MessagePack.Internal.Utf8 -- | Object Representation of MessagePack data. data Object @@ -149,14 +154,29 @@ instance OBJECT Float where tryFromObject (ObjectFloat f) = Right f tryFromObject _ = tryFromObjectError +instance OBJECT String where + toObject = toObject . encodeUtf8 + tryFromObject obj = liftM decodeUtf8 $ tryFromObject obj + instance OBJECT B.ByteString where toObject = ObjectRAW tryFromObject (ObjectRAW bs) = Right bs tryFromObject _ = tryFromObjectError -instance OBJECT String where - toObject = toObject . C8.pack - tryFromObject obj = liftM C8.unpack $ tryFromObject obj +instance OBJECT BL.ByteString where + toObject = ObjectRAW . fromLBS + tryFromObject (ObjectRAW bs) = Right $ toLBS bs + tryFromObject _ = tryFromObjectError + +instance OBJECT T.Text where + toObject = ObjectRAW . T.encodeUtf8 + tryFromObject (ObjectRAW bs) = Right $ T.decodeUtf8With skipChar bs + tryFromObject _ = tryFromObjectError + +instance OBJECT TL.Text where + toObject = ObjectRAW . fromLBS . TL.encodeUtf8 + tryFromObject (ObjectRAW bs) = Right $ TL.decodeUtf8With skipChar $ toLBS bs + tryFromObject _ = tryFromObjectError instance OBJECT a => OBJECT [a] where toObject = ObjectArray . map toObject diff --git a/haskell/src/Data/MessagePack/Pack.hs b/haskell/src/Data/MessagePack/Pack.hs index e943765a..39394ff6 100644 --- a/haskell/src/Data/MessagePack/Pack.hs +++ b/haskell/src/Data/MessagePack/Pack.hs @@ -27,11 +27,15 @@ import Data.Binary.Put import Data.Binary.IEEE754 import Data.Bits import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import qualified Data.ByteString.Lazy as L +import qualified Data.ByteString.Lazy as BL +import qualified Data.Text as T +import qualified Data.Text.Encoding as T +import qualified Data.Text.Lazy as TL +import qualified Data.Text.Lazy.Encoding as TL import qualified Data.Vector as V import Data.MessagePack.Assoc +import Data.MessagePack.Internal.Utf8 -- | Serializable class class Packable a where @@ -39,7 +43,7 @@ class Packable a where put :: a -> Put -- | Pack Haskell data to MessagePack string. -pack :: Packable a => a -> L.ByteString +pack :: Packable a => a -> BL.ByteString pack = runPut . put instance Packable Int where @@ -93,17 +97,24 @@ instance Packable Double where putFloat64be d instance Packable String where - put = putString length (putByteString . B8.pack) + put = putString encodeUtf8 B.length putByteString instance Packable B.ByteString where - put = putString B.length putByteString + put = putString id B.length putByteString -instance Packable L.ByteString where - put = putString (fromIntegral . L.length) putLazyByteString +instance Packable BL.ByteString where + put = putString id (fromIntegral . BL.length) putLazyByteString -putString :: (s -> Int) -> (s -> Put) -> s -> Put -putString lf pf str = do - case lf str of +instance Packable T.Text where + put = putString T.encodeUtf8 B.length putByteString + +instance Packable TL.Text where + put = putString TL.encodeUtf8 (fromIntegral . BL.length) putLazyByteString + +putString :: (s -> t) -> (t -> Int) -> (t -> Put) -> s -> Put +putString cnv lf pf str = do + let bs = cnv str + case lf bs of len | len <= 31 -> do putWord8 $ 0xA0 .|. fromIntegral len len | len < 0x10000 -> do @@ -112,7 +123,7 @@ putString lf pf str = do len -> do putWord8 0xDB putWord32be $ fromIntegral len - pf str + pf bs instance Packable a => Packable [a] where put = putArray length (mapM_ put) diff --git a/haskell/src/Data/MessagePack/Unpack.hs b/haskell/src/Data/MessagePack/Unpack.hs index 20deafad..66a61a22 100644 --- a/haskell/src/Data/MessagePack/Unpack.hs +++ b/haskell/src/Data/MessagePack/Unpack.hs @@ -36,8 +36,11 @@ import Data.Binary.Get import Data.Binary.IEEE754 import Data.Bits import qualified Data.ByteString as B -import qualified Data.ByteString.Char8 as B8 -import qualified Data.ByteString.Lazy as L +import qualified Data.ByteString.Lazy as BL +import qualified Data.Text as T +import qualified Data.Text.Encoding as T +import qualified Data.Text.Lazy as TL +import qualified Data.Text.Lazy.Encoding as TL import Data.Int import Data.Typeable import qualified Data.Vector as V @@ -45,6 +48,7 @@ import Data.Word import Text.Printf import Data.MessagePack.Assoc +import Data.MessagePack.Internal.Utf8 -- | Deserializable class class Unpackable a where @@ -57,8 +61,8 @@ class IsByteString s where instance IsByteString B.ByteString where toBS = id -instance IsByteString L.ByteString where - toBS = B.concat . L.toChunks +instance IsByteString BL.ByteString where + toBS = B.concat . BL.toChunks -- | The exception of unpack data UnpackError = @@ -153,13 +157,19 @@ instance Unpackable Double where fail $ printf "invlid double tag: 0x%02X" c instance Unpackable String where - get = parseString (\n -> return . B8.unpack =<< A.take n) + get = parseString (\n -> return . decodeUtf8 =<< A.take n) instance Unpackable B.ByteString where get = parseString A.take -instance Unpackable L.ByteString where - get = parseString (\n -> do bs <- A.take n; return $ L.fromChunks [bs]) +instance Unpackable BL.ByteString where + get = parseString (\n -> return . toLBS =<< A.take n) + +instance Unpackable T.Text where + get = parseString (\n -> return . T.decodeUtf8With skipChar =<< A.take n) + +instance Unpackable TL.Text where + get = parseString (\n -> return . TL.decodeUtf8With skipChar . toLBS =<< A.take n) parseString :: (Int -> A.Parser a) -> A.Parser a parseString aget = do @@ -311,6 +321,3 @@ parseInt32 = return . fromIntegral =<< parseUint32 parseInt64 :: A.Parser Int64 parseInt64 = return . fromIntegral =<< parseUint64 - -toLBS :: B.ByteString -> L.ByteString -toLBS bs = L.fromChunks [bs] From 324f215316a597fbd3766489b1f51b0d171a7221 Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Tue, 29 Mar 2011 16:17:46 +0900 Subject: [PATCH 13/53] haskell: version bump --- haskell/msgpack.cabal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index 14b37671..aef55f94 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -1,5 +1,5 @@ Name: msgpack -Version: 0.6.0.1 +Version: 0.6.1 Synopsis: A Haskell implementation of MessagePack Description: A Haskell implementation of MessagePack From 1b010a082b2e601961856d74bf76f638c31480f2 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Tue, 1 Jun 2010 10:53:19 +0900 Subject: [PATCH 14/53] Add go binding. --- go/Makefile | 11 + go/msgpack_test.go | 152 ++++++++++++ go/pack.go | 581 +++++++++++++++++++++++++++++++++++++++++++++ go/unpack.go | 203 ++++++++++++++++ 4 files changed, 947 insertions(+) create mode 100644 go/Makefile create mode 100644 go/msgpack_test.go create mode 100644 go/pack.go create mode 100644 go/unpack.go diff --git a/go/Makefile b/go/Makefile new file mode 100644 index 00000000..289bd122 --- /dev/null +++ b/go/Makefile @@ -0,0 +1,11 @@ +include $(GOROOT)/src/Make.$(GOARCH) + +TARG=msgpack + +GOFILES=pack.go unpack.go + +include $(GOROOT)/src/Make.pkg + +%: install %.go + $(GC) $*.go + $(LD) -o $@ $*.$O diff --git a/go/msgpack_test.go b/go/msgpack_test.go new file mode 100644 index 00000000..a5dda2a4 --- /dev/null +++ b/go/msgpack_test.go @@ -0,0 +1,152 @@ +package msgpack_test + +import ( + . "msgpack" + "testing" + "bytes" + "reflect" +); + +func TestPackUint8(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint8 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255 } { + _, err := PackUint8(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackUint16(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint16 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255, 256, 65533, 65534, 65535 } { + _, err := PackUint16(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xcd, 0x01, 0x00, 0xcd, 0xff, 0xfd, 0xcd, 0xff, 0xfe, 0xcd, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackUint32(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint32 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255, 256, 65533, 65534, 65535, 65536, 4294967293, 4294967294, 4294967295 } { + _, err := PackUint32(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xcd, 0x01, 0x00, 0xcd, 0xff, 0xfd, 0xcd, 0xff, 0xfe, 0xcd, 0xff, 0xff, 0xce, 0x00, 0x01, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0xfd, 0xce, 0xff, 0xff, 0xff, 0xfe, 0xce, 0xff, 0xff, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackUint64(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint64 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255, 256, 65533, 65534, 65535, 65536, 4294967293, 4294967294, 4294967295, 4294967296, 18446744073709551613, 18446744073709551614, 18446744073709551615 } { + _, err := PackUint64(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xcd, 0x01, 0x00, 0xcd, 0xff, 0xfd, 0xcd, 0xff, 0xfe, 0xcd, 0xff, 0xff, 0xce, 0x00, 0x01, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0xfd, 0xce, 0xff, 0xff, 0xff, 0xfe, 0xce, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt8(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int8 { -128, -127, -34, -33, -32, -31, 0, 1, 126, 127 } { + _, err := PackInt8(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt16(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int16 { -32768, -32767, -131, -130, -129, -128, -127, -34, -33, -32, -31, 0, 1, 126, 127, 128, 129, 130, 32765, 32766, 32767 } { + _, err := PackInt16(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd1, 0x80, 0x00, 0xd1, 0x80, 0x01, 0xd1, 0xff, 0x7d, 0xd1, 0xff, 0x7e, 0xd1, 0xff, 0x7f, 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f, 0xd1, 0x00, 0x80, 0xd1, 0x00, 0x81, 0xd1, 0x00, 0x82, 0xd1, 0x7f, 0xfd, 0xd1, 0x7f, 0xfe, 0xd1, 0x7f, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt32(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int32 { -2147483648, -2147483647, -2147483646, -32771, -32770, -32769, -32768, -32767, -131, -130, -129, -128, -127, -34, -33, -32, -31, 0, 1, 126, 127, 128, 129, 130, 32765, 32766, 32767, 32768, 32769, 32770, 2147483645, 2147483646, 2147483647 } { + _, err := PackInt32(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd2, 0x80, 0x00, 0x00, 0x00, 0xd2, 0x80, 0x00, 0x00, 0x01, 0xd2, 0x80, 0x00, 0x00, 0x02, 0xd2, 0xff, 0xff, 0x7f, 0xfd, 0xd2, 0xff, 0xff, 0x7f, 0xfe, 0xd2, 0xff, 0xff, 0x7f, 0xff, 0xd1, 0x80, 0x00, 0xd1, 0x80, 0x01, 0xd1, 0xff, 0x7d, 0xd1, 0xff, 0x7e, 0xd1, 0xff, 0x7f, 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f, 0xd1, 0x00, 0x80, 0xd1, 0x00, 0x81, 0xd1, 0x00, 0x82, 0xd1, 0x7f, 0xfd, 0xd1, 0x7f, 0xfe, 0xd1, 0x7f, 0xff, 0xd2, 0x00, 0x00, 0x80, 0x00, 0xd2, 0x00, 0x00, 0x80, 0x01, 0xd2, 0x00, 0x00, 0x80, 0x02, 0xd2, 0x7f, 0xff, 0xff, 0xfd, 0xd2, 0x7f, 0xff, 0xff, 0xfe, 0xd2, 0x7f, 0xff, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt64(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int64 { -9223372036854775808, -9223372036854775807, -9223372036854775806, -2147483651, -2147483650, -2147483649, -2147483648, -2147483647, -2147483646, -32771, -32770, -32769, -32768, -32767, -131, -130, -129, -128, -127, -34, -33, -32, -31, 0, 1, 126, 127, 128, 129, 130, 32765, 32766, 32767, 32768, 32769, 32770, 2147483645, 2147483646, 2147483647, 2147483648, 2147483649, 2147483650, 4294967296, 4294967297, 4294967298 } { + _, err := PackInt64(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfd, 0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfe, 0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xd2, 0x80, 0x00, 0x00, 0x00, 0xd2, 0x80, 0x00, 0x00, 0x01, 0xd2, 0x80, 0x00, 0x00, 0x02, 0xd2, 0xff, 0xff, 0x7f, 0xfd, 0xd2, 0xff, 0xff, 0x7f, 0xfe, 0xd2, 0xff, 0xff, 0x7f, 0xff, 0xd1, 0x80, 0x00, 0xd1, 0x80, 0x01, 0xd1, 0xff, 0x7d, 0xd1, 0xff, 0x7e, 0xd1, 0xff, 0x7f, 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f, 0xd1, 0x00, 0x80, 0xd1, 0x00, 0x81, 0xd1, 0x00, 0x82, 0xd1, 0x7f, 0xfd, 0xd1, 0x7f, 0xfe, 0xd1, 0x7f, 0xff, 0xd2, 0x00, 0x00, 0x80, 0x00, 0xd2, 0x00, 0x00, 0x80, 0x01, 0xd2, 0x00, 0x00, 0x80, 0x02, 0xd2, 0x7f, 0xff, 0xff, 0xfd, 0xd2, 0x7f, 0xff, 0xff, 0xfe, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x02, 0xd3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackNil(t *testing.T) { + b := &bytes.Buffer{} + nbyteswrite, err := PackNil(b) + if nbyteswrite != 1 { t.Error("nbyteswrite != 1") } + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0xc0 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackBool(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []bool { false, true } { + nbyteswrite, err := PackBool(b, i) + if nbyteswrite != 1 { t.Error("nbyteswrite != 1") } + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xc2, 0xc3 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt32Array(t *testing.T) { + b := &bytes.Buffer{} + _, err := PackInt32Array(b, []int32 {}) + if err != nil { t.Error("err != nil") } + _, err = PackInt32Array(b, []int32 { 0 }) + if err != nil { t.Error("err != nil") } + _, err = PackInt32Array(b, []int32 { 0, 1 }) + if err != nil { t.Error("err != nil") } + _, err = PackInt32Array(b, []int32 { 0, 1, 2 }) + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0x90, 0x91, 0x00, 0x92, 0x00, 0x01, 0x93, 0x00, 0x01, 0x02 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackArray(t *testing.T) { + b := &bytes.Buffer{} + _, err := PackArray(b, reflect.NewValue([]int32 {}).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + _, err = PackArray(b, reflect.NewValue([]int32 { 0 }).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + _, err = PackArray(b, reflect.NewValue([]int32 { 0, 1 }).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + _, err = PackArray(b, reflect.NewValue([]int32 { 0, 1, 2 }).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0x90, 0x91, 0x00, 0x92, 0x00, 0x01, 0x93, 0x00, 0x01, 0x02 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackMap(t *testing.T) { + b := &bytes.Buffer{} + _, err := PackMap(b, reflect.NewValue(map[int] int { 0: 1, 2: 3, 4: 5 }).(*reflect.MapValue)) + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0x83, 0x00, 0x01, 0x04, 0x05, 0x02, 0x03 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPack(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range [](interface{}) { nil, false, true, 0, 1, 2, 3, 127, -32, -1, -33, 128 } { + _, err := Pack(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xc0, 0xc2, 0xc3, 0x00, 0x01, 0x02, 0x03, 0x7f, 0xf0, 0xff, 0xd0, 0xef, 0xd1, 0x00, 0x80 }) == 0 { t.Error("wrong output") } +} + +func TestUnpack(t *testing.T) { + b := bytes.NewBuffer([]byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) + for _, v := range [](interface{}) { + int8(0), int8(1), int8(2), int8(125), int8(126), int8(127), + uint8(128), uint8(253), uint8(254), uint8(255), int32(2147483647), + int64(9223372036854775807) } { + retval, _, e := Unpack(b) + if e != nil { t.Error("err != nil") } + if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } + } +} diff --git a/go/pack.go b/go/pack.go new file mode 100644 index 00000000..8240394c --- /dev/null +++ b/go/pack.go @@ -0,0 +1,581 @@ +package msgpack + +import ( + "io" + "os" + "unsafe" + "reflect" +); + +func PackUint8(writer io.Writer, value uint8) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } + return writer.Write([]byte { 0xcc, byte(value) }) +} + +func PackUint16(writer io.Writer, value uint16) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } else if value < 256 { + return writer.Write([]byte { 0xcc, byte(value) }) + } + return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) +} + +func PackUint32(writer io.Writer, value uint32) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } else if value < 256 { + return writer.Write([]byte { 0xcc, byte(value) }) + } else if value < 65536 { + return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) + } + return writer.Write([]byte { 0xce, byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) +} + +func PackUint64(writer io.Writer, value uint64) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } else if value < 256 { + return writer.Write([]byte { 0xcc, byte(value) }) + } else if value < 65536 { + return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) + } else if value < 4294967296 { + return writer.Write([]byte { 0xce, byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) + } + return writer.Write([]byte { 0xcf, byte(value >> 56), byte(value >> 48), byte(value >> 40), byte(value >> 32), byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) +} + +func PackUint(writer io.Writer, value uint) (n int, err os.Error) { + switch unsafe.Sizeof(value) { + case 4: + return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) + case 8: + return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + + +func PackInt8(writer io.Writer, value int8) (n int, err os.Error) { + if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt16(writer io.Writer, value int16) (n int, err os.Error) { + if value < -128 || value >= 128 { + return writer.Write([]byte { 0xd1, byte(uint16(value) >> 8), byte(value) }) + } else if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt32(writer io.Writer, value int32) (n int, err os.Error) { + if value < -32768 || value >= 32768 { + return writer.Write([]byte { 0xd2, byte(uint32(value) >> 24), byte(uint32(value) >> 16), byte(uint32(value) >> 8), byte(value) }) + } else if value < -128 { + return writer.Write([]byte { 0xd1, byte(uint32(value) >> 8), byte(value) }) + } else if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } else if value >= 128 { + return writer.Write([]byte { 0xd1, byte(uint32(value) >> 8), byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt64(writer io.Writer, value int64) (n int, err os.Error) { + if value < -2147483648 || value >= 2147483648 { + return writer.Write([]byte { 0xd3, byte(uint64(value) >> 56), byte(uint64(value) >> 48), byte(uint64(value) >> 40), byte(uint64(value) >> 32), byte(uint64(value) >> 24), byte(uint64(value) >> 16), byte(uint64(value) >> 8), byte(value) }) + } else if value < -32768 || value >= 32768 { + return writer.Write([]byte { 0xd2, byte(uint64(value) >> 24), byte(uint64(value) >> 16), byte(uint64(value) >> 8), byte(value) }) + } else if value < -128 || value >= 128 { + return writer.Write([]byte { 0xd1, byte(uint64(value) >> 8), byte(value) }) + } else if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt(writer io.Writer, value int) (n int, err os.Error) { + switch unsafe.Sizeof(value) { + case 4: + return PackInt32(writer, *(*int32)(unsafe.Pointer(&value))) + case 8: + return PackInt64(writer, *(*int64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackNil(writer io.Writer) (n int, err os.Error) { + return writer.Write([]byte{ 0xc0 }) +} + +func PackBool(writer io.Writer, value bool) (n int, err os.Error) { + var code byte; + if value { + code = 0xc3 + } else { + code = 0xc2 + } + return writer.Write([]byte{ code }) +} + +func PackFloat32(writer io.Writer, value float32) (n int, err os.Error) { + return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) +} + +func PackFloat64(writer io.Writer, value float64) (n int, err os.Error) { + return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) +} + +func PackFloat(writer io.Writer, value float) (n int, err os.Error) { + switch unsafe.Sizeof(value) { + case 4: + return PackFloat32(writer, *(*float32)(unsafe.Pointer(&value))) + case 8: + return PackFloat64(writer, *(*float64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { + if len(value) < 32 { + n1, err := writer.Write([]byte { 0xa0 | uint8(len(value)) }) + if err != nil { return n1, err } + n2, err := writer.Write(value) + return n1 + n2, err + } else if len(value) < 65536 { + n1, err := writer.Write([]byte { 0xda, byte(len(value) >> 16), byte(len(value)) }) + if err != nil { return n1, err } + n2, err := writer.Write(value) + return n1 + n2, err + } + n1, err := writer.Write([]byte { 0xdb, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n1, err } + n2, err := writer.Write(value) + return n1 + n2, err +} + +func PackUint16Array(writer io.Writer, value []uint16) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint16(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint16(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint16(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackUint32Array(writer io.Writer, value []uint32) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint32(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint32(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint32(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackUint64Array(writer io.Writer, value []uint64) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint64(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint64(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint64(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackUintArray(writer io.Writer, value []uint) (n int, err os.Error) { + switch unsafe.Sizeof(0) { + case 4: + return PackUint32Array(writer, *(*[]uint32)(unsafe.Pointer(&value))) + case 8: + return PackUint64Array(writer, *(*[]uint64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackInt8Array(writer io.Writer, value []int8) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt8(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt8(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt8(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackInt16Array(writer io.Writer, value []int16) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt16(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt16(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt16(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackInt32Array(writer io.Writer, value []int32) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt32(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt32(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt32(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackInt64Array(writer io.Writer, value []int64) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt64(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt64(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt64(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackIntArray(writer io.Writer, value []int) (n int, err os.Error) { + switch unsafe.Sizeof(0) { + case 4: + return PackInt32Array(writer, *(*[]int32)(unsafe.Pointer(&value))) + case 8: + return PackInt64Array(writer, *(*[]int64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackFloat32Array(writer io.Writer, value []float32) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat32(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat32(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat32(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat64(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat64(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat64(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackFloatArray(writer io.Writer, value []float) (n int, err os.Error) { + switch unsafe.Sizeof(0) { + case 4: + return PackFloat32Array(writer, *(*[]float32)(unsafe.Pointer(&value))) + case 8: + return PackFloat64Array(writer, *(*[]float64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { + l := value.Len() + if l < 16 { + n, err := writer.Write([]byte { 0x90 | byte(l) }) + if err != nil { return n, err } + for i := 0; i < l; i++ { + _n, err := PackValue(writer, value.Elem(i)) + if err != nil { return n, err } + n += _n + } + } else if l < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(l >> 8), byte(l) }) + if err != nil { return n, err } + for i := 0; i < l; i++ { + _n, err := PackValue(writer, value.Elem(i)) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l) }) + if err != nil { return n, err } + for i := 0; i < l; i++ { + _n, err := PackValue(writer, value.Elem(i)) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { + keys := value.Keys() + if value.Len() < 16 { + n, err := writer.Write([]byte { 0x80 | byte(len(keys)) }) + if err != nil { return n, err } + for _, k := range keys { + _n, err := PackValue(writer, k) + if err != nil { return n, err } + n += _n + _n, err = PackValue(writer, value.Elem(k)) + if err != nil { return n, err } + n += _n + } + } else if value.Len() < 65536 { + n, err := writer.Write([]byte { 0xde, byte(len(keys) >> 8), byte(len(keys)) }) + if err != nil { return n, err } + for _, k := range keys { + _n, err := PackValue(writer, k) + if err != nil { return n, err } + n += _n + _n, err = PackValue(writer, value.Elem(k)) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdf, byte(len(keys) >> 24), byte(len(keys) >> 16), byte(len(keys) >> 8), byte(len(keys)) }) + if err != nil { return n, err } + for _, k := range keys { + _n, err := PackValue(writer, k) + if err != nil { return n, err } + n += _n + _n, err = PackValue(writer, value.Elem(k)) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { + if value.Type() == nil { return PackNil(writer) } + switch _value := value.(type) { + case *reflect.BoolValue: return PackBool(writer, _value.Get()) + case *reflect.Uint8Value: return PackUint8(writer, _value.Get()) + case *reflect.Uint16Value: return PackUint16(writer, _value.Get()) + case *reflect.Uint32Value: return PackUint32(writer, _value.Get()) + case *reflect.Uint64Value: return PackUint64(writer, _value.Get()) + case *reflect.UintValue: return PackUint(writer, _value.Get()) + case *reflect.Int8Value: return PackInt8(writer, _value.Get()) + case *reflect.Int16Value: return PackInt16(writer, _value.Get()) + case *reflect.Int32Value: return PackInt32(writer, _value.Get()) + case *reflect.Int64Value: return PackInt64(writer, _value.Get()) + case *reflect.IntValue: return PackInt(writer, _value.Get()) + case *reflect.Float32Value: return PackFloat32(writer, _value.Get()) + case *reflect.Float64Value: return PackFloat64(writer, _value.Get()) + case *reflect.FloatValue: return PackFloat(writer, _value.Get()) + case *reflect.ArrayValue: return PackArray(writer, _value) + case *reflect.SliceValue: return PackArray(writer, _value) + case *reflect.MapValue: return PackMap(writer, _value) + } + panic("unsupported type: " + value.Type().String()) +} + +func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { + if value == nil { return PackNil(writer) } + switch _value := value.(type) { + case bool: return PackBool(writer, _value) + case uint8: return PackUint8(writer, _value) + case uint16: return PackUint16(writer, _value) + case uint32: return PackUint32(writer, _value) + case uint64: return PackUint64(writer, _value) + case uint: return PackUint(writer, _value) + case int8: return PackInt8(writer, _value) + case int16: return PackInt16(writer, _value) + case int32: return PackInt32(writer, _value) + case int64: return PackInt64(writer, _value) + case int: return PackInt(writer, _value) + case float32: return PackFloat32(writer, _value) + case float64: return PackFloat64(writer, _value) + case float: return PackFloat(writer, _value) + case []byte: return PackBytes(writer, _value) + case []uint16: return PackUint16Array(writer, _value) + case []uint32: return PackUint32Array(writer, _value) + case []uint64: return PackUint64Array(writer, _value) + case []uint: return PackUintArray(writer, _value) + case []int8: return PackInt8Array(writer, _value) + case []int16: return PackInt16Array(writer, _value) + case []int32: return PackInt32Array(writer, _value) + case []int64: return PackInt64Array(writer, _value) + case []int: return PackIntArray(writer, _value) + case []float32: return PackFloat32Array(writer, _value) + case []float64: return PackFloat64Array(writer, _value) + case []float: return PackFloatArray(writer, _value) + default: + return PackValue(writer, reflect.NewValue(value)) + } + return 0, nil // never get here +} diff --git a/go/unpack.go b/go/unpack.go new file mode 100644 index 00000000..4bae8a3b --- /dev/null +++ b/go/unpack.go @@ -0,0 +1,203 @@ +package msgpack + +import ( + "io" + "os" + "unsafe" + "reflect" +) + +func readByte(reader io.Reader) (v uint8, err os.Error) { + data := [1]byte{} + _, e := reader.Read(data[0:]) + if e != nil { return 0, e } + return data[0], nil +} + +func readUint16(reader io.Reader) (v uint16, n int, err os.Error) { + data := [2]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (uint16(data[0]) >> 8) | uint16(data[1]), n, nil +} + +func readUint32(reader io.Reader) (v uint32, n int, err os.Error) { + data := [4]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (uint32(data[0]) << 24) | (uint32(data[1]) << 16) | (uint32(data[2]) << 8) | uint32(data[1]), n, nil +} + +func readUint64(reader io.Reader) (v uint64, n int, err os.Error) { + data := [8]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (uint64(data[0]) << 56) | (uint64(data[1]) << 48) | (uint64(data[2]) << 40) | (uint64(data[3]) << 32) | (uint64(data[4]) << 24) | (uint64(data[5]) << 16) | (uint64(data[6]) << 8) | uint64(data[7]), n, nil +} + +func readInt16(reader io.Reader) (v int16, n int, err os.Error) { + data := [2]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (int16(data[0]) << 8) | int16(data[1]), n, nil +} + +func readInt32(reader io.Reader) (v int32, n int, err os.Error) { + data := [4]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (int32(data[0]) << 24) | (int32(data[1]) << 16) | (int32(data[2]) << 8) | int32(data[1]), n, nil +} + +func readInt64(reader io.Reader) (v int64, n int, err os.Error) { + data := [8]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (int64(data[0]) << 56) | (int64(data[1]) << 48) | (int64(data[2]) << 40) | (int64(data[3]) << 32) | (int64(data[4]) << 24) | (int64(data[5]) << 16) | (int64(data[6]) << 8) | int64(data[7]), n, nil +} + +func unpackArray(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make([]interface{}, nelems) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + v, n, e := Unpack(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[i] = v.Interface() + } + return reflect.NewValue(retval), nbytesread, nil +} + +func unpackMap(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make(map [interface{}] interface{}) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + k, n, e := Unpack(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + v, n, e := Unpack(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[k.Interface()] = v.Interface() + } + return reflect.NewValue(retval), nbytesread, nil +} + +func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { + var retval reflect.Value + var nbytesread int = 0 + + c, e := readByte(reader) + if e != nil { return nil, 0, e } + nbytesread += 1 + if c < 0x80 || c >= 0xe0 { + retval = reflect.NewValue(int8(c)) + } else if c >= 0x80 && c <= 0x8f { + retval, n, e = unpackMap(reader, uint(c & 0xf)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + nbytesread += n + } else if c >= 0x90 && c <= 0x9f { + retval, n, e = unpackArray(reader, uint(c & 0xf)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + nbytesread += n + } else if c >= 0xa0 && c <= 0xbf { + data := make([]byte, c & 0xf); + n, e := reader.Read(data) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + } else { + switch c { + case 0xc0: retval = reflect.NewValue(nil) + case 0xc2: retval = reflect.NewValue(false) + case 0xc3: retval = reflect.NewValue(true) + case 0xca: + data, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(*(*float32)(unsafe.Pointer(&data))) + case 0xcb: + data, n, e := readUint64(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(*(*float64)(unsafe.Pointer(&data))) + case 0xcc: + data, e := readByte(reader) + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(uint8(data)) + nbytesread += 1 + case 0xcd: + data, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xce: + data, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xcf: + data, n, e := readUint64(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xd0: + data, e := readByte(reader) + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(int8(data)) + nbytesread += 1 + case 0xd1: + data, n, e := readInt16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xd2: + data, n, e := readInt32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xd3: + data, n, e := readInt64(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xda: + nbytestoread, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + data := make([]byte, nbytestoread) + n, e = reader.Read(data) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xdb: + nbytestoread, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + data := make([]byte, nbytestoread) + n, e = reader.Read(data) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xdc: + nelemstoread, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackArray(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + case 0xdd: + nelemstoread, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackArray(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + } + } + return retval, nbytesread, nil +} From fccf1016e454c6972c6d6a15b71a102d1407f8e2 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Wed, 9 Jun 2010 03:28:28 +0900 Subject: [PATCH 15/53] Fix bugs in unpacker. --- go/unpack.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go/unpack.go b/go/unpack.go index 4bae8a3b..e2e3dc01 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -18,14 +18,14 @@ func readUint16(reader io.Reader) (v uint16, n int, err os.Error) { data := [2]byte{} n, e := reader.Read(data[0:]) if e != nil { return 0, n, e } - return (uint16(data[0]) >> 8) | uint16(data[1]), n, nil + return (uint16(data[0]) << 8) | uint16(data[1]), n, nil } func readUint32(reader io.Reader) (v uint32, n int, err os.Error) { data := [4]byte{} n, e := reader.Read(data[0:]) if e != nil { return 0, n, e } - return (uint32(data[0]) << 24) | (uint32(data[1]) << 16) | (uint32(data[2]) << 8) | uint32(data[1]), n, nil + return (uint32(data[0]) << 24) | (uint32(data[1]) << 16) | (uint32(data[2]) << 8) | uint32(data[3]), n, nil } func readUint64(reader io.Reader) (v uint64, n int, err os.Error) { @@ -46,7 +46,7 @@ func readInt32(reader io.Reader) (v int32, n int, err os.Error) { data := [4]byte{} n, e := reader.Read(data[0:]) if e != nil { return 0, n, e } - return (int32(data[0]) << 24) | (int32(data[1]) << 16) | (int32(data[2]) << 8) | int32(data[1]), n, nil + return (int32(data[0]) << 24) | (int32(data[1]) << 16) | (int32(data[2]) << 8) | int32(data[3]), n, nil } func readInt64(reader io.Reader) (v int64, n int, err os.Error) { From 8f1bd12a1716ece95e762b5983f9e1e99f05576d Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Wed, 9 Jun 2010 03:28:43 +0900 Subject: [PATCH 16/53] Improve testsuite. --- go/msgpack_test.go | 83 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/go/msgpack_test.go b/go/msgpack_test.go index a5dda2a4..9c695553 100644 --- a/go/msgpack_test.go +++ b/go/msgpack_test.go @@ -7,6 +7,72 @@ import ( "reflect" ); +func equal(lhs reflect.Value, rhs reflect.Value) bool { + { + _rhs, ok := rhs.(*reflect.InterfaceValue) + if ok { return equal(lhs, _rhs.Elem()) } + } + switch _lhs := lhs.(type) { + case *reflect.InterfaceValue: + return equal(_lhs.Elem(), rhs) + case *reflect.BoolValue: + _rhs, ok := rhs.(*reflect.BoolValue) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint8Value: + _rhs, ok := rhs.(*reflect.Uint8Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint16Value: + _rhs, ok := rhs.(*reflect.Uint16Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint32Value: + _rhs, ok := rhs.(*reflect.Uint32Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint64Value: + _rhs, ok := rhs.(*reflect.Uint64Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.UintValue: + _rhs, ok := rhs.(*reflect.UintValue) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int8Value: + _rhs, ok := rhs.(*reflect.Int8Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int16Value: + _rhs, ok := rhs.(*reflect.Int16Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int32Value: + _rhs, ok := rhs.(*reflect.Int32Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int64Value: + _rhs, ok := rhs.(*reflect.Int64Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.IntValue: + _rhs, ok := rhs.(*reflect.IntValue) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Float32Value: + _rhs, ok := rhs.(*reflect.Float32Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Float64Value: + _rhs, ok := rhs.(*reflect.Float64Value) + return ok && _lhs.Get() == _rhs.Get() + case reflect.ArrayOrSliceValue: + _rhs := rhs.(reflect.ArrayOrSliceValue) + if _lhs.Len() != _rhs.Len() { return false; } + for i := 0; i < _lhs.Len(); i++ { + if !equal(_lhs.Elem(i), _rhs.Elem(i)) { return false; } + } + return true; + case *reflect.MapValue: + _rhs := rhs.(*reflect.MapValue) + if _lhs.Len() != _rhs.Len() { return false; } + for _, k := range _lhs.Keys() { + lv, rv := _lhs.Elem(k), _rhs.Elem(k) + if lv == nil || rv == nil || !equal(lv, rv) { return false; } + } + return true; + } + return false; +} + func TestPackUint8(t *testing.T) { b := &bytes.Buffer{} for _, i := range []uint8 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255 } { @@ -139,12 +205,19 @@ func TestPack(t *testing.T) { if bytes.Compare(b.Bytes(), []byte { 0xc0, 0xc2, 0xc3, 0x00, 0x01, 0x02, 0x03, 0x7f, 0xf0, 0xff, 0xd0, 0xef, 0xd1, 0x00, 0x80 }) == 0 { t.Error("wrong output") } } -func TestUnpack(t *testing.T) { - b := bytes.NewBuffer([]byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) +func TestUnpackArray(t *testing.T) { + b := bytes.NewBuffer([]byte { 0x90, 0x91, 0x00, 0x92, 0x00, 0x01, 0x93, 0xd1, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xdc, 0x00, 0x02, 0x00, 0x01, 0xdd, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03 }) + for _, v := range [](interface{}) { [](interface{}) {}, [](interface{}) { int8(0) }, [](interface{}) { int8(0), int8(1) }, [](interface{}) { int16(0), int32(1), int64(2) }, [](interface{}){ int8(0), int8(1) }, [](interface{}) { int8(0), int8(1), int8(2), int8(3) } } { + retval, _, e := Unpack(b) + if e != nil { t.Error("err != nil") } + if !equal(reflect.NewValue(retval.Interface()), reflect.NewValue(v)) { t.Errorf("%s != %s", retval.Interface(), v) } + } +} + +func TestUnpackInt(t *testing.T) { + b := bytes.NewBuffer([]byte { 0xff, 0xe0, 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xd0, 0x01, 0xd0, 0x80, 0xd0, 0xff, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xd1, 0x00, 0x00, 0xd1, 0x7f, 0xff, 0xd1, 0xff, 0xff, 0xcd, 0x80, 0x00, 0xcd, 0xff, 0xff, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) for _, v := range [](interface{}) { - int8(0), int8(1), int8(2), int8(125), int8(126), int8(127), - uint8(128), uint8(253), uint8(254), uint8(255), int32(2147483647), - int64(9223372036854775807) } { + int8(-1), int8(-32), int8(0), int8(1), int8(2), int8(125), int8(126), int8(127), int8(1), int8(-128), int8(-1), uint8(128), uint8(253), uint8(254), uint8(255), int16(0), int16(32767), int16(-1), uint16(32768), uint16(65535), int32(2147483647), uint32(2147483647), int64(9223372036854775807), uint64(18446744073709551615) } { retval, _, e := Unpack(b) if e != nil { t.Error("err != nil") } if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } From ee0debc5b350e4a40c04dbd9df6da69b8c44d7ad Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Thu, 24 Jun 2010 00:56:49 +0900 Subject: [PATCH 17/53] Add .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index d740b181..b39017b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ *.o *.so ruby/Makefile +*.5 +*.8 +*.6 +_obj +_test From 8325cce44c227e3b6fb5ffbf25b796ffd43bdd1b Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sat, 26 Jun 2010 20:31:53 +0900 Subject: [PATCH 18/53] Adapt to new reflection API (notified by mattn. thanks) --- go/msgpack_test.go | 31 ++----------------------------- go/pack.go | 16 +++------------- 2 files changed, 5 insertions(+), 42 deletions(-) diff --git a/go/msgpack_test.go b/go/msgpack_test.go index 9c695553..e324f2eb 100644 --- a/go/msgpack_test.go +++ b/go/msgpack_test.go @@ -18,41 +18,14 @@ func equal(lhs reflect.Value, rhs reflect.Value) bool { case *reflect.BoolValue: _rhs, ok := rhs.(*reflect.BoolValue) return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint8Value: - _rhs, ok := rhs.(*reflect.Uint8Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint16Value: - _rhs, ok := rhs.(*reflect.Uint16Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint32Value: - _rhs, ok := rhs.(*reflect.Uint32Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint64Value: - _rhs, ok := rhs.(*reflect.Uint64Value) - return ok && _lhs.Get() == _rhs.Get() case *reflect.UintValue: _rhs, ok := rhs.(*reflect.UintValue) return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int8Value: - _rhs, ok := rhs.(*reflect.Int8Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int16Value: - _rhs, ok := rhs.(*reflect.Int16Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int32Value: - _rhs, ok := rhs.(*reflect.Int32Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int64Value: - _rhs, ok := rhs.(*reflect.Int64Value) - return ok && _lhs.Get() == _rhs.Get() case *reflect.IntValue: _rhs, ok := rhs.(*reflect.IntValue) return ok && _lhs.Get() == _rhs.Get() - case *reflect.Float32Value: - _rhs, ok := rhs.(*reflect.Float32Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Float64Value: - _rhs, ok := rhs.(*reflect.Float64Value) + case *reflect.FloatValue: + _rhs, ok := rhs.(*reflect.FloatValue) return ok && _lhs.Get() == _rhs.Get() case reflect.ArrayOrSliceValue: _rhs := rhs.(reflect.ArrayOrSliceValue) diff --git a/go/pack.go b/go/pack.go index 8240394c..d30eef89 100644 --- a/go/pack.go +++ b/go/pack.go @@ -524,19 +524,9 @@ func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { if value.Type() == nil { return PackNil(writer) } switch _value := value.(type) { case *reflect.BoolValue: return PackBool(writer, _value.Get()) - case *reflect.Uint8Value: return PackUint8(writer, _value.Get()) - case *reflect.Uint16Value: return PackUint16(writer, _value.Get()) - case *reflect.Uint32Value: return PackUint32(writer, _value.Get()) - case *reflect.Uint64Value: return PackUint64(writer, _value.Get()) - case *reflect.UintValue: return PackUint(writer, _value.Get()) - case *reflect.Int8Value: return PackInt8(writer, _value.Get()) - case *reflect.Int16Value: return PackInt16(writer, _value.Get()) - case *reflect.Int32Value: return PackInt32(writer, _value.Get()) - case *reflect.Int64Value: return PackInt64(writer, _value.Get()) - case *reflect.IntValue: return PackInt(writer, _value.Get()) - case *reflect.Float32Value: return PackFloat32(writer, _value.Get()) - case *reflect.Float64Value: return PackFloat64(writer, _value.Get()) - case *reflect.FloatValue: return PackFloat(writer, _value.Get()) + case *reflect.UintValue: return PackUint64(writer, _value.Get()) + case *reflect.IntValue: return PackInt64(writer, _value.Get()) + case *reflect.FloatValue: return PackFloat64(writer, _value.Get()) case *reflect.ArrayValue: return PackArray(writer, _value) case *reflect.SliceValue: return PackArray(writer, _value) case *reflect.MapValue: return PackMap(writer, _value) From d4d7495c0acc2de17dbda823d725a0133feea6da Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sat, 26 Jun 2010 20:44:08 +0900 Subject: [PATCH 19/53] Forgot to support map16 / map32 --- go/unpack.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/go/unpack.go b/go/unpack.go index e2e3dc01..38098941 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -197,6 +197,20 @@ func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { retval, n, e = unpackArray(reader, uint(nelemstoread)) nbytesread += n if e != nil { return nil, nbytesread, e } + case 0xde: + nelemstoread, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackMap(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + case 0xdf: + nelemstoread, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackMap(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } } } return retval, nbytesread, nil From 5b544248bc63b8592996f900181b43f8834b65f0 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sat, 26 Jun 2010 22:09:29 +0900 Subject: [PATCH 20/53] Add new API function UnpackReflected() that returns multiple reflect.Value for unpacked elements of arrays or maps. --- go/unpack.go | 78 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/go/unpack.go b/go/unpack.go index 38098941..3ca48042 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -69,6 +69,19 @@ func unpackArray(reader io.Reader, nelems uint) (v reflect.Value, n int, err os. return reflect.NewValue(retval), nbytesread, nil } +func unpackArrayReflected(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make([]reflect.Value, nelems) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + v, n, e := UnpackReflected(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[i] = v + } + return reflect.NewValue(retval), nbytesread, nil +} + func unpackMap(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { retval := make(map [interface{}] interface{}) nbytesread := 0 @@ -85,7 +98,23 @@ func unpackMap(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Er return reflect.NewValue(retval), nbytesread, nil } -func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { +func unpackMapReflected(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make(map [reflect.Value] reflect.Value) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + k, n, e := UnpackReflected(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + v, n, e := UnpackReflected(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[k] = v + } + return reflect.NewValue(retval), nbytesread, nil +} + +func unpack(reader io.Reader, reflected bool) (v reflect.Value, n int, err os.Error) { var retval reflect.Value var nbytesread int = 0 @@ -95,12 +124,20 @@ func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { if c < 0x80 || c >= 0xe0 { retval = reflect.NewValue(int8(c)) } else if c >= 0x80 && c <= 0x8f { - retval, n, e = unpackMap(reader, uint(c & 0xf)) + if reflected { + retval, n, e = unpackMapReflected(reader, uint(c & 0xf)) + } else { + retval, n, e = unpackMap(reader, uint(c & 0xf)) + } nbytesread += n if e != nil { return nil, nbytesread, e } nbytesread += n } else if c >= 0x90 && c <= 0x9f { - retval, n, e = unpackArray(reader, uint(c & 0xf)) + if reflected { + retval, n, e = unpackArrayReflected(reader, uint(c & 0xf)) + } else { + retval, n, e = unpackArray(reader, uint(c & 0xf)) + } nbytesread += n if e != nil { return nil, nbytesread, e } nbytesread += n @@ -187,31 +224,58 @@ func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { nelemstoread, n, e := readUint16(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackArray(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackArrayReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackArray(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } case 0xdd: nelemstoread, n, e := readUint32(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackArray(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackArrayReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackArray(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } case 0xde: nelemstoread, n, e := readUint16(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackMap(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackMapReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackMap(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } case 0xdf: nelemstoread, n, e := readUint32(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackMap(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackMapReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackMap(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } } } return retval, nbytesread, nil } + +func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { + return unpack(reader, false) +} + +func UnpackReflected(reader io.Reader) (v reflect.Value, n int, err os.Error) { + return unpack(reader, true) +} + + + From 0e82278cd505f8dc0b2c17bd0b43e7d22844f292 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sun, 27 Jun 2010 01:32:37 +0900 Subject: [PATCH 21/53] Fix: InterfaceValue wasnt' correctly unwrapped when passed to PackValue() --- go/pack.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/go/pack.go b/go/pack.go index d30eef89..602f48ac 100644 --- a/go/pack.go +++ b/go/pack.go @@ -521,7 +521,7 @@ func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { } func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { - if value.Type() == nil { return PackNil(writer) } + if value == nil || value.Type() == nil { return PackNil(writer) } switch _value := value.(type) { case *reflect.BoolValue: return PackBool(writer, _value.Get()) case *reflect.UintValue: return PackUint64(writer, _value.Get()) @@ -530,6 +530,12 @@ func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { case *reflect.ArrayValue: return PackArray(writer, _value) case *reflect.SliceValue: return PackArray(writer, _value) case *reflect.MapValue: return PackMap(writer, _value) + case *reflect.InterfaceValue: + __value := reflect.NewValue(_value.Interface()) + _, ok := __value.(*reflect.InterfaceValue) + if !ok { + return PackValue(writer, __value) + } } panic("unsupported type: " + value.Type().String()) } From 003fb3392fc749131f1904e53bf1aeafcbb4ca29 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sun, 27 Jun 2010 01:39:04 +0900 Subject: [PATCH 22/53] Byte arrays in Go should not be serialized as arrays. --- go/pack.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/go/pack.go b/go/pack.go index 602f48ac..f23652e3 100644 --- a/go/pack.go +++ b/go/pack.go @@ -452,6 +452,13 @@ func PackFloatArray(writer io.Writer, value []float) (n int, err os.Error) { } func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { + { + elemType, ok := value.Type().(reflect.ArrayOrSliceType).Elem().(*reflect.UintType) + if ok && elemType.Kind() == reflect.Uint8 { + return PackBytes(writer, value.Interface().([]byte)) + } + } + l := value.Len() if l < 16 { n, err := writer.Write([]byte { 0x90 | byte(l) }) From ee16e2eb30df2fd3ae2219fe95ade0941515b490 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sun, 27 Jun 2010 03:02:18 +0900 Subject: [PATCH 23/53] Handle unsupported typecode --- go/unpack.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/unpack.go b/go/unpack.go index 3ca48042..a3753112 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -4,6 +4,7 @@ import ( "io" "os" "unsafe" + "strconv" "reflect" ) @@ -264,6 +265,8 @@ func unpack(reader io.Reader, reflected bool) (v reflect.Value, n int, err os.Er } nbytesread += n if e != nil { return nil, nbytesread, e } + default: + panic("unsupported code: " + strconv.Itoa(int(c))) } } return retval, nbytesread, nil From 7e31d487e0443658c0af1e80935ad60a1af62aa3 Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Sun, 3 Apr 2011 14:06:08 +0900 Subject: [PATCH 24/53] float type was gone from go language at some time I don't know. --- go/Makefile | 2 +- go/pack.go | 22 ---------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/go/Makefile b/go/Makefile index 289bd122..adc243af 100644 --- a/go/Makefile +++ b/go/Makefile @@ -1,4 +1,4 @@ -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc TARG=msgpack diff --git a/go/pack.go b/go/pack.go index f23652e3..aadd7f93 100644 --- a/go/pack.go +++ b/go/pack.go @@ -132,16 +132,6 @@ func PackFloat64(writer io.Writer, value float64) (n int, err os.Error) { return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) } -func PackFloat(writer io.Writer, value float) (n int, err os.Error) { - switch unsafe.Sizeof(value) { - case 4: - return PackFloat32(writer, *(*float32)(unsafe.Pointer(&value))) - case 8: - return PackFloat64(writer, *(*float64)(unsafe.Pointer(&value))) - } - return 0, os.ENOENT // never get here -} - func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { if len(value) < 32 { n1, err := writer.Write([]byte { 0xa0 | uint8(len(value)) }) @@ -441,16 +431,6 @@ func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { return n, nil } -func PackFloatArray(writer io.Writer, value []float) (n int, err os.Error) { - switch unsafe.Sizeof(0) { - case 4: - return PackFloat32Array(writer, *(*[]float32)(unsafe.Pointer(&value))) - case 8: - return PackFloat64Array(writer, *(*[]float64)(unsafe.Pointer(&value))) - } - return 0, os.ENOENT // never get here -} - func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { { elemType, ok := value.Type().(reflect.ArrayOrSliceType).Elem().(*reflect.UintType) @@ -563,7 +543,6 @@ func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { case int: return PackInt(writer, _value) case float32: return PackFloat32(writer, _value) case float64: return PackFloat64(writer, _value) - case float: return PackFloat(writer, _value) case []byte: return PackBytes(writer, _value) case []uint16: return PackUint16Array(writer, _value) case []uint32: return PackUint32Array(writer, _value) @@ -576,7 +555,6 @@ func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { case []int: return PackIntArray(writer, _value) case []float32: return PackFloat32Array(writer, _value) case []float64: return PackFloat64Array(writer, _value) - case []float: return PackFloatArray(writer, _value) default: return PackValue(writer, reflect.NewValue(value)) } From 64fe90aabb69dea61794132d5390fc6659dcfe5c Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Sun, 3 Apr 2011 15:34:37 +0900 Subject: [PATCH 25/53] Add TestUnpackFloat(). --- go/msgpack_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/go/msgpack_test.go b/go/msgpack_test.go index e324f2eb..50de668a 100644 --- a/go/msgpack_test.go +++ b/go/msgpack_test.go @@ -5,6 +5,7 @@ import ( "testing" "bytes" "reflect" + "math" ); func equal(lhs reflect.Value, rhs reflect.Value) bool { @@ -196,3 +197,22 @@ func TestUnpackInt(t *testing.T) { if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } } } + +func TestUnpackFloat(t *testing.T) { + b := bytes.NewBuffer([]byte { 0xca, 0x3d, 0xcc, 0xcc, 0xcd, 0xca, 0x3e, 0x4c, 0xcc, 0xcd, 0xca, 0xbd, 0xcc, 0xcc, 0xcd, 0xca, 0xbe, 0x4c, 0xcc, 0xcd, 0xca, 0x7f, 0x80, 0x00, 0x00, 0xca, 0xff, 0x80, 0x00, 0x00, 0xca, 0xff, 0xc0, 0x00, 0x0, 0xcb, 0x3f, 0xb9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0x3f, 0xc9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0xbf, 0xb9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0xbf, 0xc9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xcb, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + for _, v := range [](interface{}) { float32(.1), float32(.2), float32(-.1), float32(-.2), float32(math.Inf(1)), float32(math.Inf(-1)), float32(math.NaN()), float64(.1), float64(.2), float64(-.1), float64(-.2) } { + retval, _, e := Unpack(b) + if e != nil { t.Error("err != nil") } + isnan := false + if _v, ok := v.(float64); ok { + isnan = math.IsNaN(_v) + } else if _v, ok := v.(float32); ok { + isnan = math.IsNaN(float64(_v)) + } + if isnan { + if retval.Interface() == v { t.Errorf("[NaN] %u == %u", retval.Interface(), v) } + } else { + if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } + } + } +} From 6e5f9404b74341b4678e1c8dd976bdc669e51d6b Mon Sep 17 00:00:00 2001 From: mzp Date: Sun, 3 Apr 2011 17:11:53 +0900 Subject: [PATCH 26/53] ocaml: initial commit --- ocaml/.gitignore | 11 + ocaml/OMakefile | 8 + ocaml/OMakeroot | 45 ++ ocaml/README.markdown | 22 + ocaml/bleis-hooks/commit-msg | 14 + ocaml/bleis-hooks/common.sh | 60 +++ ocaml/bleis-hooks/pre-commit | 22 + ocaml/ocaml/.gitignore | 4 + ocaml/ocaml/META | 6 + ocaml/ocaml/OMakefile | 80 ++++ ocaml/ocaml/base.ml | 142 ++++++ ocaml/ocaml/config.ml | 1 + ocaml/ocaml/hList.ml | 191 ++++++++ ocaml/ocaml/main.ml | 2 + ocaml/ocaml/msgpack.mli | 46 ++ ocaml/ocaml/pack.ml | 206 +++++++++ ocaml/ocaml/pack.mli | 32 ++ ocaml/ocaml/packTest.ml | 175 ++++++++ ocaml/ocaml/serialize.ml | 20 + ocaml/ocaml/serialize.mli | 4 + ocaml/ocaml/serializeTest.ml | 16 + ocaml/proof/.gitignore | 2 + ocaml/proof/CoqBuildRule | 14 + ocaml/proof/DeserializeImplement.v | 630 +++++++++++++++++++++++++++ ocaml/proof/ExtractUtil.v | 95 ++++ ocaml/proof/ListUtil.v | 259 +++++++++++ ocaml/proof/Main.v | 3 + ocaml/proof/MultiByte.v | 334 ++++++++++++++ ocaml/proof/OCamlBase.v | 8 + ocaml/proof/OMakefile | 26 ++ ocaml/proof/Object.v | 122 ++++++ ocaml/proof/Pow.v | 162 +++++++ ocaml/proof/Prefix.v | 674 +++++++++++++++++++++++++++++ ocaml/proof/ProofUtil.v | 5 + ocaml/proof/SerializeImplement.v | 465 ++++++++++++++++++++ ocaml/proof/SerializeSpec.v | 99 +++++ ocaml/proof/SerializedList.v | 521 ++++++++++++++++++++++ ocaml/proof/Soundness.v | 623 ++++++++++++++++++++++++++ ocaml/proof/Util.v | 39 ++ 39 files changed, 5188 insertions(+) create mode 100644 ocaml/.gitignore create mode 100644 ocaml/OMakefile create mode 100644 ocaml/OMakeroot create mode 100644 ocaml/README.markdown create mode 100755 ocaml/bleis-hooks/commit-msg create mode 100755 ocaml/bleis-hooks/common.sh create mode 100755 ocaml/bleis-hooks/pre-commit create mode 100644 ocaml/ocaml/.gitignore create mode 100644 ocaml/ocaml/META create mode 100644 ocaml/ocaml/OMakefile create mode 100644 ocaml/ocaml/base.ml create mode 100644 ocaml/ocaml/config.ml create mode 100644 ocaml/ocaml/hList.ml create mode 100644 ocaml/ocaml/main.ml create mode 100644 ocaml/ocaml/msgpack.mli create mode 100644 ocaml/ocaml/pack.ml create mode 100644 ocaml/ocaml/pack.mli create mode 100644 ocaml/ocaml/packTest.ml create mode 100644 ocaml/ocaml/serialize.ml create mode 100644 ocaml/ocaml/serialize.mli create mode 100644 ocaml/ocaml/serializeTest.ml create mode 100644 ocaml/proof/.gitignore create mode 100644 ocaml/proof/CoqBuildRule create mode 100644 ocaml/proof/DeserializeImplement.v create mode 100644 ocaml/proof/ExtractUtil.v create mode 100644 ocaml/proof/ListUtil.v create mode 100644 ocaml/proof/Main.v create mode 100644 ocaml/proof/MultiByte.v create mode 100644 ocaml/proof/OCamlBase.v create mode 100644 ocaml/proof/OMakefile create mode 100644 ocaml/proof/Object.v create mode 100644 ocaml/proof/Pow.v create mode 100644 ocaml/proof/Prefix.v create mode 100644 ocaml/proof/ProofUtil.v create mode 100644 ocaml/proof/SerializeImplement.v create mode 100644 ocaml/proof/SerializeSpec.v create mode 100644 ocaml/proof/SerializedList.v create mode 100644 ocaml/proof/Soundness.v create mode 100644 ocaml/proof/Util.v diff --git a/ocaml/.gitignore b/ocaml/.gitignore new file mode 100644 index 00000000..fbfb0c56 --- /dev/null +++ b/ocaml/.gitignore @@ -0,0 +1,11 @@ +*~ +*.omc +.omakedb +.omakedb.lock +*.vo +*.glob +*.cm[iox] +*.o +*.annot +*.opt +*.run \ No newline at end of file diff --git a/ocaml/OMakefile b/ocaml/OMakefile new file mode 100644 index 00000000..496727d5 --- /dev/null +++ b/ocaml/OMakefile @@ -0,0 +1,8 @@ +NATIVE_ENABLED = true +BYTE_ENABLED = true + +.PHONY: clean +.SUBDIRS: ocaml proof + +clean: + rm -rf *.vo *.glob *~ *.omc .omakedb .omakedb.lock diff --git a/ocaml/OMakeroot b/ocaml/OMakeroot new file mode 100644 index 00000000..35c219da --- /dev/null +++ b/ocaml/OMakeroot @@ -0,0 +1,45 @@ +######################################################################## +# Permission is hereby granted, free of charge, to any person +# obtaining a copy of this file, to deal in the File without +# restriction, including without limitation the rights to use, +# copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the File, and to permit persons to whom the +# File is furnished to do so, subject to the following condition: +# +# THE FILE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +# OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE FILE OR +# THE USE OR OTHER DEALINGS IN THE FILE. + +######################################################################## +# The standard OMakeroot file. +# You will not normally need to modify this file. +# By default, your changes should be placed in the +# OMakefile in this directory. +# +# If you decide to modify this file, note that it uses exactly +# the same syntax as the OMakefile. +# + +# +# Include the standard installed configuration files. +# Any of these can be deleted if you are not using them, +# but you probably want to keep the Common file. +# +open build/C +open build/OCaml +open build/LaTeX + +# +# The command-line variables are defined *after* the +# standard configuration has been loaded. +# +DefineCommandVars() + +# +# Include the OMakefile in this directory. +# +.SUBDIRS: . diff --git a/ocaml/README.markdown b/ocaml/README.markdown new file mode 100644 index 00000000..26048134 --- /dev/null +++ b/ocaml/README.markdown @@ -0,0 +1,22 @@ +MsgPack for OCaml +============================== + +OVERVIEW +------------------------------ +MessagePack(http://msgpack.org)のOCaml版ライブラリです。 +シリアライズしたものをデシリアライズすると元にもどることがCoqによって保証されています。 + +REQUIRE +------------------------------ +* extlib http://code.google.com/p/ocaml-extlib/ +* Coq 8.3 http://coq.inria.fr + +BUILD & INSTALL +------------------------------ + + $ omake + $ omake install + +DOCUMENT +------------------------------ +http://mzp.github.com/msgpack-ocaml/refman \ No newline at end of file diff --git a/ocaml/bleis-hooks/commit-msg b/ocaml/bleis-hooks/commit-msg new file mode 100755 index 00000000..38d4baf7 --- /dev/null +++ b/ocaml/bleis-hooks/commit-msg @@ -0,0 +1,14 @@ +#! /bin/sh + +if [ -n "${GIT_DIR}" ]; then + hooksdir="./${GIT_DIR}/hooks/" +else + hooksdir="./" +fi + +. "${hooksdir}common.sh" + +ticket="$(extractTicketId)" +if [ -n "${ticket}" ]; then + appendMsgTo1stLine "$1" "${ticket}" +fi diff --git a/ocaml/bleis-hooks/common.sh b/ocaml/bleis-hooks/common.sh new file mode 100755 index 00000000..556e74eb --- /dev/null +++ b/ocaml/bleis-hooks/common.sh @@ -0,0 +1,60 @@ +#! /bin/sh + +getGitBranchName() +{ + branch="$(git symbolic-ref HEAD 2>/dev/null)" || + "$(git describe --contains --all HEAD)" + echo ${branch##refs/heads/} +} + +isOnMasterBranch() +{ + if [ "$(getGitBranchName)" = "master" ]; then + return 0 + fi + return 1 +} + +appendMsgTo1stLine() +{ + mv $1 $1.$$ + if [ -s "$1.$$" ]; then + if head -1 "$1.$$" | grep "$2" > /dev/null; then + cp "$1.$$" "$1" + else + sed '1s/$/ '"$2"'/' "$1.$$" > $1 + fi + else + echo "$2" > "$1" + fi + rm -f $1.$$ +} + +extractTicketId() +{ + echo "$(getGitBranchName)" \ + | awk 'BEGIN{ FS="[/]"} + $1 == "id" { printf "refs #%s", $2 } + $2 == "id" { printf "refs #%s", $3 }' +} + +hasTicketId() +{ + first="$(git cat-file -p $1 \ + | sed '1,/^$/d' | head -1 \ + | sed '/.*refs #[0-9][0-9]*.*/!d')" + + if [ -n "${first}" ]; then + echo "true" + else + echo "false" + fi +} + +extractParents() +{ + parents="$(git cat-file -p $1 \ + | grep '^parent [0-9a-f]\{40\}$')" + echo "${parents##parent }" +} + diff --git a/ocaml/bleis-hooks/pre-commit b/ocaml/bleis-hooks/pre-commit new file mode 100755 index 00000000..9b7766bc --- /dev/null +++ b/ocaml/bleis-hooks/pre-commit @@ -0,0 +1,22 @@ +#! /bin/sh + +if [ -z "$(git branch)" ]; then + exit 0 +fi + +if [ -n "${GIT_DIR}" ]; then + hooksdir="./${GIT_DIR}/hooks/" +else + hooksdir="./" +fi + +. "${hooksdir}common.sh" + +isOnMasterBranch +if [ $? -eq 0 ]; then + echo "can't commit on master branch." + echo "please commit on topic branch." + exit 1 +fi + +exit 0 diff --git a/ocaml/ocaml/.gitignore b/ocaml/ocaml/.gitignore new file mode 100644 index 00000000..3425f3f1 --- /dev/null +++ b/ocaml/ocaml/.gitignore @@ -0,0 +1,4 @@ +runner +doc +msgpackCore.ml +msgpackCore.mli diff --git a/ocaml/ocaml/META b/ocaml/ocaml/META new file mode 100644 index 00000000..1170b98f --- /dev/null +++ b/ocaml/ocaml/META @@ -0,0 +1,6 @@ +name="msgpack" +version="0.1.0" +description="a library for MessagePack." +requires="extlib, num" +archive(byte)="msgpack.cmo" +archive(native)="msgpack.cmx" \ No newline at end of file diff --git a/ocaml/ocaml/OMakefile b/ocaml/ocaml/OMakefile new file mode 100644 index 00000000..47babc35 --- /dev/null +++ b/ocaml/ocaml/OMakefile @@ -0,0 +1,80 @@ +.PHONY: all clean check doc install + +# ------------------------------ +# camlp4 +# ------------------------------ +public.UseCamlp4(files) = + protected.CAMLP4CMO = $(addprefix $(ROOT)/camlp4/,$(addsuffix .cmo,$(files))) + OCAMLPPFLAGS+=-pp 'camlp4o $(CAMLP4CMO)' + OCAMLDEPFLAGS+=-pp 'camlp4o $(CAMLP4CMO)' + export + .SCANNER: scan-ocaml-%.ml: %.ml $(CAMLP4CMO) + +# ------------------------------ +# findlib +# ------------------------------ +USE_OCAMLFIND = true + +if $(not $(OCAMLFIND_EXISTS)) + eprintln('This project requires ocamlfind, but is was not found.') + eprintln('You need to install ocamlfind and run "omake --configure".') + exit 1 + +OCAMLPACKS[] = + oUnit + extlib + num + +OCAML_WARN_FLAGS=$`(if $(equal $<,msgpackCore.ml),-annot,-w A -warn-error A ) #` +OCAMLFLAGS=$(OCAML_WARN_FLAGS) -annot +# ------------------------------ +# library +# ------------------------------ +FILES[] = + pack + base + hList + msgpackCore + serialize + config + +msgpackCore.ml : ../proof/msgpackCore.ml + cp $^ $@ + +msgpackCore.mli : ../proof/msgpackCore.mli + cp $^ $@ + +# ------------------------------ +# test code +# ------------------------------ +TEST_FILES[] = + packTest + serializeTest + +TEST_PROGRAM = runner + +# ------------------------------ +# build rule +# ------------------------------ +PROGRAM = msgpack +OCAMLLINK = $(OCAMLC) +OCAMLOPTLINK = $(OCAMLOPT) +OCAMLC += -for-pack $(capitalize $(PROGRAM)) +OCAMLOPT += -for-pack $(capitalize $(PROGRAM)) + +.DEFAULT: all + +all : $(OCamlPackage $(PROGRAM), $(FILES)) + +check : $(OCamlProgram $(TEST_PROGRAM), $(TEST_FILES) $(FILES)) + ./$(TEST_PROGRAM) + +doc: + mkdir -p doc + ocamldoc -d doc -html msgpack.mli + +install: + ocamlfind install msgpack META msgpack.cmx msgpack.cmo + +clean: + rm -rf *.cm[iox] *.o *~ *.omc .omakedb .omakedb.lock *.cmxa *.a *.opt *.run *.annot runner msgpackCore.* diff --git a/ocaml/ocaml/base.ml b/ocaml/ocaml/base.ml new file mode 100644 index 00000000..e1ccdde5 --- /dev/null +++ b/ocaml/ocaml/base.ml @@ -0,0 +1,142 @@ +let (@@) f g = f g +let (+>) f g = g f +let ($) f g x = f (g x) +let (!$) = Lazy.force +external id : 'a -> 'a = "%identity" + +let uncurry f a b = f (a,b) +let curry f (a,b) = f a b +let flip f a b = f b a +let const a _ = a + +let sure f = + function + Some x -> + Some (f x) + | None -> + None + +let option f x = try Some (f x) with Not_found -> None +let maybe f x = try `Val (f x) with e -> `Error e +let tee f x = try ignore @@ f x; x with _ -> x + +type ('a,'b) either = Left of 'a | Right of 'b +let left x = Left x +let right x = Right x + +let failwithf fmt = Printf.kprintf (fun s () -> failwith s) fmt + +let lookup x xs = (option @@ List.assoc x) xs + +let string_of_list xs = + Printf.sprintf "[%s]" + @@ String.concat ";" xs + +let rec unfold f init = + match f init with + Some (a, b) -> a :: unfold f b + | None -> [] + +let rec range a b = + if a >= b then + [] + else + a::range (a+1) b + +let rec interperse delim = + function + [] -> [] + | [x] -> [x] + | x::xs -> x::delim::interperse delim xs + +let map_accum_left f init xs = + let f (accum,ys) x = + let accum',y = + f accum x in + (accum',y::ys) in + let accum,ys = + List.fold_left f (init,[]) xs in + accum,List.rev ys + +let rec map_accum_right f init = + function + [] -> + init,[] + | x::xs -> + let (accum,ys) = + map_accum_right f init xs in + let (accum,y) = + f accum x in + accum,y::ys + +let rec filter_map f = + function + x::xs -> + begin match f x with + Some y -> y::filter_map f xs + | None -> filter_map f xs + end + | [] -> + [] + +let rec group_by f = + function + [] -> + [] + | x1::x2::xs when f x1 x2 -> + begin match group_by f @@ x2::xs with + y::ys -> + (x1::y)::ys + | _ -> + failwith "must not happen" + end + | x::xs -> + [x]::group_by f xs + +let index x xs = + let rec loop i = function + [] -> + raise Not_found + | y::ys -> + if x = y then + i + else + loop (i+1) ys in + loop 0 xs + +let string_of_char = + String.make 1 + +let hex = + Printf.sprintf "0x%x" + +let open_out_with path f = + let ch = + open_out_bin path in + maybe f ch + +> tee (fun _ -> close_out ch) + +> function + `Val v -> v + | `Error e -> raise e + +let open_in_with path f = + let ch = + open_in_bin path in + maybe f ch + +> tee (fun _ -> close_in ch) + +> function + `Val v -> v + | `Error e -> raise e + +let forever f () = + while true do + f () + done + +let undefined = Obj.magic 42 +let undef = undefined + +let p fmt = Printf.kprintf (fun s () -> print_endline s; flush stdout) fmt + +let ret x _ = + x diff --git a/ocaml/ocaml/config.ml b/ocaml/ocaml/config.ml new file mode 100644 index 00000000..9a6723a5 --- /dev/null +++ b/ocaml/ocaml/config.ml @@ -0,0 +1 @@ +let version = (1,0,0) diff --git a/ocaml/ocaml/hList.ml b/ocaml/ocaml/hList.ml new file mode 100644 index 00000000..732a6f10 --- /dev/null +++ b/ocaml/ocaml/hList.ml @@ -0,0 +1,191 @@ +open Base + +let rec last = + function + [] -> + invalid_arg "HList.last" + | [x] -> + x + | _::xs -> + last xs + +let init xs = + let rec init' ys = + function + [] -> + invalid_arg "HList.init" + | [_] -> + List.rev ys + | x::xs -> + init' (x::ys) xs in + init' [] xs + +let null = + function + [] -> + true + | _ -> + false + +let fold_left1 f = + function + [] -> + invalid_arg "HList.fold_left1" + | x::xs -> + List.fold_left f x xs + +let rec fold_right1 f = + function + [] -> + invalid_arg "HList.fold_right1" + | [x] -> + x + | x::xs -> + f x (fold_right1 f xs) + +let conj = + List.fold_left (&&) true + +let disj = + List.fold_left (||) false + +let sum = + List.fold_left (+) 0 + +let product = + List.fold_left ( * ) 1 + +let concat_map f xs = + List.fold_right ((@) $ f) xs [] + +let maximum xs = + fold_left1 max xs + +let minimum xs = + fold_left1 min xs + +let rec scanl f y = + function + [] -> + [y] + | x::xs -> + y::scanl f (f y x) xs + +let scanl1 f = + function + [] -> + [] + | x::xs -> + scanl f x xs + +let rec scanr f z = + function + [] -> + [z] + | x::xs -> + match scanr f z xs with + y::_ as yss -> + (f x y) :: yss + | _ -> + failwith "must not happen" + +let scanr1 f = + function + [] -> + [] + | x::xs -> + scanr f x xs + +let replicate n x = + let rec loop i ys = + if i = 0 then + ys + else + loop (i-1) (x::ys) in + loop n [] + +let rec take n = + function + [] -> + [] + | x::xs -> + if n <= 0 then + [] + else + x :: take (n - 1) xs + +let rec drop n = + function + [] -> + [] + | xs when n <= 0 -> + xs + | _::xs -> + drop (n-1) xs + +let rec splitAt n xs = + match n,xs with + 0,_ | _,[] -> + [],xs + | _,y::ys -> + let p,q = + splitAt (n-1) ys in + y::p,q + +let rec takeWhile f = + function + x::xs when f x -> + x :: takeWhile f xs + | _ -> + [] + +let rec dropWhile f = + function + x::xs when f x -> + dropWhile f xs + | xs -> + xs + +let rec span f = + function + x::xs when f x -> + let ys,zs = + span f xs in + x::ys,zs + | xs -> + [],xs + +let break f = + span (not $ f) + +let rec zip_with f xs ys = + match xs,ys with + [],_ | _,[] -> + [] + | x::xs',y::ys' -> + (f x y)::zip_with f xs' ys' + +let rec zip_with3 f xs ys zs = + match xs,ys,zs with + [],_,_ | _,[],_ | _,_,[] -> + [] + | x::xs',y::ys',z::zs' -> + (f x y z)::zip_with3 f xs' ys' zs' + +let zip xs ys = + zip_with (fun x y -> (x,y)) xs ys + +let zip3 xs ys zs = + zip_with3 (fun x y z -> (x,y,z)) xs ys zs + +let unzip xs = + List.fold_right (fun (x,y) (xs,ys) -> (x::xs,y::ys)) xs ([],[]) + +let unzip3 xs = + List.fold_right (fun (x,y,z) (xs,ys,zs) -> (x::xs,y::ys,z::zs)) xs ([],[],[]) + +let lookup x xs = + try + Some (List.assoc x xs) + with Not_found -> + None diff --git a/ocaml/ocaml/main.ml b/ocaml/ocaml/main.ml new file mode 100644 index 00000000..f7c81958 --- /dev/null +++ b/ocaml/ocaml/main.ml @@ -0,0 +1,2 @@ +let _ = + print_endline "hello" diff --git a/ocaml/ocaml/msgpack.mli b/ocaml/ocaml/msgpack.mli new file mode 100644 index 00000000..cd227da5 --- /dev/null +++ b/ocaml/ocaml/msgpack.mli @@ -0,0 +1,46 @@ +(** MessagePack for OCaml *) + +(** Conversion MessagePack object between OCaml and Coq. *) +module Pack : sig + (** exception when MesagePack object is invalid form *) + exception Not_conversion of string +end + +(** MessagePack Serializer *) +module Serialize : sig + (** MesagePack object. See also {{:http://redmine.msgpack.org/projects/msgpack/wiki/FormatSpec}MessagePack specification}. *) + type t = + [ `Bool of bool + | `Nil + | `PFixnum of int + | `NFixnum of int + | `Uint8 of int + | `Uint16 of int + | `Uint32 of int64 + | `Uint64 of Big_int.big_int + | `Int8 of int + | `Int16 of int + | `Int32 of int32 + | `Int64 of int64 + | `Float of float + | `Double of float + | `FixRaw of char list + | `Raw16 of char list + | `Raw32 of char list + | `FixArray of t list + | `Array16 of t list + | `Array32 of t list + | `FixMap of (t * t) list + | `Map16 of (t * t) list + | `Map32 of (t * t) list ] + + (** [MessagePack.Serialize.deserialize_string str] deserialize MessagePack string [str] to MessagePack object. *) + val deserialize_string : string -> t + + (** [MessagePack.Serialize.serialize_string obj] serialize MessagePack object [obj] to MessagePack string. *) + val serialize_string : t -> string +end + +module Config : sig + val version : int * int * int +end diff --git a/ocaml/ocaml/pack.ml b/ocaml/ocaml/pack.ml new file mode 100644 index 00000000..e70e96ee --- /dev/null +++ b/ocaml/ocaml/pack.ml @@ -0,0 +1,206 @@ +open Base +open MsgpackCore + +exception Not_conversion of string + +type t = + [ `Bool of bool + | `Nil + | `PFixnum of int + | `NFixnum of int + | `Uint8 of int + | `Uint16 of int + | `Uint32 of int64 + | `Uint64 of Big_int.big_int + | `Int8 of int + | `Int16 of int + | `Int32 of int32 + | `Int64 of int64 + | `Float of float + | `Double of float + | `FixRaw of char list + | `Raw16 of char list + | `Raw32 of char list + | `FixArray of t list + | `Array16 of t list + | `Array32 of t list + | `FixMap of (t * t) list + | `Map16 of (t * t) list + | `Map32 of (t * t) list ] + +let ascii8 n = + Ascii(n land 0b0000_0001 <> 0, + n land 0b0000_0010 <> 0, + n land 0b0000_0100 <> 0, + n land 0b0000_1000 <> 0, + n land 0b0001_0000 <> 0, + n land 0b0010_0000 <> 0, + n land 0b0100_0000 <> 0, + n land 0b1000_0000 <> 0) + +let ascii8_of_char c = + c +> Char.code +> ascii8 + +let ascii16 n = + (ascii8 (n lsr 8), ascii8 n) + +let ascii32 n = + (ascii16 (Int64.to_int (Int64.shift_right_logical n 16)), + ascii16 (Int64.to_int (Int64.logand n 0xFFFFL))) + +let ascii64 n = + let open Big_int in + let x = + shift_right_big_int n 32 + +> int64_of_big_int + +> ascii32 in + let y = + and_big_int n (big_int_of_int64 0xFFFF_FFFFL) + +> int64_of_big_int + +> ascii32 in + (x, y) + +let ascii32_of_int32 n = + (ascii16 (Int32.to_int (Int32.shift_right_logical n 16)), + ascii16 (Int32.to_int n)) + +let ascii64_of_int64 n = + (ascii32 (Int64.shift_right_logical n 32), + ascii32 n) + +let not_conversion msg = + raise @@ Not_conversion msg + +let rec pack = function + `Nil -> + Nil + | `Bool b -> + Bool b + | `PFixnum n -> + if 0 <= n && n < 128 then + PFixnum (ascii8 n) + else + not_conversion "pfixnum" + | `NFixnum n -> + if -32 <= n && n < 0 then + NFixnum (ascii8 n) + else + not_conversion "nfixnum" + | `Uint8 n -> + if 0 <= n && n <= 0xFF then + Uint8 (ascii8 n) + else + not_conversion "uint8" + | `Uint16 n -> + if 0 <= n && n <= 0xFF_FF then + Uint16 (ascii16 n) + else + not_conversion "uint16" + | `Uint32 n -> + if 0L <= n && n <= 0xFFFF_FFFFL then + Uint32 (ascii32 n) + else + not_conversion "uint32" + | `Uint64 n -> + let open Big_int in + let (<=%) = le_big_int in + let (<<) = shift_left_big_int in + if zero_big_int <=% n && n <=% (unit_big_int << 64) then + Uint64 (ascii64 n) + else + not_conversion "uint64" + | `Int8 n -> + if -127 <= n && n <= 128 then + Int8 (ascii8 n) + else + not_conversion "int8" + | `Int16 n -> + if -32767 <= n && n <= 32768 then + Int16 (ascii16 n) + else + not_conversion "int16" + | `Int32 n -> + Int32 (ascii16 (Int32.to_int (Int32.shift_right_logical n 16)), + ascii16 (Int32.to_int n)) + | `Int64 n -> + Int64 (ascii64_of_int64 n) + | `Float n -> + Float (ascii32_of_int32 @@ Int32.bits_of_float n) + | `Double n -> + Double (ascii64_of_int64 @@ Int64.bits_of_float n) + | `FixRaw cs -> + FixRaw (List.map ascii8_of_char cs) + | `Raw16 cs -> + Raw16 (List.map ascii8_of_char cs) + | `Raw32 cs -> + Raw32 (List.map ascii8_of_char cs) + | `FixArray xs -> + FixArray (List.map pack xs) + | `Array16 xs -> + Array16 (List.map pack xs) + | `Array32 xs -> + Array32 (List.map pack xs) + | `FixMap xs -> + FixMap (List.map (fun (x,y) -> (pack x, pack y)) xs) + | `Map16 xs -> + Map16 (List.map (fun (x,y) -> (pack x, pack y)) xs) + | `Map32 xs -> + Map32 (List.map (fun (x,y) -> (pack x, pack y)) xs) + +let of_ascii8 (Ascii(b1,b2,b3,b4,b5,b6,b7,b8)) = + List.fold_left (fun x y -> 2 * x + (if y then 1 else 0)) 0 [ b8; b7; b6; b5; b4; b3; b2; b1 ] + +let char_of_ascii8 c = + c +> of_ascii8 +> Char.chr + +let of_ascii16 (c1, c2) = + of_ascii8 c1 lsl 8 + of_ascii8 c2 + +let of_ascii32 (c1,c2) = + let (+%) = Int64.add in + let (<<) = Int64.shift_left in + ((Int64.of_int (of_ascii16 c1)) << 16) +% Int64.of_int (of_ascii16 c2) + +let int32_of_ascii32 (c1,c2) = + let (+%) = Int32.add in + let (<<) = Int32.shift_left in + ((Int32.of_int @@ of_ascii16 c1) << 16) +% (Int32.of_int @@ of_ascii16 c2) + +let int64_of_ascii64 (c1,c2) = + let (+%) = Int64.add in + let (<<) = Int64.shift_left in + (of_ascii32 c1 << 32) +% (of_ascii32 c2) + +let of_ascii64 (c1, c2) = + let open Big_int in + let (+%) = add_big_int in + let (<<) = shift_left_big_int in + ((big_int_of_int64 @@ of_ascii32 c1) << 32) +% (big_int_of_int64 @@ of_ascii32 c2) + +let int width n = + (n lsl (Sys.word_size-width-1)) asr (Sys.word_size-width-1);; + +let rec unpack = function + | Nil -> `Nil + | Bool b -> `Bool b + | PFixnum c -> `PFixnum (of_ascii8 c) + | NFixnum c -> `NFixnum (int 8 @@ of_ascii8 c) + | Uint8 c -> `Uint8 (of_ascii8 c) + | Uint16 c -> `Uint16 (of_ascii16 c) + | Uint32 c -> `Uint32 (of_ascii32 c) + | Uint64 c -> `Uint64 (of_ascii64 c) + | Int8 c -> `Int8 (int 8 @@ of_ascii8 c) + | Int16 c -> `Int16 (int 16 @@ of_ascii16 c) + | Int32 c -> `Int32 (int32_of_ascii32 c) + | Int64 c -> `Int64 (int64_of_ascii64 c) + | Float c -> `Float (Int32.float_of_bits (int32_of_ascii32 c)) + | Double c -> `Double (Int64.float_of_bits (int64_of_ascii64 c)) + | FixRaw cs -> `FixRaw (List.map char_of_ascii8 cs) + | Raw16 cs -> `Raw16 (List.map char_of_ascii8 cs) + | Raw32 cs -> `Raw32 (List.map char_of_ascii8 cs) + | FixArray xs -> `FixArray (List.map unpack xs) + | Array16 xs -> `Array16 (List.map unpack xs) + | Array32 xs -> `Array32 (List.map unpack xs) + | FixMap xs -> `FixMap (List.map (fun (x,y) -> (unpack x, unpack y)) xs) + | Map16 xs -> `Map16 (List.map (fun (x,y) -> (unpack x, unpack y)) xs) + | Map32 xs -> `Map32 (List.map (fun (x,y) -> (unpack x, unpack y)) xs) diff --git a/ocaml/ocaml/pack.mli b/ocaml/ocaml/pack.mli new file mode 100644 index 00000000..55c4c36a --- /dev/null +++ b/ocaml/ocaml/pack.mli @@ -0,0 +1,32 @@ +exception Not_conversion of string + +type t = + [ `Bool of bool + | `Nil + | `PFixnum of int + | `NFixnum of int + | `Uint8 of int + | `Uint16 of int + | `Uint32 of int64 + | `Uint64 of Big_int.big_int + | `Int8 of int + | `Int16 of int + | `Int32 of int32 + | `Int64 of int64 + | `Float of float + | `Double of float + | `FixRaw of char list + | `Raw16 of char list + | `Raw32 of char list + | `FixArray of t list + | `Array16 of t list + | `Array32 of t list + | `FixMap of (t * t) list + | `Map16 of (t * t) list + | `Map32 of (t * t) list ] + +val pack : t -> MsgpackCore.object0 +val unpack : MsgpackCore.object0 -> t + +val char_of_ascii8 : MsgpackCore.ascii -> char +val ascii8_of_char : char -> MsgpackCore.ascii diff --git a/ocaml/ocaml/packTest.ml b/ocaml/ocaml/packTest.ml new file mode 100644 index 00000000..a68a711a --- /dev/null +++ b/ocaml/ocaml/packTest.ml @@ -0,0 +1,175 @@ +open Base +open OUnit +open MsgpackCore +open Pack +open Printf + +let c0 = + Ascii (false,false,false,false,false,false,false,false) +let c1 = + Ascii (true, false,false,false,false,false,false,false) +let c255 = + Ascii (true,true,true,true,true,true,true,true) + +let valid = [ + "nil",[ + Nil, `Nil + ], []; + "bool",[ + Bool true , `Bool true; + Bool false, `Bool false + ], []; + "pfixnum",[ + PFixnum c0,`PFixnum 0; + PFixnum c1,`PFixnum 1; + ], [ + `PFixnum 128; + `PFixnum (~-1); + ]; + "nfixnum",[ + NFixnum c255, `NFixnum ~-1; + NFixnum (Ascii (false,false,false,false,false,true,true,true)), `NFixnum ~-32 + ],[ + `NFixnum 0; + `NFixnum (~-33) + ]; + "uint8", [ + Uint8 c0, `Uint8 0; + Uint8 c1, `Uint8 1; + Uint8 c255, `Uint8 255 + ],[ + `Uint8 ~-1; + `Uint8 256 + ]; + "uint16", [ + Uint16 (c0,c0), `Uint16 0; + Uint16 (c0,c1), `Uint16 1; + Uint16 (c1,c0), `Uint16 256; + Uint16 (c255,c255), `Uint16 65535; + ],[ + `Uint16 ~-1; + `Uint16 65536 + ]; + "uint32", [ + Uint32 ((c0,c0), (c0,c0)), `Uint32 0L; + Uint32 ((c255,c255), (c255,c255)), `Uint32 0xFFFF_FFFFL + ],[ + `Uint32 (-1L); + `Uint32 0x1FFFF_FFFFL + ]; + "uint64", [ + Uint64 (((c0,c0), (c0,c0)),((c0,c0), (c0,c0))), `Uint64 Big_int.zero_big_int; + Uint64 (((c0,c0), (c0,c0)),((c0,c0), (c0,c1))), `Uint64 Big_int.unit_big_int; + Uint64 (((c255,c255), (c255,c255)),((c255,c255), (c255,c255))), `Uint64 (Big_int.big_int_of_string "18446744073709551615") + ],[ + `Uint64 (Big_int.big_int_of_string "-1"); + `Uint64 (Big_int.big_int_of_string "18446744073709551617") + ]; + "int8", [ + Int8 c0, `Int8 0; + Int8 c1, `Int8 1; + Int8 c255, `Int8 (~-1) + ],[ + `Int8 129 + ]; + "int16", [ + Int16 (c0,c0), `Int16 0; + Int16 (c0,c1), `Int16 1; + Int16 (c1,c0), `Int16 256; + Int16 (c255,c255), `Int16 ~-1; + ],[ + `Int16 65536 + ]; + "int32", [ + Int32 ((c0,c0), (c0,c0)), `Int32 0l; + Int32 ((c255,c255), (c255,c255)), `Int32 (-1l) + ],[]; + "int64", [ + Int64 (((c0,c0), (c0,c0)),((c0,c0), (c0,c0))), `Int64 0L; + Int64 (((c0,c0), (c0,c0)),((c0,c0), (c0,c1))), `Int64 1L; + Int64 (((c255,c255), (c255,c255)),((c255,c255), (c255,c255))), `Int64 (-1L) + ],[]; + "float", [ + Float ((c0,c0),(c0,c0)), `Float 0.0; + (* 0.5 = 3f_00_00_00 *) + Float ((Ascii (true,true,true,true,true,true,false,false),c0),(c0,c0)), `Float 0.5; + ], []; + "double", [ + Double (((c0,c0),(c0,c0)),((c0,c0),(c0,c0))), `Double 0.0; + (* 0.5 = 3f_e0_00_00_00_00_00_00 *) + Double (((Ascii (true,true,true,true,true,true,false,false), + Ascii (false,false,false,false,false,true,true,true)), + (c0,c0)), + ((c0,c0),(c0,c0))), `Double 0.5 + ],[]; + "fixraw", [ + FixRaw [], `FixRaw []; + FixRaw [ c0 ], `FixRaw [ '\000']; + FixRaw [ c0; c1 ], `FixRaw [ '\000'; '\001']; + ],[]; + "raw16", [ + Raw16 [], `Raw16 []; + Raw16 [ c0 ], `Raw16 [ '\000']; + Raw16 [ c0; c1 ], `Raw16 [ '\000'; '\001']; + ], []; + "raw32", [ + Raw32 [], `Raw32 []; + Raw32 [ c0 ], `Raw32 [ '\000']; + Raw32 [ c0; c1 ], `Raw32 [ '\000'; '\001']; + ], []; + "fixarray", [ + FixArray [], `FixArray []; + FixArray [ PFixnum c0 ], `FixArray [`PFixnum 0 ]; + FixArray [ FixArray [ PFixnum c0 ] ], `FixArray [`FixArray [ `PFixnum 0] ]; + ], []; + "array16", [ + Array16 [], `Array16 []; + Array16 [ PFixnum c0 ], `Array16 [`PFixnum 0 ]; + Array16 [ Array16 [ PFixnum c0 ] ], `Array16 [`Array16 [ `PFixnum 0] ]; + ], []; + "array32", [ + Array32 [], `Array32 []; + Array32 [ PFixnum c0 ], `Array32 [`PFixnum 0 ]; + Array32 [ Array32 [ PFixnum c0 ] ], `Array32 [`Array32 [ `PFixnum 0] ]; + ], []; + "fixmap", [ + FixMap [], `FixMap []; + FixMap [ PFixnum c0, PFixnum c1 ], `FixMap [`PFixnum 0, `PFixnum 1 ]; + ], []; + "map16", [ + Map16 [], `Map16 []; + Map16 [ PFixnum c0, PFixnum c1 ], `Map16 [`PFixnum 0, `PFixnum 1 ]; + ], []; + "map32", [ + Map32 [], `Map32 []; + Map32 [ PFixnum c0, PFixnum c1 ], `Map32 [`PFixnum 0, `PFixnum 1 ]; + ], []; +] + + +let _ = begin "pack.ml" >::: [ + "変換のテスト" >::: + valid +> HList.concat_map begin fun (name, ok, ng) -> + let xs = + ok +> List.map begin fun (expect, actual) -> + (sprintf "%sが変換できる" name) >:: (fun _ -> assert_equal expect (pack actual)); + end in + let ys = + ng +> List.map begin fun actual -> + (sprintf "%sのエラーチェック" name) >:: (fun _ -> assert_raises (Not_conversion name) (fun () -> pack actual)) + end in + xs @ ys + end; + "復元のテスト" >::: + valid +> HList.concat_map begin fun (name, ok, _) -> + ok +> List.map begin fun (actual, expect) -> + (sprintf "%sが復元できる" name) >:: begin fun _ -> + match expect, unpack actual with + `Uint64 n1, `Uint64 n2 -> + assert_equal ~cmp:Big_int.eq_big_int n1 n2 + | x, y -> + assert_equal x y + end + end + end; +] end +> run_test_tt_main diff --git a/ocaml/ocaml/serialize.ml b/ocaml/ocaml/serialize.ml new file mode 100644 index 00000000..e6e30d75 --- /dev/null +++ b/ocaml/ocaml/serialize.ml @@ -0,0 +1,20 @@ +open Base +open ExtString + +type t = Pack.t + +let deserialize_string str = + str + +> String.explode + +> List.map Pack.ascii8_of_char + +> MsgpackCore.deserialize 0 + +> List.hd + +> Pack.unpack + +let serialize_string obj = + obj + +> Pack.pack + +> MsgpackCore.serialize + +> List.map Pack.char_of_ascii8 + +> String.implode + diff --git a/ocaml/ocaml/serialize.mli b/ocaml/ocaml/serialize.mli new file mode 100644 index 00000000..69719e55 --- /dev/null +++ b/ocaml/ocaml/serialize.mli @@ -0,0 +1,4 @@ +type t = Pack.t + +val deserialize_string : string -> t +val serialize_string : t -> string diff --git a/ocaml/ocaml/serializeTest.ml b/ocaml/ocaml/serializeTest.ml new file mode 100644 index 00000000..32c8bab4 --- /dev/null +++ b/ocaml/ocaml/serializeTest.ml @@ -0,0 +1,16 @@ +open Base +open OUnit +open Serialize + +let _ = begin "serialize.ml" >::: [ + "Rubyのライブラリとの互換テスト(deserialize)" >:: begin fun _ -> + (* [1,2,3].to_msgpack *) + assert_equal (`FixArray [`PFixnum 1; `PFixnum 2; `PFixnum 3]) @@ + deserialize_string "\147\001\002\003" + end; + "Rubyのライブラリとの互換テスト(serialize)" >:: begin fun _ -> + assert_equal "\147\001\002\003" @@ + serialize_string @@ `FixArray [`PFixnum 1; `PFixnum 2; `PFixnum 3] + end +] end +> run_test_tt_main + diff --git a/ocaml/proof/.gitignore b/ocaml/proof/.gitignore new file mode 100644 index 00000000..ffb82899 --- /dev/null +++ b/ocaml/proof/.gitignore @@ -0,0 +1,2 @@ +msgpackCore.ml +msgpackCore.mli diff --git a/ocaml/proof/CoqBuildRule b/ocaml/proof/CoqBuildRule new file mode 100644 index 00000000..57be1c52 --- /dev/null +++ b/ocaml/proof/CoqBuildRule @@ -0,0 +1,14 @@ +public.COQC = coqc +public.COQC_FLAGS = +public.COQLIB = $(shell coqc -where) +public.COQDEP = coqdep -w -coqlib $`(COQLIB) -I . + +public.CoqProof(files) = + vo=$(addsuffix .vo,$(files)) + value $(vo) + +%.vo %.glob: %.v + $(COQC) $(COQC_FLAGS) $< + +.SCANNER: %.vo: %.v + $(COQDEP) $< diff --git a/ocaml/proof/DeserializeImplement.v b/ocaml/proof/DeserializeImplement.v new file mode 100644 index 00000000..f9e1f728 --- /dev/null +++ b/ocaml/proof/DeserializeImplement.v @@ -0,0 +1,630 @@ +Require Import Ascii List. +Require Import ListUtil Object MultiByte Util SerializeSpec Pow SerializedList ProofUtil. + +Open Scope char_scope. + +Definition compact (xs : list object) : list ascii8 := + List.flat_map (fun x => match x with + FixRaw xs => xs + | _ => [] + end) + xs. + +Fixpoint deserialize (n : nat) (xs : list ascii8) {struct xs} := + match n with + | 0 => + match xs with + | "192" :: ys => + Nil::deserialize 0 ys + | "194" :: ys => + Bool false :: deserialize 0 ys + | "195" :: ys => + Bool true :: deserialize 0 ys + | Ascii b1 b2 b3 b4 b5 b6 b7 false :: ys => + PFixnum (Ascii b1 b2 b3 b4 b5 b6 b7 false) :: deserialize 0 ys + | (Ascii b1 b2 b3 b4 b5 true true true) :: ys => + NFixnum (Ascii b1 b2 b3 b4 b5 true true true) :: deserialize 0 ys + | "204" :: c1 :: ys => + Uint8 c1 :: deserialize 0 ys + | "205" :: c1 :: c2 :: ys => + Uint16 (c1, c2) :: deserialize 0 ys + | "206" :: c1 :: c2 :: c3 :: c4 :: ys => + Uint32 ((c1, c2), (c3, c4)) :: deserialize 0 ys + | "207" :: c1 :: c2 :: c3 :: c4 :: c5 :: c6 :: c7 :: c8 :: ys => + Uint64 (((c1, c2), (c3, c4)), ((c5, c6), (c7, c8))) :: deserialize 0 ys + | "208" :: c1 :: ys => + Int8 c1 :: deserialize 0 ys + | "209" :: c1 :: c2 :: ys => + Int16 (c1, c2) :: deserialize 0 ys + | "210" :: c1 :: c2 :: c3 :: c4 :: ys => + Int32 ((c1, c2), (c3, c4)) :: deserialize 0 ys + | "211" :: c1 :: c2 :: c3 :: c4 :: c5 :: c6 :: c7 :: c8 :: ys => + Int64 (((c1, c2), (c3, c4)), ((c5, c6), (c7, c8))) :: deserialize 0 ys + | "202" :: c1 :: c2 :: c3 :: c4 :: ys => + Float ((c1,c2), (c3, c4)) :: deserialize 0 ys + | "203" :: c1 :: c2 :: c3 :: c4 :: c5 :: c6 :: c7 :: c8 :: ys => + Double (((c1, c2), (c3, c4)), ((c5, c6), (c7, c8))) :: deserialize 0 ys + | Ascii b1 b2 b3 b4 b5 true false true :: ys => + let n := + nat_of_ascii8 (Ascii b1 b2 b3 b4 b5 false false false) in + let (zs, ws) := + split_at n @@ deserialize n ys in + FixRaw (compact zs) :: ws + | "218" :: s1 :: s2 :: ys => + let n := + nat_of_ascii16 (s1,s2) in + let (zs, ws) := + split_at n @@ deserialize n ys in + Raw16 (compact zs) :: ws + | "219" :: s1 :: s2 :: s3 :: s4 :: ys => + let n := + nat_of_ascii32 ((s1,s2),(s3,s4)) in + let (zs, ws) := + split_at n @@ deserialize n ys in + Raw32 (compact zs) :: ws + | Ascii b1 b2 b3 b4 true false false true :: ys => + let n := + nat_of_ascii8 (Ascii b1 b2 b3 b4 false false false false) in + let (zs, ws) := + split_at n @@ deserialize 0 ys in + FixArray zs :: ws + | "220" :: s1 :: s2 :: ys => + let n := + nat_of_ascii16 (s1,s2) in + let (zs, ws) := + split_at n @@ deserialize 0 ys in + Array16 zs :: ws + | "221" :: s1 :: s2 :: s3 :: s4 :: ys => + let n := + nat_of_ascii32 ((s1, s2), (s3, s4)) in + let (zs, ws) := + split_at n @@ deserialize 0 ys in + Array32 zs :: ws + | Ascii b1 b2 b3 b4 false false false true :: ys => + let n := + nat_of_ascii8 (Ascii b1 b2 b3 b4 false false false false) in + let (zs, ws) := + split_at (2 * n) @@ deserialize 0 ys in + FixMap (pair zs) :: ws + | "222" :: s1 :: s2 :: ys => + let n := + nat_of_ascii16 (s1,s2) in + let (zs, ws) := + split_at (2 * n) @@ deserialize 0 ys in + Map16 (pair zs) :: ws + | "223" :: s1 :: s2 :: s3 :: s4 :: ys => + let n := + nat_of_ascii32 ((s1, s2), (s3, s4)) in + let (zs, ws) := + split_at (2 * n) @@ deserialize 0 ys in + Map32 (pair zs) :: ws + | _ => + [] + end + | S m => + match xs with + | y::ys => FixRaw [ y ]::deserialize m ys + | _ => [] + end + end. + +Definition DeserializeCorrect os bs := + SerializedList os bs -> + deserialize 0 bs = os. + +Lemma correct_bot : + DeserializeCorrect [] []. +Proof with auto. +unfold DeserializeCorrect... +Qed. + +Lemma correct_nil : forall os bs, + DeserializeCorrect os bs -> + DeserializeCorrect (Nil :: os) ("192"::bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H0. +apply H in H3. +rewrite <- H3... +Qed. + +Lemma correct_false: forall os bs, + DeserializeCorrect os bs -> + DeserializeCorrect ((Bool false) :: os) ("194"::bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H0. +apply H in H3. +rewrite <- H3... +Qed. + +Lemma correct_true: forall os bs, + DeserializeCorrect os bs -> + DeserializeCorrect ((Bool true) :: os) ("195"::bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H0. +apply H in H3. +rewrite <- H3... +Qed. + +Lemma correct_pfixnum: forall os bs x1 x2 x3 x4 x5 x6 x7, + DeserializeCorrect os bs -> + DeserializeCorrect ((PFixnum (Ascii x1 x2 x3 x4 x5 x6 x7 false))::os) + ((Ascii x1 x2 x3 x4 x5 x6 x7 false)::bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H0. +apply H in H2. +rewrite <- H2. +destruct x1,x2,x3,x4,x5,x6,x7; reflexivity. +Qed. + +Lemma correct_nfixnum: forall os bs x1 x2 x3 x4 x5, + DeserializeCorrect os bs -> + DeserializeCorrect + ((NFixnum (Ascii x1 x2 x3 x4 x5 true true true))::os) + ((Ascii x1 x2 x3 x4 x5 true true true)::bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H0. +apply H in H2. +rewrite <- H2. +destruct x1,x2,x3,x4,x5; reflexivity. +Qed. + +Lemma correct_uint8 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Uint8 c)::os) ("204"::list_of_ascii8 c ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H0. +apply H in H2. +rewrite <- H2... +Qed. + +Lemma correct_uint16 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Uint16 c)::os) ("205"::list_of_ascii16 c ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +destruct c. +inversion H0. +apply H in H2. +rewrite <- H2... +Qed. + +Lemma correct_uint32 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Uint32 c)::os) ("206"::list_of_ascii32 c ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +destruct c. +destruct a, a0. +inversion H0. +apply H in H2. +rewrite <- H2... +Qed. + +Lemma correct_uint64 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Uint64 c)::os) ("207"::list_of_ascii64 c ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +destruct c. +destruct a, a0. +destruct a, a0, a1, a2. +inversion H0. +apply H in H2. +rewrite <- H2... +Qed. + +Lemma correct_int8 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Int8 c)::os) ("208"::list_of_ascii8 c ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H0. +apply H in H2. +rewrite <- H2... +Qed. + +Lemma correct_int16 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Int16 c)::os) ("209"::list_of_ascii16 c ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +destruct c. +inversion H0. +apply H in H2. +rewrite <- H2... +Qed. + +Lemma correct_int32 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Int32 c)::os) ("210"::list_of_ascii32 c ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +destruct c. +destruct a, a0. +inversion H0. +apply H in H2. +rewrite <- H2... +Qed. + +Lemma correct_int64 : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Int64 c)::os) ("211"::list_of_ascii64 c ++ bs). +Proof. +unfold DeserializeCorrect. +intros. +destruct c. +destruct a, a0. +destruct a, a0, a1, a2. +inversion H0. +apply H in H2. +rewrite <- H2. +reflexivity. +Qed. + +Lemma correct_float : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Float c)::os) ("202"::list_of_ascii32 c ++ bs). +Proof. +unfold DeserializeCorrect. +intros. +destruct c. +destruct a, a0. +inversion H0. +apply H in H2. +rewrite <- H2. +reflexivity. +Qed. + +Lemma correct_double : forall os bs c, + DeserializeCorrect os bs -> + DeserializeCorrect ((Double c)::os) ("203"::list_of_ascii64 c ++ bs). +Proof. +unfold DeserializeCorrect. +intros. +destruct c. +destruct a, a0. +destruct a, a0, a1, a2. +inversion H0. +apply H in H2. +rewrite <- H2. +reflexivity. +Qed. + +Lemma deserialize_take_length: forall xs ys, + take (List.length xs) (deserialize (List.length xs) (xs ++ ys)) = List.map (fun x => FixRaw [ x ]) xs. +Proof with auto. +induction xs; [ reflexivity | intros ]. +simpl. +rewrite IHxs... +Qed. + +Lemma deserialize_drop_length: forall xs ys, + drop (List.length xs) (deserialize (List.length xs) (xs ++ ys)) = deserialize 0 ys. +Proof with auto. +induction xs; [ reflexivity | intros ]. +simpl. +rewrite IHxs... +Qed. + +Lemma compact_eq : forall xs, + compact (List.map (fun x => FixRaw [ x ]) xs) = xs. +Proof with auto. +induction xs; [ reflexivity | intros ]. +simpl. +rewrite IHxs... +Qed. + +Lemma correct_fixraw: forall os bs cs b1 b2 b3 b4 b5, + DeserializeCorrect os bs -> + Ascii b1 b2 b3 b4 b5 false false false = ascii8_of_nat (List.length cs) -> + List.length cs < pow 5 -> + DeserializeCorrect (FixRaw cs :: os) ((Ascii b1 b2 b3 b4 b5 true false true) :: cs ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H2. +assert (bs0 = bs); [| rewrite_for bs0 ]. + apply app_same in H11... +apply H in H13. +assert (length cs < pow 8). + transitivity (pow 5); auto. + apply pow_lt... +destruct b1,b2,b3,b4,b5; + ((replace (deserialize 0 _ ) with + (let n := nat_of_ascii8 (ascii8_of_nat (length cs)) in + let (zs, ws) := split_at n @@ deserialize n (cs++bs) in + FixRaw (compact zs) :: ws)); + [ unfold atat, split_at; + rewrite nat_ascii8_embedding, deserialize_take_length, deserialize_drop_length, compact_eq, <- H13 + | rewrite <- H7])... +Qed. + +Lemma correct_raw16: forall os bs cs s1 s2, + DeserializeCorrect os bs -> + (s1, s2) = ascii16_of_nat (List.length cs) -> + List.length cs < pow 16 -> + DeserializeCorrect (Raw16 cs :: os) ("218" :: s1 :: s2 :: cs ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H2. +assert (bs0 = bs); [| rewrite_for bs0 ]. + apply app_same in H8... +apply H in H10. +change (deserialize 0 _ ) with + (let (zs, ws) := + split_at (nat_of_ascii16 (s1,s2)) @@ deserialize (nat_of_ascii16 (s1,s2)) (cs++bs) in + Raw16 (compact zs) :: ws). +unfold atat, split_at. +rewrite H7, nat_ascii16_embedding, deserialize_take_length, deserialize_drop_length, compact_eq, H10... +Qed. + +Lemma correct_raw32: forall os bs cs s1 s2 s3 s4, + DeserializeCorrect os bs -> + ((s1, s2), (s3, s4)) = ascii32_of_nat (List.length cs) -> + List.length cs < pow 32 -> + DeserializeCorrect (Raw32 cs :: os) ("219" :: s1 :: s2 :: s3 :: s4 :: cs ++ bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H2. +assert (bs0 = bs); [| rewrite_for bs0 ]. + apply app_same in H10... +apply H in H12. +change (deserialize 0 _ ) with + (let (zs, ws) := + split_at (nat_of_ascii32 ((s1,s2),(s3,s4))) @@ deserialize (nat_of_ascii32 ((s1,s2),(s3,s4))) (cs++bs) in + Raw32 (compact zs) :: ws). +unfold atat, split_at. +rewrite H7, nat_ascii32_embedding, deserialize_take_length, deserialize_drop_length, compact_eq, H12... +Qed. + +Lemma correct_fixarray : forall os bs n xs ys b1 b2 b3 b4, + DeserializeCorrect os bs -> + (xs, ys) = split_at n os -> + n < pow 4 -> + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat n -> + DeserializeCorrect (FixArray xs :: ys) (Ascii b1 b2 b3 b4 true false false true :: bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H3. +assert (os = os0); [| rewrite_for os0 ]. + apply split_at_soundness in H0. + apply split_at_soundness in H12. + rewrite H0, H12... +apply H in H9. +assert (n0 < pow 8). + transitivity (pow 4); auto. + apply pow_lt... +destruct b1, b2, b3, b4; + (replace (deserialize 0 (_ :: bs)) with + (let (zs, ws) := + split_at (nat_of_ascii8 (ascii8_of_nat n0)) @@ deserialize 0 bs + in + FixArray zs :: ws); + [ unfold atat; rewrite H9, nat_ascii8_embedding, <- H12 | rewrite <- H14])... +Qed. + +Lemma correct_array16 : forall os bs n xs ys s1 s2 , + DeserializeCorrect os bs -> + n < pow 16 -> + (s1, s2) = ascii16_of_nat n -> + (xs, ys) = split_at n os -> + DeserializeCorrect (Array16 xs :: ys) ("220" :: s1 :: s2 :: bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H3. +assert (os = os0). + apply split_at_soundness in H2. + apply split_at_soundness in H10. + rewrite H2, H10... + + rewrite_for os0. + apply H in H9. + assert ( n = nat_of_ascii16 (s1, s2)). + rewrite H1. + rewrite nat_ascii16_embedding... + + simpl. + change (nat_of_ascii8 s1 * 256 + nat_of_ascii8 s2) with (nat_of_ascii16 (s1, s2)). + rewrite <- H13. + inversion H2. + rewrite <- H9... +Qed. + +Lemma correct_array32: forall os bs n xs ys s1 s2 s3 s4, + DeserializeCorrect os bs -> + (xs, ys) = split_at n os -> + n < pow 32 -> + ((s1, s2), (s3, s4)) = ascii32_of_nat n -> + DeserializeCorrect (Array32 xs :: ys) ("221" :: s1 :: s2 :: s3 :: s4 :: bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H3. +assert (os = os0). + apply split_at_soundness in H0. + apply split_at_soundness in H12. + rewrite H0, H12... + + rewrite_for os0. + apply H in H9. + change (deserialize 0 ("221" :: s1 :: s2 :: s3 :: s4 :: bs)) with + (let (zs, ws) := split_at (nat_of_ascii32 (s1, s2, (s3, s4))) (deserialize 0 bs) in + Array32 zs :: ws). + rewrite H9, H14, nat_ascii32_embedding, <- H12... +Qed. + +Lemma correct_fixmap: forall os bs n xs ys b1 b2 b3 b4, + DeserializeCorrect os bs -> + (xs, ys) = split_at (2 * n) os -> + length xs = 2 * n -> + n < pow 4 -> + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat n -> + DeserializeCorrect (FixMap (pair xs) :: ys) (Ascii b1 b2 b3 b4 false false false true :: bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H4. +assert ( n < pow 8). + transitivity (pow 4); auto. + apply pow_lt... +assert ( n0 < pow 8). + transitivity (pow 4); auto. + apply pow_lt... +assert (n0 = n); [| rewrite_for n0 ]. + rewrite H3 in H16. + apply ascii8_of_nat_eq in H16... +assert (xs0 = xs); [| rewrite_for xs0 ]. + rewrite <- (unpair_pair _ n xs), <- (unpair_pair _ n xs0); auto. + rewrite H5... +assert (os0 = os); [| rewrite_for os0 ]. + apply split_at_soundness in H0. + apply split_at_soundness in H13. + rewrite H0, H13... +apply H in H11. +destruct b1, b2, b3, b4; + (replace (deserialize 0 (_ :: bs)) with + (let (zs, ws) := + split_at (2 * (nat_of_ascii8 (ascii8_of_nat n))) @@ deserialize 0 bs + in + FixMap (pair zs) :: ws); + [ unfold atat; rewrite nat_ascii8_embedding, H11, <- H13 + | rewrite <- H16 ])... +Qed. + +Lemma correct_map16: forall os bs n xs ys s1 s2, + DeserializeCorrect os bs -> + (xs, ys) = split_at (2 * n) os -> + length xs = 2 * n -> + n < pow 16 -> + (s1, s2) = ascii16_of_nat n -> + DeserializeCorrect (Map16 (pair xs) :: ys) ("222" :: s1 :: s2 :: bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H4. +assert (n0 = n). + rewrite H3 in H14. + apply ascii16_of_nat_eq in H14... +rewrite_for n0. +assert (xs0 = xs). + rewrite <- (unpair_pair _ n xs), <- (unpair_pair _ n xs0); auto. + rewrite H5... +rewrite_for xs0. +assert (os0 = os). + apply split_at_soundness in H0. + apply split_at_soundness in H11. + rewrite H0, H11... +rewrite_for os0. +apply H in H10. +change (deserialize 0 ("222" :: s1 :: s2 :: bs)) with + (let (zs, ws) := split_at (2 * nat_of_ascii16 (s1, s2)) @@ deserialize 0 bs in + Map16 (pair zs) :: ws). +unfold atat. +rewrite H10, H14, nat_ascii16_embedding, <- H11... +Qed. + +Lemma correct_map32: forall os bs n xs ys s1 s2 s3 s4, + DeserializeCorrect os bs -> + (xs, ys) = split_at (2 * n) os -> + length xs = 2 * n -> + n < pow 32 -> + ((s1, s2), (s3, s4)) = ascii32_of_nat n -> + DeserializeCorrect (Map32 (pair xs) :: ys) ("223" :: s1 :: s2 :: s3 :: s4 :: bs). +Proof with auto. +unfold DeserializeCorrect. +intros. +inversion H4. +assert (n0 = n); [| rewrite_for n0 ]. + rewrite H3 in H16. + apply ascii32_of_nat_eq in H16... +assert (xs0 = xs); [| rewrite_for xs0 ]. + rewrite <- (unpair_pair _ n xs), <- (unpair_pair _ n xs0); auto. + rewrite H5... +assert (os0 = os); [| rewrite_for os0 ]. + apply split_at_soundness in H0. + apply split_at_soundness in H13. + rewrite H0, H13... +apply H in H11. +change (deserialize 0 ("223" :: s1 :: s2 :: s3 :: s4 :: bs)) with + (let (zs, ws) := split_at (2 * nat_of_ascii32 ((s1, s2),(s3,s4))) @@ deserialize 0 bs in + Map32 (pair zs) :: ws). +unfold atat. +rewrite H16, H11, nat_ascii32_embedding, <- H13... +Qed. + +Lemma correct_intro : forall os bs, + (SerializedList os bs -> DeserializeCorrect os bs) -> + DeserializeCorrect os bs. +Proof with auto. +unfold DeserializeCorrect. +intros. +apply H in H0... +Qed. + +Theorem deserialize_correct : forall os bs, + DeserializeCorrect os bs. +Proof with auto. +intros. +apply correct_intro. +intros. +pattern os, bs. +apply SerializedList_ind; intros; auto. + apply correct_bot... + apply correct_nil... + apply correct_true... + apply correct_false... + apply correct_pfixnum... + apply correct_nfixnum... + apply correct_uint8... + apply correct_uint16... + apply correct_uint32... + apply correct_uint64... + apply correct_int8... + apply correct_int16... + apply correct_int32... + apply correct_int64... + apply correct_float... + apply correct_double... + apply correct_fixraw... + simpl; apply correct_raw16... + simpl; apply correct_raw32... + apply correct_fixarray with (os:=os0) (n:=n)... + apply correct_array16 with (os:=os0) (n:=n)... + apply correct_array32 with (os:=os0) (n:=n)... + apply correct_fixmap with (os:=os0) (n:=n)... + apply correct_map16 with (os:=os0) (n:=n)... + apply correct_map32 with (os:=os0) (n:=n)... +Qed. + +Lemma app_nil: forall A (xs : list A), + xs ++ [] = xs. +Proof. +induction xs. + reflexivity. +simpl. +rewrite IHxs. +reflexivity. +Qed. + diff --git a/ocaml/proof/ExtractUtil.v b/ocaml/proof/ExtractUtil.v new file mode 100644 index 00000000..42fcbca4 --- /dev/null +++ b/ocaml/proof/ExtractUtil.v @@ -0,0 +1,95 @@ +Require Ascii. +Require String. +Require List. + + +(* basic types for OCaml *) +Parameter mlunit mlchar mlint mlstring : Set. + +(* unit *) +Extract Constant mlunit => "unit". + +(* bool *) +Extract Inductive bool => "bool" ["true" "false"]. +Extract Inductive sumbool => "bool" ["true" "false"]. + +(* int *) +Extract Constant mlint => "int". +Parameter mlint_of_nat : nat -> mlint. +Parameter nat_of_mlint : mlint -> nat. +Extract Constant mlint_of_nat => + "let rec iter = function O -> 0 | S p -> succ (iter p) in iter". +Extract Constant nat_of_mlint => + "let rec iter = function 0 -> O | n -> S (iter (pred n)) in iter". + +(* char *) +Extract Constant mlchar => "char". +Parameter mlchar_of_mlint : mlint -> mlchar. +Parameter mlint_of_mlchar : mlchar -> mlint. +Extract Constant mlchar_of_mlint => "char_of_int". +Extract Constant mlint_of_mlchar => "int_of_char". + +(* list *) +Extract Inductive list => "list" ["[]" "(::)"]. + +(* option *) +Extract Inductive option => "option" ["None" "Some"]. + +(* string *) +Extract Constant mlstring => "string". +Extract Inductive String.string => "ascii list" ["[]" "(::)"]. +Parameter string_of_list : List.list Ascii.ascii -> String.string. +Parameter list_of_string : String.string -> List.list Ascii.ascii. +Extract Constant list_of_string => "(fun x -> x)". +Extract Constant string_of_list => "(fun x -> x)". + +Parameter mlstring_of_list : forall {A:Type}, + (A->mlchar) -> List.list A -> mlstring. +Parameter list_of_mlstring : forall {A:Type}, + (mlchar->A) -> mlstring -> List.list A. +Extract Constant mlstring_of_list => + "(fun f s -> String.concat """" + (List.map (fun x -> String.make 1 (f x)) s))". +Extract Constant list_of_mlstring => " +(fun f s -> + let rec explode_rec n = + if n >= String.length s then + [] + else + f (String.get s n) :: explode_rec (succ n) + in + explode_rec 0) +". + +Parameter mlstring_of_mlint : mlint -> mlstring. +Extract Constant mlstring_of_mlint => "string_of_int". + + +(* print to stdout *) +Parameter print_mlstring : mlstring -> mlunit. +Parameter println_mlstring : mlstring -> mlunit. +Parameter prerr_mlstring : mlstring -> mlunit. +Parameter prerrln_mlstring : mlstring -> mlunit. +Parameter semicolon_flipped : forall {A:Type}, A -> mlunit -> A. +Extract Constant semicolon_flipped => "(fun x f -> f; x)". +Extract Constant print_mlstring => "print_string". +Extract Constant println_mlstring => "print_endline". +Extract Constant prerr_mlstring => "print_string". +Extract Constant prerrln_mlstring => "print_endline". + +CoInductive llist (A: Type) : Type := + LNil | LCons (x: A) (xs: llist A). + +Implicit Arguments LNil [A]. +Implicit Arguments LCons [A]. + +Parameter get_contents_mlchars : llist mlchar. +Extract Constant get_contents_mlchars => " + let rec iter store = + lazy + begin + try (LCons (input_char stdin, iter())) with + | End_of_file -> LNil + end + in + iter ()". diff --git a/ocaml/proof/ListUtil.v b/ocaml/proof/ListUtil.v new file mode 100644 index 00000000..22a82821 --- /dev/null +++ b/ocaml/proof/ListUtil.v @@ -0,0 +1,259 @@ +Require Import List Omega. + +Notation "[ ]" := nil : list_scope. +Notation "[ a ; .. ; b ]" := (a :: .. (b :: []) ..) : list_scope. + +Lemma app_same : forall A (xs ys zs : list A), + xs ++ ys = xs ++ zs -> ys = zs. +Proof. +induction xs; intros; simpl in H. + auto. + + inversion H. + apply IHxs in H1. + auto. +Qed. +Lemma length_lt_O: forall A (x : A) xs, + length (x::xs) > 0. +Proof. +intros. +simpl. +omega. +Qed. + +Lemma length_inv: forall A (x y : A) xs ys, + length (x :: xs) = length (y :: ys) -> + length xs = length ys. +Proof. +intros. +inversion H. +auto. +Qed. + +Hint Resolve length_lt_O. + + +Fixpoint take {A} n (xs : list A) := + match n, xs with + | O , _ => [] + | _ , [] => [] + | S m, x::xs => + x::take m xs + end. + +Fixpoint drop {A} n (xs : list A) := + match n, xs with + | O , _ => xs + | _ , [] => [] + | S m, x::xs => + drop m xs + end. + +Definition split_at {A} (n : nat) (xs : list A) : list A * list A := + (take n xs, drop n xs). + +Lemma take_length : forall A ( xs ys : list A) n, + n = List.length xs -> + take n (xs ++ ys) = xs. +Proof. +induction xs; intros; simpl in *. + rewrite H. + reflexivity. + + rewrite H. + simpl. + rewrite IHxs; auto. +Qed. + +Lemma drop_length : forall A ( xs ys : list A) n, + n = List.length xs -> + drop n (xs ++ ys) = ys. +Proof. +induction xs; intros; simpl in *. + rewrite H. + reflexivity. + + rewrite H. + simpl. + rewrite IHxs; auto. +Qed. + +Lemma split_at_length : forall A (xs ys : list A), + (xs, ys) = split_at (length xs) (xs ++ ys). +Proof. +intros. +unfold split_at. +rewrite take_length, drop_length; auto. +Qed. + +Lemma take_length_lt : forall A (xs ys : list A) n, + ys = take n xs -> + List.length ys <= n. +Proof. +induction xs; intros. + rewrite H. + destruct n; simpl; omega... + + destruct n. + rewrite H. + simpl. + auto... + + destruct ys; [ discriminate |]. + inversion H. + rewrite <- H2. + apply IHxs in H2. + simpl. + omega... +Qed. + +Lemma split_at_length_lt : forall A (xs ys zs : list A) n, + (xs, ys) = split_at n zs -> + List.length xs <= n. +Proof. +intros. +unfold split_at in *. +inversion H. +apply (take_length_lt _ zs). +reflexivity. +Qed. + +Lemma split_at_soundness : forall A (xs ys zs : list A) n, + (ys,zs) = split_at n xs -> + xs = ys ++ zs. +Proof. +induction xs; induction n; intros; simpl; + try (inversion H; reflexivity). + + unfold split_at in *. + simpl in H. + destruct ys. + inversion H. + + rewrite (IHxs ys zs n); auto. + inversion H. + reflexivity. + + inversion H. + reflexivity. +Qed. + +Lemma take_nil : forall A n, + take n ([] : list A) = []. +Proof. +induction n; auto. +Qed. + +Lemma take_drop_length : forall A ( xs ys : list A) n, + take n xs = ys -> + drop n xs = [ ] -> + xs = ys. +Proof. +induction xs; intros; simpl in *. + rewrite take_nil in H. + assumption. + + destruct n. + simpl in H0. + discriminate. + + simpl in *. + destruct ys. + discriminate. + + inversion H. + rewrite H3. + apply IHxs in H3; auto. + rewrite H3. + reflexivity. +Qed. + +Fixpoint pair { A } ( xs : list A ) := + match xs with + | [] => [] + | [x] => [] + | k :: v :: ys => + (k, v) :: pair ys + end. + +Definition unpair {A} (xs : list (A * A)) := + flat_map (fun x => [ fst x; snd x]) xs. + +Lemma pair_unpair : forall A ( xs : list ( A * A )), + pair (unpair xs) = xs. +Proof. +induction xs; intros; simpl; auto. +rewrite IHxs. +destruct a. +simpl. +reflexivity. +Qed. + +Lemma unpair_pair : forall A n ( xs : list A), + List.length xs = 2 * n -> + unpair (pair xs) = xs. +Proof. +induction n; intros. + destruct xs; auto. + simpl in H. + discriminate. + + destruct xs. + simpl in H. + discriminate... + + destruct xs. + simpl in H. + assert (1 <> S (n + S (n + 0))); [ omega | contradiction ]... + + replace (2 * S n) with (2 + 2 * n) in H; [| omega ]. + simpl in *. + inversion H. + apply IHn in H1. + rewrite H1. + reflexivity. +Qed. + +Lemma pair_length' : forall A n (xs : list A), + n = List.length (pair xs) -> + 2 * n <= List.length xs. +Proof. +induction n; intros; simpl. + omega... + + destruct xs; simpl in *; [ discriminate |]. + destruct xs; simpl in *; [ discriminate |]. + inversion H. + apply IHn in H1. + omega. +Qed. + + +Lemma pair_length : forall A (xs : list A), + 2 * List.length (pair xs) <= List.length xs. +Proof. +intros. +apply pair_length'. +reflexivity. +Qed. + +Lemma unpair_length : forall A ( xs : list (A * A)), + List.length (unpair xs) = 2 * List.length xs. +Proof. +induction xs; simpl; auto. +rewrite IHxs. +omega. +Qed. + +Lemma unpair_split_at: forall A (x1 x2 : A) xs ys, + (unpair ((x1, x2) :: xs), ys) = + split_at (2 * length ((x1, x2) :: xs)) (x1 :: x2 :: unpair xs ++ ys). +Proof. +intros. +replace (2 * (length ((x1,x2) :: xs))) with (length (unpair ((x1,x2)::xs))). + apply split_at_length. + + simpl. + rewrite unpair_length. + omega. +Qed. \ No newline at end of file diff --git a/ocaml/proof/Main.v b/ocaml/proof/Main.v new file mode 100644 index 00000000..e189c802 --- /dev/null +++ b/ocaml/proof/Main.v @@ -0,0 +1,3 @@ +Require Import ExtrOcamlBasic ExtrOcamlIntConv ExtrOcamlNatInt. +Require Import SerializeImplement DeserializeImplement. +Extraction "msgpackCore.ml" serialize deserialize. diff --git a/ocaml/proof/MultiByte.v b/ocaml/proof/MultiByte.v new file mode 100644 index 00000000..3aa33416 --- /dev/null +++ b/ocaml/proof/MultiByte.v @@ -0,0 +1,334 @@ +(* + 16bits,32bits,64bitsの定義。BigEndian。 +*) +Require Import List Ascii NArith Omega Euclid. +Require Import Pow. + +Open Scope char_scope. + +(* * 型の定義 *) +Definition ascii8 : Set := ascii. +Definition ascii16 : Set := (ascii8 * ascii8)%type. +Definition ascii32 : Set := (ascii16 * ascii16)%type. +Definition ascii64 : Set := (ascii32 * ascii32)%type. + +(** ** natとの相互変換 *) +Definition nat_of_ascii8 := + nat_of_ascii. + +Definition ascii8_of_nat := + ascii_of_nat. + +Definition ascii16_of_nat (a : nat) := + let (q,r,_,_) := divmod a (pow 8) (pow_lt_O 8) in + (ascii8_of_nat q, ascii8_of_nat r). + +Definition nat_of_ascii16 (a : ascii16) := + let (a1, a2) := a in + (nat_of_ascii8 a1) * (pow 8) + (nat_of_ascii8 a2). + +Definition ascii32_of_nat (a : nat) := + let (q,r,_,_) := divmod a (pow 16) (pow_lt_O 16) in + (ascii16_of_nat q, ascii16_of_nat r). + +Definition nat_of_ascii32 (a : ascii32) := + let (a1, a2) := a in + (nat_of_ascii16 a1) * (pow 16) + (nat_of_ascii16 a2). + +Definition ascii64_of_nat (a : nat) := + let (q,r,_,_) := divmod a (pow 32) (pow_lt_O 32) in + (ascii32_of_nat q, ascii32_of_nat r). + +Definition nat_of_ascii64 (a : ascii64) := + let (a1, a2) := a in + (nat_of_ascii32 a1) * (pow 32) + (nat_of_ascii32 a2). + +(** ** natに戻せることの証明 *) +Lemma nat_ascii8_embedding : forall n, + n < pow 8 -> + nat_of_ascii8 (ascii8_of_nat n) = n. +Proof. +intros. +unfold nat_of_ascii8,ascii8_of_nat. +rewrite nat_ascii_embedding. + reflexivity. + + simpl in H. + assumption. +Qed. + +Lemma nat_ascii16_embedding : forall n, + n < pow 16 -> + nat_of_ascii16 (ascii16_of_nat n) = n. +Proof. +intros. +unfold ascii16_of_nat, nat_of_ascii16. +destruct divmod. +rewrite (nat_ascii8_embedding q), (nat_ascii8_embedding r); try omega. +apply divmod_lt_q with (t := 8) in e; + change (8+8) with 16; assumption. +Qed. + +Lemma nat_ascii32_embedding : forall n, + n < pow 32 -> + nat_of_ascii32 (ascii32_of_nat n) = n. +Proof. +intros. +unfold ascii32_of_nat, nat_of_ascii32. +destruct divmod. +rewrite (nat_ascii16_embedding q), (nat_ascii16_embedding r); try omega. +apply divmod_lt_q with (t := 16) in e; + change (16+16) with 32; assumption. +Qed. + +Lemma nat_ascii64_embedding : forall n, + n < pow 64 -> + nat_of_ascii64 (ascii64_of_nat n) = n. +Proof. +intros. +unfold ascii64_of_nat, nat_of_ascii64. +destruct divmod. +rewrite (nat_ascii32_embedding q), (nat_ascii32_embedding r); try omega. +apply divmod_lt_q with (t := 32) in e; + change (32+32) with 64; assumption. +Qed. + +(** ** ascii8への変換 *) +Definition list_of_ascii8 (x : ascii8) := + x :: nil. + +Definition list_of_ascii16 (p : ascii16) := + match p with + (x1,x2) => (list_of_ascii8 x1) ++ (list_of_ascii8 x2) + end. + +Definition list_of_ascii32 (p : ascii32) := + match p with + (x1,x2) => (list_of_ascii16 x1) ++ (list_of_ascii16 x2) + end. + +Definition list_of_ascii64 (p : ascii64) := + match p with + (x1,x2) => (list_of_ascii32 x1) ++ (list_of_ascii32 x2) + end. + +Lemma list_of_ascii8_eq : forall c1 c2, + list_of_ascii8 c1 = list_of_ascii8 c2 -> + c1 = c2. +Proof. +intros. +unfold list_of_ascii8 in H. +inversion H. +reflexivity. +Qed. + +Lemma list_of_ascii16_eq : forall c1 c2, + list_of_ascii16 c1 = list_of_ascii16 c2 -> + c1 = c2. +Proof. +intros. +destruct c1; destruct c2. +inversion H. +reflexivity. +Qed. + +Lemma list_of_ascii32_eq : forall c1 c2, + list_of_ascii32 c1 = list_of_ascii32 c2 -> + c1 = c2. +Proof. +intros. +destruct c1; destruct c2. +destruct a; destruct a0; destruct a1; destruct a2. +inversion H. +reflexivity. +Qed. + +Lemma list_of_ascii64_eq : forall c1 c2, + list_of_ascii64 c1 = list_of_ascii64 c2 -> + c1 = c2. +Proof. +intros. +destruct c1; destruct c2. +destruct a; destruct a0; destruct a1; destruct a2. +destruct a; destruct a3; destruct a0; destruct a4; +destruct a1; destruct a5; destruct a2; destruct a6. +inversion H. +reflexivity. +Qed. + +(** 0でないことの証明 *) +Lemma ascii8_not_O: forall n, + 0 < n < pow 8 -> + "000" <> ascii8_of_nat n. +Proof. +intros. +destruct H. +apply nat_ascii8_embedding in H0. +destruct (ascii8_of_nat n). +intro. +destruct b; destruct b0; destruct b1; destruct b2; destruct b3; destruct b4; destruct b5; destruct b6; inversion H1. +compute in H0. +rewrite <- H0 in H. +inversion H. +Qed. + +Lemma ascii16_not_O: forall n, + 0 < n < pow 16 -> + ("000","000") <> ascii16_of_nat n. +Proof. +intros. +unfold ascii16_of_nat. +destruct divmod. +destruct H. +intro. +inversion H1. +generalize e; intro. +apply divmod_not_O in e; auto with pow. +decompose [or] e. + apply ascii8_not_O in H3; auto. + apply divmod_lt_q with (t:=8) in e0; auto with pow. + + apply ascii8_not_O in H4; auto with pow. +Qed. + +Lemma ascii32_not_O: forall n, + 0 < n < pow 32 -> + ("000","000",("000","000")) <> ascii32_of_nat n. +Proof. +intros. +unfold ascii32_of_nat. +destruct divmod. +destruct H. +intro. +inversion H1. +generalize e; intro. +apply divmod_not_O in e. + decompose [or] e. + apply divmod_lt_q with (t:=16) in e0. + apply ascii16_not_O in H3. + contradiction. + + split; assumption. + + assumption. + + exact H0. + + apply ascii16_not_O in H4. + contradiction. + + split; assumption. + + assumption. + + apply pow_lt_O. +Qed. + +(* ** 2^n未満なら等価性が変らないことの証明 *) +Lemma ascii8_of_nat_eq : forall n m, + n < pow 8 -> + m < pow 8 -> + ascii8_of_nat n = ascii8_of_nat m -> + n = m. +Proof. +intros. +rewrite <- (nat_ascii8_embedding n), <- (nat_ascii8_embedding m), <- H1; auto. +Qed. + +Lemma ascii16_of_nat_eq : forall n m, + n < pow 16 -> + m < pow 16 -> + ascii16_of_nat n = ascii16_of_nat m -> + n = m. +Proof. +intros. +rewrite <- (nat_ascii16_embedding n), <- (nat_ascii16_embedding m), <- H1; auto. +Qed. + +Lemma ascii32_of_nat_eq : forall n m, + n < pow 32 -> + m < pow 32 -> + ascii32_of_nat n = ascii32_of_nat m -> + n = m. +Proof. +intros. +rewrite <- (nat_ascii32_embedding n), <- (nat_ascii32_embedding m), <- H1; auto. +Qed. + +Lemma ascii8_of_nat_O: + "000" = ascii8_of_nat 0. +Proof. +compute. +reflexivity. +Qed. + +Lemma ascii16_of_nat_O: + ("000", "000") = ascii16_of_nat 0. +Proof. +unfold ascii16_of_nat. +destruct divmod. +apply divmod_O_pow in e. +decompose [and] e. +rewrite H, H0. +rewrite <- ascii8_of_nat_O. +reflexivity. +Qed. + +Lemma ascii32_of_nat_O: + (("000", "000"),("000","000")) = ascii32_of_nat 0. +Proof. +unfold ascii32_of_nat. +destruct divmod. +apply divmod_O_pow in e. +decompose [and] e. +rewrite H, H0. +rewrite <- ascii16_of_nat_O. +reflexivity. +Qed. + +(* lengthが等しいことの証明 *) +Lemma ascii8_length : forall c1 c2, + length (list_of_ascii8 c1) = length (list_of_ascii8 c2). +Proof. +auto. +Qed. + +Lemma ascii16_length : forall c1 c2, + length (list_of_ascii16 c1) = length (list_of_ascii16 c2). +Proof. +destruct c1,c2. +auto. +Qed. + +Lemma ascii32_length : forall c1 c2, + length (list_of_ascii32 c1) = length (list_of_ascii32 c2). +Proof. +destruct c1 as [a1 a2] ,c2 as [a3 a4]. +destruct a1,a2,a3,a4. +auto. +Qed. + +Lemma ascii64_length : forall c1 c2, + length (list_of_ascii64 c1) = length (list_of_ascii64 c2). +Proof. +destruct c1 as [a1 a2] ,c2 as [a3 a4]. +destruct a1 as [b1 b2], a2 as [b3 b4], a3 as [b5 b6], a4 as [b7 b8]. +destruct b1,b2,b3,b4,b5,b6,b7,b8. +auto. +Qed. + +Lemma ascii5 : forall n b1 b2 b3 b4 b5 b6 b7 b8, + n < pow 5 -> + Ascii b1 b2 b3 b4 b5 b6 b7 b8 = ascii8_of_nat n -> + b6 = false /\ b7 = false /\ b8 = false. +Proof. +intros. +simpl in H. +do 32 (destruct n; [ inversion H0; auto | idtac]). +do 32 (apply Lt.lt_S_n in H). +inversion H. +Qed. + +Hint Resolve ascii16_length ascii32_length ascii64_length + list_of_ascii8_eq list_of_ascii16_eq list_of_ascii32_eq list_of_ascii64_eq + : ascii. \ No newline at end of file diff --git a/ocaml/proof/OCamlBase.v b/ocaml/proof/OCamlBase.v new file mode 100644 index 00000000..f5c0be5a --- /dev/null +++ b/ocaml/proof/OCamlBase.v @@ -0,0 +1,8 @@ +Require Export String. +Require Export List. +Require Export ExtractUtil. +Require Export Util. + +Open Scope string_scope. + +Notation "op ; x" := (semicolon_flipped x op) (at level 50). diff --git a/ocaml/proof/OMakefile b/ocaml/proof/OMakefile new file mode 100644 index 00000000..5ce19233 --- /dev/null +++ b/ocaml/proof/OMakefile @@ -0,0 +1,26 @@ +open CoqBuildRule +.PHONY: all clean + +FILES[] = + Pow + MultiByte + ListUtil + Object + SerializeSpec + Prefix + Soundness + SerializeImplement + SerializedList + DeserializeImplement + OCamlBase + Util + ExtractUtil + Main + +.DEFAULT: all + +all: msgpackCore.ml msgpackCore.mli +msgpackCore.ml msgpackCore.mli: $(CoqProof $(FILES)) + echo "Proof complete" +clean: + rm -rf *.vo *.glob *~ *.omc .omakedb .omakedb.lock *.cm[iox] *.annot *.o msgpackCore.ml msgpackCore.mli diff --git a/ocaml/proof/Object.v b/ocaml/proof/Object.v new file mode 100644 index 00000000..a80928e7 --- /dev/null +++ b/ocaml/proof/Object.v @@ -0,0 +1,122 @@ +(* -*- coding:utf-8 -*- *) +Require Import List Ascii. +Require Import Pow MultiByte ListUtil. + +Open Scope char_scope. + +(** MsgPackで使うオブジェクトの定義 *) +Inductive object := +| Bool (_ : bool) +| Nil +| PFixnum (_ : ascii8) +| NFixnum (_ : ascii8) +| Uint8 (_ : ascii8) +| Uint16 (_ : ascii16) +| Uint32 (_ : ascii32) +| Uint64 (_ : ascii64) +| Int8 (_ : ascii8) +| Int16 (_ : ascii16) +| Int32 (_ : ascii32) +| Int64 (_ : ascii64) +| Float (_ : ascii32) +| Double (_ : ascii64) +| FixRaw (_ : list ascii8) +| Raw16 (_ : list ascii8) +| Raw32 (_ : list ascii8) +| FixArray ( _ : list object) +| Array16 ( _ : list object) +| Array32 ( _ : list object) +| FixMap ( _ : list (object * object)%type) +| Map16 ( _ : list (object * object)%type) +| Map32 ( _ : list (object * object)%type). + +(** 妥当なオブジェクトの定義 *) +Inductive Valid : object -> Prop := +| VBool : forall b, + Valid (Bool b) +| VPFixNum : forall n, + nat_of_ascii8 n < 128 -> Valid (PFixnum n) +| VNFixNum : forall n, + (* 負の数を導入したくないので、補数表現を使う *) + 223 < nat_of_ascii8 n /\ nat_of_ascii8 n < 256 -> Valid (NFixnum n) +| VUint8 : forall c, Valid (Uint8 c) +| VUint16 : forall c, Valid (Uint16 c) +| VUint32 : forall c, Valid (Uint32 c) +| VUint64 : forall c, Valid (Uint64 c) +| VInt8 : forall c, Valid (Int8 c) +| VInt16 : forall c, Valid (Int16 c) +| VInt32 : forall c, Valid (Int32 c) +| VInt64 : forall c, Valid (Int64 c) +| VFloat : forall c, Valid (Float c) +| VDouble : forall c, Valid (Double c) +| VFixRaw : forall xs, + length xs < pow 5 -> Valid (FixRaw xs) +| VRaw16 : forall xs, + length xs < pow 16 -> Valid (Raw16 xs) +| VRaw32 : forall xs, + length xs < pow 32 -> Valid (Raw32 xs) +| VFixArrayNil : + Valid (FixArray []) +| VFixArrayCons : forall x xs, + Valid x -> + Valid (FixArray xs) -> + length (x::xs) < pow 4 -> + Valid (FixArray (x::xs)) +| VArray16Nil : + Valid (Array16 []) +| VArray16Cons: forall x xs, + Valid x -> + Valid (Array16 xs) -> + length (x::xs) < pow 16 -> + Valid (Array16 (x::xs)) +| VArray32Nil : + Valid (Array32 []) +| VArray32Cons : forall x xs, + Valid x -> + Valid (Array32 xs) -> + length (x::xs) < pow 32 -> + Valid (Array32 (x::xs)) +| VFixMapNil: + Valid (FixMap []) +| VFixMapCons : forall k v xs, + Valid k -> + Valid v -> + Valid (FixMap xs) -> + length ((k,v)::xs) < pow 4 -> + Valid (FixMap ((k,v)::xs)) +| VMap16Nil : + Valid (Map16 []) +| VMap16Cons : forall k v xs, + Valid k -> + Valid v -> + Valid (Map16 xs) -> + length ((k,v)::xs) < pow 16 -> + Valid (Map16 ((k,v)::xs)) +| VMap32Nil : + Valid (Map32 []) +| VMap32Cons : forall k v xs, + Valid k -> + Valid v -> + Valid (Map32 xs) -> + length ((k,v)::xs) < pow 32 -> + Valid (Map32 ((k,v)::xs)). + +Lemma varray16_inv1: forall x xs, + Valid (Array16 (x::xs)) -> + ("000", "000") <> ascii16_of_nat (length (x :: xs)). +Proof. +intros. +apply ascii16_not_O. +split; [ apply length_lt_O | inversion H; auto ]. +Qed. + +Lemma varray16_inv2 : forall A (x y : A) xs ys, + pow 16 > length (x :: xs) -> + pow 16 > length (y :: ys) -> + ascii16_of_nat (length (x :: xs)) = ascii16_of_nat (length (y :: ys)) -> + ascii16_of_nat (length xs) = ascii16_of_nat (length ys). +Proof. +intros. +apply ascii16_of_nat_eq in H1; auto. +Qed. + diff --git a/ocaml/proof/Pow.v b/ocaml/proof/Pow.v new file mode 100644 index 00000000..23c0666e --- /dev/null +++ b/ocaml/proof/Pow.v @@ -0,0 +1,162 @@ +(** + 算術演算関連の補題 +*) + +Require Import Omega NArith Euclid. + +(** ** 算術演算 *) +Lemma mult_S_lt_reg_l : + forall n m p, 0 < n -> n * m < n * p -> m < p. +Proof. +intros. +destruct n. + inversion H. + +elim (le_or_lt m p). + intro. + inversion H1. + rewrite H2 in H0. + elim (lt_irrefl _ H0). + omega. + + intro. + apply (mult_S_lt_compat_l n _ _) in H1. + omega. +Qed. + +Lemma plus_elim: forall p a b, + a + p < b -> a < b. +Proof. +intros. +omega. +Qed. + +(** ** pow *) +Fixpoint pow (n : nat) := + match n with + | 0 => + 1 + | S n' => + 2 * pow n' + end. + +Lemma pow_lt_O : forall n, + 0 < pow n. +Proof. +induction n; simpl; omega. +Qed. + +Hint Resolve pow_lt_O. + +Lemma pow_add: forall n m, + pow n * pow m = pow (n + m). +Proof. +induction n; intros. + simpl in *. + omega. + + simpl. + repeat rewrite plus_0_r. + rewrite <- IHn, mult_plus_distr_r. + reflexivity. +Qed. + +(** ** divmod *) +Definition divmod (n m : nat) (P : 0 < m) := + eucl_dev m P n. + +Lemma divmod_lt_q : forall (n m q r s t: nat), + n < pow (s + t) -> + n = q * pow s + r -> + q < pow t. +Proof. +intros. +rewrite H0 in H. +apply plus_elim in H. +rewrite <- pow_add, mult_comm in H. +apply mult_S_lt_reg_l in H. + assumption. + + apply pow_lt_O. +Qed. + +Lemma divmod_not_O: forall n m q r, + 0 < n -> + 0 < m -> + n = q * m + r -> + 0 < q \/ 0 < r. +Proof. +intros. +rewrite H1 in H. +destruct q. + simpl in H. + right. + assumption. + + left. + omega. +Qed. + +Lemma divmod_O: forall n q r, + 0 = q * n + r -> + n <> 0 -> + q = 0 /\ r = 0. +Proof. +intros. +destruct q; destruct n; destruct r; try omega. + simpl in H. + discriminate. + + simpl in H. + discriminate. +Qed. + +Lemma divmod_O_pow: forall n q r, + 0 = q * pow n + r -> + q = 0 /\ r = 0. +Proof. +intros. +apply (divmod_O (pow n) _ _); auto. +intro. +generalize (pow_lt_O n); intros. +omega. +Qed. + +Lemma plus_O : forall n, + n + 0 = n. +Proof. +Admitted. + +Lemma plus_double : forall n, + n < n + n. +Admitted. + +Lemma pow_lt : forall n m, + n < m -> + pow n < pow m. +Proof. +induction n; induction m; simpl; intros. + inversion H. + + destruct m; auto. + transitivity (pow (S m)); + [ apply IHm | idtac]; + omega. + + inversion H. + + simpl in IHm. + inversion H; simpl. + repeat (rewrite plus_O in *). + apply (Plus.plus_lt_compat_r O _). + transitivity (pow n); auto. + apply plus_double. + + assert (S n < m); auto. + apply IHm in H2. + transitivity (pow m); auto. + rewrite plus_O. + apply plus_double. +Qed. + +Hint Resolve pow_lt pow_lt_O: pow. diff --git a/ocaml/proof/Prefix.v b/ocaml/proof/Prefix.v new file mode 100644 index 00000000..d9e456f3 --- /dev/null +++ b/ocaml/proof/Prefix.v @@ -0,0 +1,674 @@ +Require Import List Ascii. +Require Import ListUtil Object SerializeSpec MultiByte ProofUtil Pow. + +Definition Prefix obj1 x : Prop := forall obj2 y xs ys, + Serialized obj1 x -> + Serialized obj2 y -> + Valid obj1 -> + Valid obj2 -> + x ++ xs = y ++ ys -> + x = y. + +Ltac destruct_serialize obj y := + match goal with + | [ H1 : _ ++ _ = y ++ _, + H2 : Serialized obj y |- _ ] => + destruct y as [ | a ] ; + [ inversion H2 | inversion H1 ; rewrite_for a; inversion H2 ]; + auto + end. + +(* 結果が1バイトになる変換 *) +Ltac straight_forward := + intros; + unfold Prefix; + intros obj2 y xs ys S1 S2 V1 V2 Happ; + destruct_serialize obj2 y. + +Lemma prefix_true : + Prefix (Bool true) ["195"]. +Proof. +straight_forward. +Qed. + +Lemma prefix_false : + Prefix (Bool false) ["194"]. +Proof. +straight_forward. +Qed. + +Lemma prefix_nil : + Prefix Nil ["192"]. +Proof. +straight_forward. +Qed. + +Lemma prefix_pfixnum: forall x1 x2 x3 x4 x5 x6 x7, + Prefix (PFixnum (Ascii x1 x2 x3 x4 x5 x6 x7 false)) + [Ascii x1 x2 x3 x4 x5 x6 x7 false]. +Proof. +straight_forward. +Qed. + +Lemma prefix_nfixnum : forall x1 x2 x3 x4 x5, + Prefix (NFixnum (Ascii x1 x2 x3 x4 x5 true true true)) + [Ascii x1 x2 x3 x4 x5 true true true]. +Proof. +straight_forward. +Qed. + +(* 結果が固定長多バイトになる変換 *) +Lemma prefix_same : forall A (x y xs ys : list A), + x ++ xs = y ++ ys -> + length x = length y -> + x = y. +Proof. +induction x; induction y; intros; auto. + simpl in H0. + discriminate. + + simpl in H0. + discriminate. + + inversion H. + inversion H0. + apply IHx in H3; auto. + rewrite_for y. + reflexivity. +Qed. + +Ltac same_as_uint8 := + unfold Prefix; + intros c obj2 y xs ys S1 S2 V1 V2 Happ; + destruct_serialize obj2 y; + rewrite_for y; + apply prefix_same in Happ; simpl; auto with ascii. + +Lemma prefix_uint8 : forall c, + Prefix (Uint8 c) ("204"::list_of_ascii8 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_uint16: forall c, + Prefix (Uint16 c) ("205"::list_of_ascii16 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_uint32: forall c, + Prefix (Uint32 c) ("206"::list_of_ascii32 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_uint64 : forall c, + Prefix (Uint64 c) ("207"::list_of_ascii64 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_int8 : forall c, + Prefix (Int8 c) ("208"::list_of_ascii8 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_int16 : forall c, + Prefix (Int16 c) ("209"::list_of_ascii16 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_int32 : forall c, + Prefix (Int32 c) ("210"::list_of_ascii32 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_int64 : forall c, + Prefix (Int64 c) ("211"::list_of_ascii64 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_float : forall c, + Prefix (Float c) ("202"::list_of_ascii32 c). +Proof. +same_as_uint8. +Qed. + +Lemma prefix_double : forall c, + Prefix (Double c) ("203"::list_of_ascii64 c). +Proof. +same_as_uint8. +Qed. + +Lemma app_length_eq : forall A (xs ys zs ws : list A), + xs ++zs = ys ++ ws -> + length xs = length ys -> + xs = ys. +Proof. +induction xs; induction ys; simpl; intros; auto. + inversion H0. + + inversion H0. + + inversion H. + inversion H0. + assert (xs = ys); [| rewrite_for xs; auto]. + apply (IHxs _ zs ws); auto. +Qed. + +Lemma prefix_fixraw : forall cs b1 b2 b3 b4 b5, + Ascii b1 b2 b3 b4 b5 false false false = ascii8_of_nat (length cs) -> + Prefix (FixRaw cs) ((Ascii b1 b2 b3 b4 b5 true false true)::cs). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y. +rewrite_for obj2. +rewrite_for y. +inversion H2. +inversion H3. +assert (cs = cs0); [| rewrite_for cs; auto ]. +apply (app_length_eq _ _ _ xs ys); auto. +rewrite <- (nat_ascii8_embedding (length cs)), + <- (nat_ascii8_embedding (length cs0)). + rewrite <- H, <- H8. + reflexivity. + + transitivity (pow 5); auto with pow. + + transitivity (pow 5); auto with pow. +Qed. + +Lemma prefix_raw16 : forall cs s1 s2, + (s1,s2) = ascii16_of_nat (length cs) -> + Prefix (Raw16 cs) ("218"::s1::s2::cs). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y. +rewrite_for obj2. +rewrite_for y. +inversion H2. +inversion H3. +inversion H7. +assert (cs = cs0); [| rewrite_for cs; auto ]. +apply (app_length_eq _ _ _ xs ys); auto. +rewrite <- (nat_ascii16_embedding (length cs)), + <- (nat_ascii16_embedding (length cs0)); auto. +rewrite <- H, <- H8, H12, H13. +reflexivity. +Qed. + +Lemma prefix_raw32 : forall cs s1 s2 s3 s4, + ((s1,s2),(s3,s4)) = ascii32_of_nat (length cs) -> + Prefix (Raw32 cs) ("219"::s1::s2::s3::s4::cs). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y. +rewrite_for obj2. +rewrite_for y. +inversion H2. +inversion H3. +inversion H7. +assert (cs = cs0); [| rewrite_for cs; auto ]. +apply (app_length_eq _ _ _ xs ys); auto. +rewrite <- (nat_ascii32_embedding (length cs)), + <- (nat_ascii32_embedding (length cs0)); auto. +rewrite <- H, <- H8, H12, H13, H14, H15. +reflexivity. +Qed. + +Lemma prefix_fixarray_nil: + Prefix (FixArray []) ["144"]. +Proof. +straight_forward. +apply ascii8_not_O in H7; [ contradiction |]. +rewrite_for obj2. +inversion V2. +split; [ simpl; omega |]. +transitivity (pow 4); [ exact H13 | apply pow_lt; auto ]. +Qed. + +Lemma prefix_array16_nil: + Prefix (Array16 []) ["220"; "000"; "000"]. +Proof. +unfold Prefix; intros. +destruct_serialize obj2 y. +rewrite_for obj2. +rewrite_for y. +inversion H3. +rewrite <- H9, <- H11 in *. +assert (("000", "000") <> ascii16_of_nat ((length (x::xs0)))); try contradiction. +inversion H2. +apply ascii16_not_O. +split; auto. +simpl. +omega. +Qed. + +Lemma prefix_array32_nil: + Prefix (Array32 []) ["221"; "000"; "000";"000"; "000"]. +Proof. +unfold Prefix; intros. +destruct_serialize obj2 y. +rewrite_for obj2. +rewrite_for y. +inversion H3. +rewrite <- H9, <- H11, <- H12, <- H13 in *. +assert (("000", "000",("000","000")) <> ascii32_of_nat ((length (x::xs0)))); try contradiction. +inversion H2. +apply ascii32_not_O. +split; auto. +simpl. +omega. +Qed. + +Lemma prefix_fixmap_nil: + Prefix (FixMap []) ["128"]. +Proof. +unfold Prefix; intros. +destruct_serialize obj2 y. +rewrite_for obj2. +apply ascii8_not_O in H12; [ contradiction |]. +inversion H2. +split; [ simpl; omega |]. +transitivity (pow 4); [ exact H21 |]. +apply pow_lt. +auto. +Qed. + +Lemma prefix_map16_nil: + Prefix (Map16 []) ["222"; "000"; "000"]. +Proof. +unfold Prefix; intros. +destruct_serialize obj2 y. +rewrite_for obj2. +rewrite_for y. +inversion H3. +rewrite <- H10, <- H12 in *. +assert (("000", "000") <> ascii16_of_nat ((length ((x1, x2)::xs0)))); try contradiction. +inversion H2. +apply ascii16_not_O. +split. + simpl. + omega. + + exact H19. +Qed. + +Lemma prefix_map32_nil: + Prefix (Map32 []) ["223"; "000"; "000";"000"; "000"]. +Proof. +unfold Prefix; intros. +destruct_serialize obj2 y. +rewrite_for obj2. +rewrite_for y. +inversion H3. +rewrite <- H10, <- H12, <- H13, <- H14 in *. +assert (("000", "000",("000","000")) <> ascii32_of_nat ((length ((x1, x2)::xs0)))); try contradiction. +inversion H2. +apply ascii32_not_O. +split. + simpl. + omega. + + exact H21. +Qed. + +Lemma prefix_fixarray_cons: forall x xs y ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length (x::xs)) -> + Serialized x y -> + Prefix x y -> + Serialized (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Prefix (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Prefix (FixArray (x :: xs)) ((Ascii b5 b6 b7 b8 true false false true)::y ++ ys). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y0; rewrite_for y0; rewrite_for obj2. + inversion H6. + rewrite_for b5. + rewrite_for b6. + rewrite_for b7. + rewrite_for b8. + apply ascii8_not_O in H0; [contradiction |]. + split; [ simpl; omega |]. + inversion H7. + transitivity (pow 4); [ exact H19 | apply pow_lt; auto]. + + assert (y ++ ys = y1 ++ ys1); [| rewrite_for (y++ys); reflexivity ]. + generalize H12; intro Happ; clear H12. + rewrite <- (app_assoc y ys xs0), <- (app_assoc y1 ys1 ys0) in Happ. + inversion H7. + inversion H8. + apply (H2 x0 y1 (ys++xs0) (ys1++ys0))in H1; auto. + rewrite_for y1. + apply app_same in Happ. + apply (H4 (FixArray xs1) (Ascii b0 b9 b10 b11 true false false true :: ys1) xs0 ys0) in H3; auto. + inversion H3. + reflexivity. + + simpl. + unfold ascii8 in *. + rewrite <- Happ. + rewrite H0 in H18. + apply ascii8_of_nat_eq in H18; [ + | transitivity (pow 4); [| apply pow_lt]; auto + | transitivity (pow 4); [| apply pow_lt]; auto ]. + simpl in H18. + inversion H18. + rewrite <- H28 in H16. + rewrite <- H16 in H. + inversion H. + reflexivity. +Qed. + +Lemma prefix_array16_cons: forall x xs y ys s1 s2 t1 t2, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length (x :: xs)) -> + Serialized x y -> + Prefix x y -> + Serialized (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + Prefix (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + Prefix (Array16 (x::xs)) ("220"::s1::s2::y ++ ys). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y0. + rewrite_for y0. + inversion H9. + rewrite_for s1. + rewrite_for s2. + apply ascii16_not_O in H0; [ contradiction |]. + inversion H7. + split; [ simpl; omega | exact H17 ]. + + rewrite_for y0. + rewrite_for obj2. + inversion H9. + rewrite_for s0. + rewrite_for s3. + assert( y++ ys = y1 ++ ys1); [| rewrite_for (y++ys); reflexivity ]. + rewrite <- (app_assoc y ys xs0), <- (app_assoc y1 ys1 ys0) in H18. + inversion H7. + inversion H8. + apply (H2 x0 y1 (ys++xs0) (ys1++ys0))in H1; auto. + rewrite_for y1. + apply app_same in H18. + apply (H4 (Array16 xs1) ("220" :: t0 :: t3 :: ys1) xs0 ys0) in H3; auto. + inversion H3. + reflexivity. + + simpl. + unfold ascii8 in *. + rewrite <- H18. + rewrite H0 in H13. + apply ascii16_of_nat_eq in H13; auto. + simpl in H13. + inversion H13. + rewrite <- H26 in H11. + rewrite <- H11 in H. + inversion H. + reflexivity. +Qed. + +Lemma prefix_array32_cons: forall x xs y ys s1 s2 s3 s4 t1 t2 t3 t4, + (t1, t2, (t3, t4)) = ascii32_of_nat (length xs) -> + (s1, s2, (s3, s4)) = ascii32_of_nat (length (x :: xs)) -> + Serialized x y -> + Prefix x y -> + Serialized (Array32 xs) ("221" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Prefix (Array32 xs) ("221" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Prefix (Array32 (x :: xs)) ("221" :: s1 :: s2 :: s3 :: s4 :: y ++ ys). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y0; + rewrite_for y0; rewrite_for obj2; inversion H9. + rewrite_for s1. + rewrite_for s2. + rewrite_for s3. + rewrite_for s4. + apply ascii32_not_O in H0; [ contradiction |]. + inversion H7. + split; [ simpl; omega | exact H15 ]. + + rewrite_for s0. + rewrite_for s5. + rewrite_for s6. + rewrite_for s7. + assert( y++ ys = y1 ++ ys1); [| rewrite_for (y++ys); reflexivity ]. + rewrite <- (app_assoc y ys xs0), <- (app_assoc y1 ys1 ys0) in H20. + inversion H7. + inversion H8. + apply (H2 x0 y1 (ys++xs0) (ys1++ys0)) in H1; auto. + rewrite_for y1. + apply app_same in H20. + apply (H4 (Array32 xs1) ("221" :: t0 :: t5 :: t6 :: t7 :: ys1) xs0 ys0) in H3; auto. + inversion H3. + reflexivity. + + simpl. + unfold ascii8 in *. + rewrite <- H20. + rewrite H0 in H13. + apply ascii32_of_nat_eq in H13; auto. + simpl in H13. + inversion H13. + rewrite <- H26 in H11. + rewrite <- H11 in H. + inversion H. + reflexivity. +Qed. + +Lemma prefix_fixmap_cons: forall x1 x2 xs y1 y2 ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length ((x1,x2)::xs)) -> + Serialized x1 y1 -> Prefix x1 y1 -> + Serialized x2 y2 -> Prefix x2 y2 -> + Serialized (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Prefix (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Prefix (FixMap ((x1, x2) :: xs)) (Ascii b5 b6 b7 b8 false false false true :: y1 ++ y2 ++ ys). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y; rewrite_for y; rewrite_for obj2. + rewrite_for b5. + rewrite_for b6. + rewrite_for b7. + rewrite_for b8. + apply ascii8_not_O in H0; [ contradiction |]. + split; [ simpl; omega |]. + inversion H9. + transitivity (pow 4); auto. + apply pow_lt. + auto. + +assert (y1 ++ y2 ++ ys = y0 ++ y3 ++ ys1); [| rewrite_for (y1 ++ y2 ++ ys); reflexivity ]. +generalize H14; intro Happ; clear H14. +replace ((y1 ++ y2 ++ ys) ++ xs0) with (y1 ++ y2 ++ ys ++ xs0) in Happ; + [| repeat (rewrite app_assoc); reflexivity ]. +replace ((y0 ++ y3 ++ ys1) ++ ys0) with (y0 ++ y3 ++ ys1 ++ ys0) in Happ; + [| repeat (rewrite app_assoc); reflexivity ]. +inversion H9. +inversion H10. +apply (H2 x0 y0 (y2 ++ ys ++ xs0) (y3 ++ ys1 ++ ys0))in H1; auto. +rewrite_for y1. +apply app_same in Happ. +apply (H4 x3 y3 (ys ++ xs0) (ys1 ++ ys0)) in H3; auto. +rewrite_for y3. +apply app_same in Happ. +apply (H6 (FixMap xs1) (Ascii b0 b9 b10 b11 false false false true :: ys1) xs0 ys0) in H5; auto. + inversion H5. + reflexivity. + + simpl. + unfold ascii8 in *. + rewrite <- Happ. + rewrite H0 in H20. + apply ascii8_of_nat_eq in H20; [ + | transitivity (pow 4); [| apply pow_lt]; auto + | transitivity (pow 4); [| apply pow_lt]; auto ]. + simpl in H20. + inversion H20. + rewrite H3 in H. + rewrite <- H19 in H. + inversion H. + reflexivity. +Qed. + +Lemma prefix_map16_cons: forall x1 x2 xs y1 y2 ys s1 s2 t1 t2, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Prefix x1 y1 -> + Serialized x2 y2 -> + Prefix x2 y2 -> + Serialized (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Prefix (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Prefix (Map16 ((x1, x2) :: xs)) ("222" :: s1 :: s2 :: y1 ++ y2 ++ ys). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y; rewrite_for y; rewrite_for obj2. + inversion H11. + rewrite_for s1. + rewrite_for s2. + apply ascii16_not_O in H0; [ contradiction |]. + inversion H9. + split; [ simpl; omega | exact H20 ]. + + inversion H14. + rewrite_for s1. + rewrite_for s2. + assert( y1 ++ y2 ++ ys = y0 ++ y3 ++ ys1); [| rewrite_for (y1 ++ y2 ++ ys); reflexivity ]. + replace ((y1 ++ y2 ++ ys) ++ xs0) with (y1 ++ y2 ++ ys ++ xs0) in H21; + [| repeat (rewrite app_assoc); reflexivity ]. + replace ((y0 ++ y3 ++ ys1) ++ ys0) with (y0 ++ y3 ++ ys1 ++ ys0) in H21; + [| repeat (rewrite app_assoc); reflexivity ]. + inversion H9. + inversion H10. + apply (H2 x0 y0 (y2 ++ ys ++ xs0) (y3 ++ ys1 ++ ys0))in H1; auto. + rewrite_for y1. + apply app_same in H21. + apply (H4 x3 y3 (ys ++ xs0) (ys1 ++ ys0)) in H3; auto. + rewrite_for y3. + apply app_same in H21. + apply (H6 (Map16 xs1) ("222" :: t0 :: t3 :: ys1) xs0 ys0) in H5; auto. + inversion H5. + reflexivity. + + simpl. + unfold ascii8 in *. + rewrite <- H21. + rewrite H0 in H15. + apply ascii16_of_nat_eq in H15; auto. + simpl in H15. + inversion H15. + rewrite H3 in H. + rewrite <- H13 in H. + inversion H. + reflexivity. +Qed. + +Lemma prefix_map32_cons : forall x1 x2 xs y1 y2 ys s1 s2 s3 s4 t1 t2 t3 t4, + (t1, t2, (t3, t4)) = ascii32_of_nat (length xs) -> + (s1, s2, (s3, s4)) = ascii32_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Prefix x1 y1 -> + Serialized x2 y2 -> + Prefix x2 y2 -> + Serialized (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Prefix (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Prefix (Map32 ((x1, x2) :: xs)) ("223" :: s1 :: s2 :: s3 :: s4 :: y1 ++ y2 ++ ys). +Proof. +unfold Prefix. +intros. +destruct_serialize obj2 y; rewrite_for y; rewrite_for obj2. + inversion H11. + rewrite_for s1. + rewrite_for s2. + rewrite_for s3. + rewrite_for s4. + apply ascii32_not_O in H0; [ contradiction |]. + inversion H9. + split; [ simpl; omega | exact H20 ]. + + inversion H14. + rewrite_for s1. + rewrite_for s2. + rewrite_for s3. + rewrite_for s4. + generalize H23; intro Happ; clear H23. + assert( y1 ++ y2 ++ ys = y0 ++ y3 ++ ys1); [| rewrite_for (y1 ++ y2 ++ ys); reflexivity ]. + replace ((y1 ++ y2 ++ ys) ++ xs0) with (y1 ++ y2 ++ ys ++ xs0) in Happ; + [| repeat (rewrite app_assoc); reflexivity ]. + replace ((y0 ++ y3 ++ ys1) ++ ys0) with (y0 ++ y3 ++ ys1 ++ ys0) in Happ; + [| repeat (rewrite app_assoc); reflexivity ]. + inversion H9. + inversion H10. + apply (H2 x0 y0 (y2 ++ ys ++ xs0) (y3 ++ ys1 ++ ys0)) in H1; auto. + rewrite_for y1. + apply app_same in Happ. + apply (H4 x3 y3 (ys ++ xs0) (ys1 ++ ys0)) in H3; auto. + rewrite_for y3. + apply app_same in Happ. + apply (H6 (Map32 xs1) ("223" :: t0 :: t5 :: t6 :: t7 :: ys1) xs0 ys0) in H5; auto. + inversion H5. + reflexivity. + + simpl. + unfold ascii8 in *. + rewrite <- Happ. + rewrite H0 in H15. + apply ascii32_of_nat_eq in H15; auto. + simpl in H15. + inversion H15. + rewrite H3 in H. + rewrite <- H13 in H. + inversion H. + reflexivity. +Qed. + +Hint Resolve + prefix_true prefix_false + prefix_nil prefix_pfixnum prefix_nfixnum + prefix_uint8 prefix_uint16 prefix_uint32 prefix_uint64 + prefix_int8 prefix_int16 prefix_int32 prefix_int64 + prefix_float prefix_double + prefix_raw16 prefix_raw32 + prefix_fixarray_nil prefix_array16_nil prefix_array32_nil + prefix_fixmap_nil prefix_map16_nil prefix_map32_nil + : prefix. + +Lemma prefix_intro: forall obj x, + (Serialized obj x -> Prefix obj x)-> + Prefix obj x. +Proof. +unfold Prefix. +intros. +apply H with (xs:=xs) (ys:=ys) in H1; auto. +Qed. + +Lemma prefix : forall obj1 x, + Prefix obj1 x. +Proof. +intros. +apply prefix_intro. +intro. +pattern obj1,x. +apply Serialized_ind; intros; auto with prefix. + apply prefix_fixraw; auto. + apply prefix_fixarray_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply prefix_array16_cons with (t1:=t1) (t2:=t2); auto. + apply prefix_array32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. + apply prefix_fixmap_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply prefix_map16_cons with (t1:=t1) (t2:=t2); auto. + apply prefix_map32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. +Qed. diff --git a/ocaml/proof/ProofUtil.v b/ocaml/proof/ProofUtil.v new file mode 100644 index 00000000..191544e6 --- /dev/null +++ b/ocaml/proof/ProofUtil.v @@ -0,0 +1,5 @@ +Ltac rewrite_for x := + match goal with + | [ H : x = _ |- _ ] => rewrite H in *; clear H + | [ H : _ = x |- _ ] => rewrite <- H in *; clear H + end. \ No newline at end of file diff --git a/ocaml/proof/SerializeImplement.v b/ocaml/proof/SerializeImplement.v new file mode 100644 index 00000000..0bfd6ddf --- /dev/null +++ b/ocaml/proof/SerializeImplement.v @@ -0,0 +1,465 @@ +Require Import Ascii List. +Require Import ListUtil Object MultiByte Util SerializeSpec ProofUtil. + +Open Scope char_scope. + +Fixpoint serialize (obj : object) : list ascii8 := + match obj with + | Nil => [ "192" ] + | Bool false => [ "194" ] + | Bool true => [ "195" ] + | PFixnum (Ascii b1 b2 b3 b4 b5 b6 b7 _) => + [ Ascii b1 b2 b3 b4 b5 b6 b7 false ] + | NFixnum (Ascii b1 b2 b3 b4 b5 _ _ _) => + [ Ascii b1 b2 b3 b4 b5 true true true ] + | Uint8 c => "204"::list_of_ascii8 c + | Uint16 c => "205"::list_of_ascii16 c + | Uint32 c => "206"::list_of_ascii32 c + | Uint64 c => "207"::list_of_ascii64 c + | Int8 c => "208"::list_of_ascii8 c + | Int16 c => "209"::list_of_ascii16 c + | Int32 c => "210"::list_of_ascii32 c + | Int64 c => "211"::list_of_ascii64 c + | Float c => "202"::list_of_ascii32 c + | Double c => "203"::list_of_ascii64 c + | FixRaw xs => + match ascii8_of_nat @@ length xs with + | Ascii b1 b2 b3 b4 b5 _ _ _ => + (Ascii b1 b2 b3 b4 b5 true false true)::xs + end + | Raw16 xs => + let (s1,s2) := + ascii16_of_nat @@ length xs + in + "218"::s1::s2::xs + | Raw32 xs => + match ascii32_of_nat @@ length xs with + | ((s1,s2),(s3,s4)) => + "219"::s1::s2::s3::s4::xs + end + | FixArray xs => + let ys := + flat_map serialize xs + in + match ascii8_of_nat @@ length xs with + | Ascii b1 b2 b3 b4 _ _ _ _ => + (Ascii b1 b2 b3 b4 true false false true)::ys + end + | Array16 xs => + let ys := + flat_map serialize xs + in + let (s1, s2) := + ascii16_of_nat (length xs) + in + "220"::s1::s2::ys + | Array32 xs => + let ys := + flat_map serialize xs + in + match ascii32_of_nat @@ length xs with + | ((s1,s2),(s3,s4)) => + "221"::s1::s2::s3::s4::ys + end + | FixMap xs => + let ys := + flat_map (fun p => serialize (fst p) ++ serialize (snd p)) xs + in + match ascii8_of_nat @@ length xs with + | Ascii b1 b2 b3 b4 _ _ _ _ => + (Ascii b1 b2 b3 b4 false false false true)::ys + end + | Map16 xs => + let ys := + flat_map (fun p => serialize (fst p) ++ serialize (snd p)) xs + in + let (s1, s2) := + ascii16_of_nat (length xs) + in + "222"::s1::s2::ys + | Map32 xs => + let ys := + flat_map (fun p => serialize (fst p) ++ serialize (snd p)) xs + in + match ascii32_of_nat @@ length xs with + | ((s1,s2),(s3,s4)) => + "223"::s1::s2::s3::s4::ys + end + end. + +Definition Correct obj xs := + Serialized obj xs -> + serialize obj = xs. + +Ltac straitfoward := + unfold Correct; + intros; + simpl; + reflexivity. + +Lemma correct_nil: + Correct Nil ["192"]. +Proof. +straitfoward. +Qed. + +Lemma correct_false: + Correct (Bool false) ["194"]. +Proof. +straitfoward. +Qed. + +Lemma correct_true: + Correct (Bool true) ["195"]. +Proof. +straitfoward. +Qed. + +Lemma correct_pfixnum: forall x1 x2 x3 x4 x5 x6 x7, + Correct (PFixnum (Ascii x1 x2 x3 x4 x5 x6 x7 false)) + [Ascii x1 x2 x3 x4 x5 x6 x7 false]. +Proof. +straitfoward. +Qed. + +Lemma correct_nfixnum: forall x1 x2 x3 x4 x5, + Correct (NFixnum (Ascii x1 x2 x3 x4 x5 true true true)) + [Ascii x1 x2 x3 x4 x5 true true true]. +Proof. +straitfoward. +Qed. + +Lemma correct_uint8 : forall c, + Correct (Uint8 c) ("204"::list_of_ascii8 c). +Proof. +straitfoward. +Qed. + +Lemma correct_uint16 : forall c, + Correct (Uint16 c) ("205"::list_of_ascii16 c). +Proof. +straitfoward. +Qed. + +Lemma correct_uint32 : forall c, + Correct (Uint32 c) ("206"::list_of_ascii32 c). +Proof. +straitfoward. +Qed. + +Lemma correct_uint64 : forall c, + Correct (Uint64 c) ("207"::list_of_ascii64 c). +Proof. +straitfoward. +Qed. + +Lemma correct_int8 : forall c, + Correct (Int8 c) ("208"::list_of_ascii8 c). +Proof. +straitfoward. +Qed. + +Lemma correct_int16 : forall c, + Correct (Int16 c) ("209"::list_of_ascii16 c). +Proof. +straitfoward. +Qed. + +Lemma correct_int32 : forall c, + Correct (Int32 c) ("210"::list_of_ascii32 c). +Proof. +straitfoward. +Qed. + +Lemma correct_int64 : forall c, + Correct (Int64 c) ("211"::list_of_ascii64 c). +Proof. +straitfoward. +Qed. + +Lemma correct_float : forall c, + Correct (Float c) ("202"::list_of_ascii32 c). +Proof. +straitfoward. +Qed. + +Lemma correct_double : forall c, + Correct (Double c) ("203"::list_of_ascii64 c). +Proof. +straitfoward. +Qed. + +Lemma correct_fixraw : forall cs b1 b2 b3 b4 b5, + Ascii b1 b2 b3 b4 b5 false false false = ascii8_of_nat (length cs) -> + Correct (FixRaw cs) ((Ascii b1 b2 b3 b4 b5 true false true)::cs). +Proof. +unfold Correct. +intros. +inversion H0. +simpl. +unfold atat. +rewrite_for (ascii8_of_nat (length cs)). +reflexivity. +Qed. + +Lemma correct_raw16: forall cs s1 s2, + (s1,s2) = ascii16_of_nat (length cs) -> + Correct (Raw16 cs) ("218"::s1::s2::cs). +Proof. +unfold Correct. +intros. +inversion H0. +simpl. +unfold atat. +rewrite_for (ascii16_of_nat (length cs)). +reflexivity. +Qed. + +Lemma correct_raw32 : forall cs s1 s2 s3 s4, + ((s1,s2),(s3,s4)) = ascii32_of_nat (length cs) -> + Correct (Raw32 cs) ("219"::s1::s2::s3::s4::cs). +Proof. +unfold Correct. +intros. +inversion H0. +simpl. +unfold atat. +rewrite_for (ascii32_of_nat (length cs)). +reflexivity. +Qed. + +Lemma correct_fixarray_nil : + Correct (FixArray []) ["144"]. +Proof. +straitfoward. +Qed. + +Lemma correct_array16_nil : + Correct (Array16 []) ["220"; "000"; "000"]. +Proof. +unfold Correct. +intros. +simpl. +rewrite <- ascii16_of_nat_O. +reflexivity. +Qed. + +Lemma correct_array32_nil: + Correct (Array32 []) ["221"; "000"; "000";"000"; "000"]. +Proof. +unfold Correct. +intros. +simpl. +unfold atat. +rewrite <- ascii32_of_nat_O. +reflexivity. +Qed. + +Lemma correct_fixmap_nil: + Correct (FixMap []) ["128"]. +Proof. +straitfoward. +Qed. + +Lemma correct_map16_nil: + Correct (Map16 []) ["222"; "000"; "000"]. +Proof. +unfold Correct. +intros. +simpl. +rewrite <- ascii16_of_nat_O. +reflexivity. +Qed. + +Lemma correct_map32_nil: + Correct (Map32 []) ["223"; "000"; "000";"000"; "000"]. +Proof. +unfold Correct. +intros. +simpl. +unfold atat. +rewrite <- ascii32_of_nat_O. +reflexivity. +Qed. + +Lemma correct_fixarray_cons: forall x xs y ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length (x::xs)) -> + Serialized x y -> + Correct x y -> + Serialized (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Correct (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Correct (FixArray (x :: xs)) ((Ascii b5 b6 b7 b8 true false false true)::y ++ ys). +Proof. +unfold Correct. +intros. +simpl in *. +unfold atat in *. +rewrite_for (ascii8_of_nat (S (length xs))). +apply H2 in H1. +apply H4 in H3. +rewrite_for (ascii8_of_nat (length xs)). +rewrite_for y. +inversion H3. +reflexivity. +Qed. + +Lemma correct_array16_cons: forall x xs t1 t2 s1 s2 y ys, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length (x :: xs)) -> + Serialized x y -> + (Serialized x y -> Correct x y) -> + Serialized (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + (Serialized (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + Correct (Array16 xs) ("220" :: t1 :: t2 :: ys)) -> + Correct (Array16 (x :: xs)) ("220" :: s1 :: s2 :: y ++ ys). +Proof. +unfold Correct. +intros. +simpl in *. +rewrite_for (ascii16_of_nat (S (length xs))). +apply H2 in H1; auto. +apply H4 in H3; auto. +rewrite_for (ascii16_of_nat (length xs)). +rewrite_for y. +inversion H3. +reflexivity. +Qed. + +Lemma correct_array32_cons: forall x xs y ys s1 s2 s3 s4 t1 t2 t3 t4, + ((t1,t2),(t3,t4)) = ascii32_of_nat (length xs) -> + ((s1,s2),(s3,s4)) = ascii32_of_nat (length (x::xs)) -> + Serialized x y -> + (Serialized x y -> Correct x y) -> + Serialized (Array32 xs) ("221"::t1::t2::t3::t4::ys) -> + (Serialized (Array32 xs) ("221"::t1::t2::t3::t4::ys) -> Correct (Array32 xs) ("221"::t1::t2::t3::t4::ys)) -> + Correct (Array32 (x::xs)) ("221"::s1::s2::s3::s4::y ++ ys). +Proof. +unfold Correct. +intros. +simpl in *. +unfold atat in *. +rewrite_for (ascii32_of_nat (S (length xs))). +apply H2 in H1; auto. +apply H4 in H3; auto. +rewrite_for (ascii32_of_nat (length xs)). +rewrite_for y. +inversion H3. +reflexivity. +Qed. + +Lemma correct_fixmap_cons: forall x1 x2 xs y1 y2 ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length ((x1,x2)::xs)) -> + Serialized x1 y1 -> Correct x1 y1 -> + Serialized x2 y2 -> Correct x2 y2 -> + Serialized (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Correct (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Correct (FixMap ((x1, x2) :: xs)) (Ascii b5 b6 b7 b8 false false false true :: y1 ++ y2 ++ ys). +Proof. +unfold Correct. +intros. +simpl in *. +unfold atat in *. +rewrite_for (ascii8_of_nat (S (length xs))). +apply H2 in H1. +apply H4 in H3. +apply H6 in H5. +rewrite_for (ascii8_of_nat (length xs)). +rewrite_for y1. +rewrite_for y2. +inversion H5. +rewrite <- app_assoc. +reflexivity. +Qed. + +Lemma correct_map16_cons: forall x1 x2 xs y1 y2 ys s1 s2 t1 t2, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Correct x1 y1 -> + Serialized x2 y2 -> + Correct x2 y2 -> + Serialized (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Correct (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Correct (Map16 ((x1, x2) :: xs)) ("222" :: s1 :: s2 :: y1 ++ y2 ++ ys). +Proof. +unfold Correct. +intros. +simpl in *. +rewrite_for (ascii16_of_nat (S (length xs))). +apply H2 in H1. +apply H4 in H3. +apply H6 in H5. +rewrite_for (ascii16_of_nat (length xs)). +rewrite_for y1. +rewrite_for y2. +inversion H5. +rewrite <- app_assoc. +reflexivity. +Qed. + +Lemma correct_map32_cons : forall x1 x2 xs y1 y2 ys s1 s2 s3 s4 t1 t2 t3 t4, + (t1, t2, (t3, t4)) = ascii32_of_nat (length xs) -> + (s1, s2, (s3, s4)) = ascii32_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Correct x1 y1 -> + Serialized x2 y2 -> + Correct x2 y2 -> + Serialized (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Correct (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Correct (Map32 ((x1, x2) :: xs)) ("223" :: s1 :: s2 :: s3 :: s4 :: y1 ++ y2 ++ ys). +Proof. +unfold Correct. +intros. +simpl in *. +unfold atat in *. +rewrite_for (ascii32_of_nat (S (length xs))). +apply H2 in H1. +apply H4 in H3. +apply H6 in H5. +rewrite_for (ascii32_of_nat (length xs)). +rewrite_for y1. +rewrite_for y2. +inversion H5. +rewrite <- app_assoc. +reflexivity. +Qed. + +Lemma correct_intro : forall obj xs, + (Serialized obj xs -> Correct obj xs) -> + Correct obj xs. +Proof. +unfold Correct. +intros. +apply H in H0; auto. +Qed. + +Hint Resolve + correct_true correct_false + correct_nil correct_pfixnum correct_nfixnum + correct_uint8 correct_uint16 correct_uint32 correct_uint64 + correct_int8 correct_int16 correct_int32 correct_int64 + correct_float correct_double + correct_raw16 correct_raw32 + correct_fixarray_nil correct_array16_nil correct_array32_nil + correct_fixmap_nil correct_map16_nil correct_map32_nil + : correct. + + +Theorem serialize_correct : forall obj xs, + Correct obj xs. +Proof. +intros. +apply correct_intro. +intro. +pattern obj,xs. +apply Serialized_ind; intros; auto with correct. + apply correct_fixraw; auto. + apply correct_fixarray_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply correct_array16_cons with (t1:=t1) (t2:=t2); auto. + apply correct_array32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. + apply correct_fixmap_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply correct_map16_cons with (t1:=t1) (t2:=t2); auto. + apply correct_map32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. +Qed. diff --git a/ocaml/proof/SerializeSpec.v b/ocaml/proof/SerializeSpec.v new file mode 100644 index 00000000..a071c62a --- /dev/null +++ b/ocaml/proof/SerializeSpec.v @@ -0,0 +1,99 @@ +Require Import List Ascii. +Require Import MultiByte Object ListUtil. + +Open Scope list_scope. +Open Scope char_scope. + +Inductive Serialized : object -> list ascii8 -> Prop := +| SNil : + Serialized Nil ["192"] +| STrue : + Serialized (Bool true) ["195"] +| SFalse : + Serialized (Bool false) ["194"] +| SPFixnum : forall x1 x2 x3 x4 x5 x6 x7, + Serialized (PFixnum (Ascii x1 x2 x3 x4 x5 x6 x7 false)) + [Ascii x1 x2 x3 x4 x5 x6 x7 false] +| SNFixnum : forall x1 x2 x3 x4 x5, + Serialized (NFixnum (Ascii x1 x2 x3 x4 x5 true true true)) + [Ascii x1 x2 x3 x4 x5 true true true] +| SUint8 : forall c, + Serialized (Uint8 c) ("204"::list_of_ascii8 c) +| SUint16 : forall c, + Serialized (Uint16 c) ("205"::list_of_ascii16 c) +| SUint32 : forall c, + Serialized (Uint32 c) ("206"::list_of_ascii32 c) +| SUint64 : forall c, + Serialized (Uint64 c) ("207"::list_of_ascii64 c) +| SInt8 : forall c, + Serialized (Int8 c) ("208"::list_of_ascii8 c) +| SInt16 : forall c, + Serialized (Int16 c) ("209"::list_of_ascii16 c) +| SInt32 : forall c, + Serialized (Int32 c) ("210"::list_of_ascii32 c) +| SInt64 : forall c, + Serialized (Int64 c) ("211"::list_of_ascii64 c) +| SFloat : forall c, + Serialized (Float c) ("202"::list_of_ascii32 c) +| SDouble : forall c, + Serialized (Double c) ("203"::list_of_ascii64 c) +| SFixRaw : forall cs b1 b2 b3 b4 b5, + Ascii b1 b2 b3 b4 b5 false false false = ascii8_of_nat (length cs) -> + Serialized (FixRaw cs) ((Ascii b1 b2 b3 b4 b5 true false true)::cs) +| SRaw16 : forall cs s1 s2, + (s1,s2) = ascii16_of_nat (length cs) -> + Serialized (Raw16 cs) ("218"::s1::s2::cs) +| SRaw32 : forall cs s1 s2 s3 s4, + ((s1,s2),(s3,s4)) = ascii32_of_nat (length cs) -> + Serialized (Raw32 cs) ("219"::s1::s2::s3::s4::cs) +| SFixArrayNil : + Serialized (FixArray []) ["144"] +| SFixArrayCons : forall x xs y ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length (x::xs)) -> + Serialized x y -> + Serialized (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Serialized (FixArray (x::xs)) ((Ascii b5 b6 b7 b8 true false false true)::y ++ ys) +| SArray16Nil : + Serialized (Array16 []) ["220"; "000"; "000"] +| SArray16Cons : forall x xs y ys s1 s2 t1 t2, + (t1,t2) = ascii16_of_nat (length xs) -> + (s1,s2) = ascii16_of_nat (length (x::xs)) -> + Serialized x y -> + Serialized (Array16 xs) ("220"::t1::t2::ys) -> + Serialized (Array16 (x::xs)) ("220"::s1::s2::y ++ ys) +| SArray32Nil : + Serialized (Array32 []) ["221"; "000"; "000";"000"; "000"] +| SArray32Cons : forall x xs y ys s1 s2 s3 s4 t1 t2 t3 t4, + ((t1,t2),(t3,t4)) = ascii32_of_nat (length xs) -> + ((s1,s2),(s3,s4)) = ascii32_of_nat (length (x::xs)) -> + Serialized x y -> + Serialized (Array32 xs) ("221"::t1::t2::t3::t4::ys) -> + Serialized (Array32 (x::xs)) ("221"::s1::s2::s3::s4::y ++ ys) +| SFixMapNil : + Serialized (FixMap []) ["128"] +| SFixMapCons : forall x1 x2 xs y1 y2 ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length ((x1,x2)::xs)) -> + Serialized x1 y1 -> + Serialized x2 y2 -> + Serialized (FixMap xs) ((Ascii b1 b2 b3 b4 false false false true)::ys) -> + Serialized (FixMap ((x1,x2)::xs)) ((Ascii b5 b6 b7 b8 false false false true)::y1 ++ y2 ++ ys) +| SMap16Nil : + Serialized (Map16 []) ["222"; "000"; "000"] +| SMap16Cons : forall x1 x2 xs y1 y2 ys s1 s2 t1 t2, + (t1,t2) = ascii16_of_nat (length xs) -> + (s1,s2) = ascii16_of_nat (length ((x1,x2)::xs)) -> + Serialized x1 y1 -> + Serialized x2 y2 -> + Serialized (Map16 xs) ("222"::t1::t2::ys) -> + Serialized (Map16 ((x1,x2)::xs)) ("222"::s1::s2::y1 ++ y2 ++ ys) +| SMap32Nil : + Serialized (Map32 []) ["223"; "000"; "000";"000"; "000"] +| SMap32Cons : forall x1 x2 xs y1 y2 ys s1 s2 s3 s4 t1 t2 t3 t4, + ((t1,t2),(t3,t4)) = ascii32_of_nat (length xs) -> + ((s1,s2),(s3,s4)) = ascii32_of_nat (length ((x1,x2)::xs)) -> + Serialized x1 y1 -> + Serialized x2 y2 -> + Serialized (Map32 xs) ("223"::t1::t2::t3::t4::ys) -> + Serialized (Map32 ((x1,x2)::xs)) ("223"::s1::s2::s3::s4::y1 ++ y2 ++ ys). diff --git a/ocaml/proof/SerializedList.v b/ocaml/proof/SerializedList.v new file mode 100644 index 00000000..e2da9e5f --- /dev/null +++ b/ocaml/proof/SerializedList.v @@ -0,0 +1,521 @@ +Require Import Ascii List. +Require Import ListUtil Object MultiByte Util SerializeSpec Pow. + +Open Scope char_scope. + +Definition lift P (o : object) (b : list ascii) := forall os bs, + P os bs -> P (o::os) (b ++ bs). + +Inductive SerializedList : list object -> list ascii8 -> Prop := +| SLbot : + SerializedList [] [] +| SLNil: + lift SerializedList Nil ["192"] +| SLTrue : + lift SerializedList (Bool true) ["195"] +| SLFalse : + lift SerializedList (Bool false) ["194"] +| SLPFixnum : forall x1 x2 x3 x4 x5 x6 x7, + lift SerializedList (PFixnum (Ascii x1 x2 x3 x4 x5 x6 x7 false)) + [Ascii x1 x2 x3 x4 x5 x6 x7 false] +| SLNFixnum : forall x1 x2 x3 x4 x5, + lift SerializedList (NFixnum (Ascii x1 x2 x3 x4 x5 true true true)) + [Ascii x1 x2 x3 x4 x5 true true true] +| SLUint8 : forall c, + lift SerializedList (Uint8 c) ("204" :: list_of_ascii8 c) +| SLUint16 : forall c, + lift SerializedList (Uint16 c) ("205" :: list_of_ascii16 c) +| SLUint32 : forall c, + lift SerializedList (Uint32 c) ("206" :: list_of_ascii32 c) +| SLUint64 : forall c, + lift SerializedList (Uint64 c) ("207" :: list_of_ascii64 c) +| SLInt8 : forall c, + lift SerializedList (Int8 c) ("208" :: list_of_ascii8 c) +| SLInt16 : forall c, + lift SerializedList (Int16 c) ("209" :: list_of_ascii16 c) +| SLInt32 : forall c, + lift SerializedList (Int32 c) ("210" :: list_of_ascii32 c) +| SLInt64 : forall c, + lift SerializedList (Int64 c) ("211" :: list_of_ascii64 c) +| SLFloat : forall c, + lift SerializedList (Float c) ("202" :: list_of_ascii32 c) +| SLDouble : forall c, + lift SerializedList (Double c) ("203" :: list_of_ascii64 c) +| SLFixRaw : forall cs b1 b2 b3 b4 b5, + Ascii b1 b2 b3 b4 b5 false false false = ascii8_of_nat (length cs) -> + List.length cs < pow 5 -> + lift SerializedList (FixRaw cs) ((Ascii b1 b2 b3 b4 b5 true false true) :: cs) +| SLRaw16 : forall cs s1 s2, + (s1,s2) = ascii16_of_nat (length cs) -> + List.length cs < pow 16 -> + lift SerializedList (Raw16 cs) ("218" :: s1 :: s2 :: cs) +| SLRaw32 : forall cs s1 s2 s3 s4, + ((s1,s2),(s3,s4)) = ascii32_of_nat (length cs) -> + List.length cs < pow 32 -> + lift SerializedList (Raw32 cs) ("219" :: s1 :: s2 :: s3 :: s4 :: cs) +| SLFixArray : forall os n b1 b2 b3 b4 xs ys bs, + SerializedList os bs -> + (xs,ys) = split_at n os -> + n < pow 4 -> + (Ascii b1 b2 b3 b4 false false false false) = ascii8_of_nat n -> + SerializedList ((FixArray xs) :: ys) ((Ascii b1 b2 b3 b4 true false false true) :: bs) +| SLArray16 : forall os n xs ys bs s1 s2, + SerializedList os bs -> + (xs,ys) = split_at n os -> + n < pow 16 -> + (s1,s2) = ascii16_of_nat n -> + SerializedList ((Array16 xs)::ys) ("220" :: s1 :: s2 :: bs) +| SLArray32 : forall os n xs ys bs s1 s2 s3 s4, + SerializedList os bs -> + (xs,ys) = split_at n os -> + n < pow 32 -> + ((s1,s2),(s3,s4)) = ascii32_of_nat n -> + SerializedList ((Array32 xs)::ys) ("221" :: s1 :: s2 :: s3 :: s4 :: bs) +| SLFixMap : forall os n b1 b2 b3 b4 xs ys bs, + SerializedList os bs -> + (xs,ys) = split_at (2 * n) os -> + List.length xs = 2 * n -> + n < pow 4 -> + (Ascii b1 b2 b3 b4 false false false false) = ascii8_of_nat n -> + SerializedList ((FixMap (pair xs)) :: ys) ((Ascii b1 b2 b3 b4 false false false true) :: bs) +| SLMap16 : forall os n xs ys bs s1 s2, + SerializedList os bs -> + (xs,ys) = split_at (2 * n) os -> + List.length xs = 2 * n -> + n < pow 16 -> + (s1,s2) = ascii16_of_nat n -> + SerializedList ((Map16 (pair xs))::ys) ("222" :: s1 :: s2 :: bs) +| SLMap32 : forall os n xs ys bs s1 s2 s3 s4, + SerializedList os bs -> + (xs,ys) = split_at (2 * n) os -> + List.length xs = 2 * n -> + n < pow 32 -> + ((s1,s2),(s3,s4)) = ascii32_of_nat n -> + SerializedList ((Map32 (pair xs))::ys) ("223" :: s1 :: s2 :: s3 :: s4 :: bs). + +Lemma app_cons: forall A (xs ys zs : list A) x, + x :: (xs ++ ys) ++ zs = x :: (xs ++ ys ++ zs). +Proof. +induction xs; intros; simpl; auto. +rewrite (IHxs ys zs a). +reflexivity. +Qed. + +Definition Soundness o bs := forall os bs', + Serialized o bs -> + Valid o -> + SerializedList os bs' -> + SerializedList (o :: os) (bs ++ bs'). + +Ltac straitfoward P := + intros; + unfold Soundness; + intros os bs' Hs Hv Hsl; + apply P; + auto. + +Lemma soundness_nil: + Soundness Nil ["192"]. +Proof. +straitfoward SLNil. +Qed. + +Lemma soundness_false: + Soundness (Bool false) ["194"]. +Proof. +straitfoward SLFalse. +Qed. + +Lemma soundness_true: + Soundness (Bool true) ["195"]. +Proof. +straitfoward SLTrue. +Qed. + +Lemma soundness_pfixnum: forall x1 x2 x3 x4 x5 x6 x7, + Soundness (PFixnum (Ascii x1 x2 x3 x4 x5 x6 x7 false)) + [Ascii x1 x2 x3 x4 x5 x6 x7 false]. +Proof. +straitfoward SLPFixnum. +Qed. + +Lemma soundness_nfixnum: forall x1 x2 x3 x4 x5, + Soundness (NFixnum (Ascii x1 x2 x3 x4 x5 true true true)) + [Ascii x1 x2 x3 x4 x5 true true true]. +Proof. +straitfoward SLNFixnum. +Qed. + +Lemma soundness_uint8 : forall c, + Soundness (Uint8 c) ("204"::list_of_ascii8 c). +Proof. +straitfoward SLUint8. +Qed. + +Lemma soundness_uint16 : forall c, + Soundness (Uint16 c) ("205"::list_of_ascii16 c). +Proof. +straitfoward SLUint16. +Qed. + +Lemma soundness_uint32 : forall c, + Soundness (Uint32 c) ("206"::list_of_ascii32 c). +Proof. +straitfoward SLUint32. +Qed. + +Lemma soundness_uint64 : forall c, + Soundness (Uint64 c) ("207"::list_of_ascii64 c). +Proof. +straitfoward SLUint64. +Qed. + +Lemma soundness_int8 : forall c, + Soundness (Int8 c) ("208"::list_of_ascii8 c). +Proof. +straitfoward SLInt8. +Qed. + +Lemma soundness_int16 : forall c, + Soundness (Int16 c) ("209"::list_of_ascii16 c). +Proof. +straitfoward SLInt16. +Qed. + +Lemma soundness_int32 : forall c, + Soundness (Int32 c) ("210"::list_of_ascii32 c). +Proof. +straitfoward SLInt32. +Qed. + +Lemma soundness_int64 : forall c, + Soundness (Int64 c) ("211"::list_of_ascii64 c). +Proof. +straitfoward SLInt64. +Qed. + +Lemma soundness_float : forall c, + Soundness (Float c) ("202"::list_of_ascii32 c). +Proof. +straitfoward SLFloat. +Qed. + +Lemma soundness_double : forall c, + Soundness (Double c) ("203"::list_of_ascii64 c). +Proof. +straitfoward SLDouble. +Qed. + +Lemma soundness_fixraw : forall cs b1 b2 b3 b4 b5, + Ascii b1 b2 b3 b4 b5 false false false = ascii8_of_nat (length cs) -> + Soundness (FixRaw cs) ((Ascii b1 b2 b3 b4 b5 true false true)::cs). +Proof. +straitfoward SLFixRaw. +inversion Hv. +assumption. +Qed. + +Lemma soundness_raw16: forall cs s1 s2, + (s1,s2) = ascii16_of_nat (length cs) -> + Soundness (Raw16 cs) ("218"::s1::s2::cs). +Proof. +straitfoward SLRaw16. +inversion Hv. +assumption. +Qed. + +Lemma soundness_raw32 : forall cs s1 s2 s3 s4, + ((s1,s2),(s3,s4)) = ascii32_of_nat (length cs) -> + Soundness (Raw32 cs) ("219"::s1::s2::s3::s4::cs). +Proof. +straitfoward SLRaw32. +inversion Hv. +assumption. +Qed. + +Lemma soundness_fixarray_nil : + Soundness (FixArray []) ["144"]. +Proof. +unfold Soundness. +intros. +apply (SLFixArray os 0); auto. +Qed. + +Lemma soundness_array16_nil : + Soundness (Array16 []) ["220"; "000"; "000"]. +Proof. +unfold Soundness. +intros. +apply (SLArray16 os 0 _ _ bs' "000" "000"); auto. +rewrite <- ascii16_of_nat_O. +reflexivity. +Qed. + +Lemma soundness_array32_nil: + Soundness (Array32 []) ["221"; "000"; "000";"000"; "000"]. +Proof. +unfold Soundness. +intros. +apply (SLArray32 os 0 _ _ bs' "000" "000" "000" "000"); auto. +rewrite <- ascii32_of_nat_O. +reflexivity. +Qed. + +Lemma soundness_fixmap_nil: + Soundness (FixMap []) ["128"]. +Proof. +unfold Soundness. +intros. +apply (SLFixMap os 0 _ _ _ _ [] _ bs'); auto. +Qed. + +Lemma soundness_map16_nil: + Soundness (Map16 []) ["222"; "000"; "000"]. +Proof. +unfold Soundness. +intros. +apply (SLMap16 os 0 [] _ bs' "000" "000"); auto. +rewrite <- ascii16_of_nat_O. +reflexivity. +Qed. + +Lemma soundness_map32_nil: + Soundness (Map32 []) ["223"; "000"; "000";"000"; "000"]. +Proof. +unfold Soundness. +intros. +apply (SLMap32 os 0 [] _ bs' "000" "000" "000" "000"); auto. +rewrite <- ascii32_of_nat_O. +reflexivity. +Qed. + +Lemma soundness_fixarray_cons: forall x xs y ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length (x::xs)) -> + Serialized x y -> + Soundness x y -> + Serialized (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Soundness (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Soundness (FixArray (x :: xs)) ((Ascii b5 b6 b7 b8 true false false true)::y ++ ys). +Proof. +unfold Soundness. +intros. +simpl. +rewrite app_cons. +inversion H6. +apply (SLFixArray (x::(xs++os)) (length (x::xs))); auto. + apply (H2 (xs++os) (ys++bs')) in H1; auto. + apply (H4 os bs') in H3; auto. + inversion H3. + apply split_at_soundness in H21. + rewrite H21 in *. + assumption. + + apply split_at_length. +Qed. + +Lemma soundness_array16_cons: forall x xs t1 t2 s1 s2 y ys, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length (x :: xs)) -> + Serialized x y -> + Soundness x y -> + Serialized (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + Soundness (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + Soundness (Array16 (x :: xs)) ("220" :: s1 :: s2 :: y ++ ys). +Proof. +unfold Soundness. +intros. +simpl. +rewrite app_cons. +inversion H6. +apply (SLArray16 (x::(xs++os)) (length (x::xs))); auto. + apply (H2 (xs++os) (ys++bs')) in H1; auto. + apply (H4 os bs') in H3; auto. + inversion H3. + apply split_at_soundness in H19. + rewrite H19 in *. + assumption. + + apply split_at_length. +Qed. + +Lemma soundness_array32_cons: forall x xs y ys s1 s2 s3 s4 t1 t2 t3 t4, + ((t1,t2),(t3,t4)) = ascii32_of_nat (length xs) -> + ((s1,s2),(s3,s4)) = ascii32_of_nat (length (x::xs)) -> + Serialized x y -> + Soundness x y -> + Serialized (Array32 xs) ("221"::t1::t2::t3::t4::ys) -> + Soundness (Array32 xs) ("221"::t1::t2::t3::t4::ys) -> + Soundness (Array32 (x::xs)) ("221"::s1::s2::s3::s4::y ++ ys). +Proof. +unfold Soundness. +intros. +simpl. +rewrite app_cons. +inversion H6. +apply (SLArray32 (x::(xs++os)) (length (x::xs))); auto. + apply (H2 (xs++os) (ys++bs')) in H1; auto. + apply (H4 os bs') in H3; auto. + inversion H3. + apply split_at_soundness in H21. + rewrite H21 in *. + assumption. + + apply split_at_length. +Qed. + + +Lemma soundness_fixmap_cons: forall x1 x2 xs y1 y2 ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length ((x1,x2)::xs)) -> + Serialized x1 y1 -> Soundness x1 y1 -> + Serialized x2 y2 -> Soundness x2 y2 -> + Serialized (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Soundness (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Soundness (FixMap ((x1, x2) :: xs)) (Ascii b5 b6 b7 b8 false false false true :: y1 ++ y2 ++ ys). +Proof with auto. +unfold Soundness. +intros. +simpl. +rewrite app_cons. +rewrite <- app_assoc. +rewrite <- (pair_unpair _ ( (x1, x2) :: xs )). +inversion H8. +apply (SLFixMap (x1::x2::unpair xs++os) (length ((x1,x2)::xs))); auto. + apply (H2 ( x2 :: unpair xs ++ os ) ( y2 ++ ys ++ bs' )) in H1; auto. + apply (H4 ( unpair xs ++ os) ( ys ++ bs')) in H3; auto. + apply (H6 os bs') in H5; auto. + inversion H5. + rewrite (unpair_pair _ n); auto. + apply split_at_soundness in H25. + rewrite <- H25... + + apply unpair_split_at. + + apply unpair_length. +Qed. + +Lemma soundness_map16_cons: forall x1 x2 xs y1 y2 ys s1 s2 t1 t2, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Soundness x1 y1 -> + Serialized x2 y2 -> + Soundness x2 y2 -> + Serialized (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Soundness (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Soundness (Map16 ((x1, x2) :: xs)) ("222" :: s1 :: s2 :: y1 ++ y2 ++ ys). +Proof with auto. +unfold Soundness. +intros. +simpl. +rewrite app_cons. +rewrite <- app_assoc. +rewrite <- (pair_unpair _ ( (x1, x2) :: xs )). +inversion H8. +apply (SLMap16 (x1::x2::unpair xs++os) (length ((x1,x2)::xs))); auto. + apply (H2 ( x2 :: unpair xs ++ os ) ( y2 ++ ys ++ bs' )) in H1; auto. + apply (H4 ( unpair xs ++ os) ( ys ++ bs')) in H3; auto. + apply (H6 os bs') in H5; auto. + inversion H5. + rewrite (unpair_pair _ n); auto. + apply split_at_soundness in H23. + rewrite <- H23... + + apply unpair_split_at. + + apply unpair_length. +Qed. + +Lemma soundness_map32_cons : forall x1 x2 xs y1 y2 ys s1 s2 s3 s4 t1 t2 t3 t4, + (t1, t2, (t3, t4)) = ascii32_of_nat (length xs) -> + (s1, s2, (s3, s4)) = ascii32_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Soundness x1 y1 -> + Serialized x2 y2 -> + Soundness x2 y2 -> + Serialized (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Soundness (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Soundness (Map32 ((x1, x2) :: xs)) ("223" :: s1 :: s2 :: s3 :: s4 :: y1 ++ y2 ++ ys). +Proof with auto. +unfold Soundness. +intros. +simpl. +rewrite app_cons. +rewrite <- app_assoc. +rewrite <- (pair_unpair _ ( (x1, x2) :: xs )). +inversion H8. +apply (SLMap32 (x1::x2::unpair xs++os) (length ((x1,x2)::xs))); auto. + apply (H2 ( x2 :: unpair xs ++ os ) ( y2 ++ ys ++ bs' )) in H1; auto. + apply (H4 ( unpair xs ++ os) ( ys ++ bs')) in H3; auto. + apply (H6 os bs') in H5; auto. + inversion H5. + rewrite (unpair_pair _ n); auto. + apply split_at_soundness in H25. + rewrite <- H25... + + apply unpair_split_at. + + apply unpair_length. +Qed. + +Lemma soundness_intro : forall obj xs, + (Serialized obj xs -> Soundness obj xs) -> + Soundness obj xs. +Proof. +unfold Soundness. +intros. +eapply H in H0; auto. +apply H0. +auto. +Qed. + +Hint Resolve + soundness_true soundness_false + soundness_nil soundness_pfixnum soundness_nfixnum + soundness_uint8 soundness_uint16 soundness_uint32 soundness_uint64 + soundness_int8 soundness_int16 soundness_int32 soundness_int64 + soundness_float soundness_double + soundness_raw16 soundness_raw32 + soundness_fixarray_nil soundness_array16_nil soundness_array32_nil + soundness_fixmap_nil soundness_map16_nil soundness_map32_nil + : soundness. + + +Theorem serialize_soundness : forall obj xs, + Soundness obj xs. +Proof. +intros. +apply soundness_intro. +intro. +pattern obj,xs. +apply Serialized_ind; intros; auto with soundness. + apply soundness_fixraw; auto. + apply soundness_fixarray_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply soundness_array16_cons with (t1:=t1) (t2:=t2); auto. + apply soundness_array32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. + apply soundness_fixmap_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply soundness_map16_cons with (t1:=t1) (t2:=t2); auto. + apply soundness_map32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. +Qed. + +Lemma sl_soundness: forall o os bs bs', + Serialized o bs -> + Valid o -> + SerializedList os bs' -> + SerializedList (o :: os) (bs ++ bs'). +Proof. +intros. +apply soundness_intro; auto. +intro. +pattern o, bs. +apply Serialized_ind; intros; auto with soundness. + apply soundness_fixraw; auto. + apply soundness_fixarray_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply soundness_array16_cons with (t1:=t1) (t2:=t2); auto. + apply soundness_array32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. + apply soundness_fixmap_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply soundness_map16_cons with (t1:=t1) (t2:=t2); auto. + apply soundness_map32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. +Qed. + diff --git a/ocaml/proof/Soundness.v b/ocaml/proof/Soundness.v new file mode 100644 index 00000000..a3072e80 --- /dev/null +++ b/ocaml/proof/Soundness.v @@ -0,0 +1,623 @@ +Require Import Ascii. +Require Import ListUtil Object MultiByte SerializeSpec Prefix ProofUtil Pow. + +Definition Soundness obj1 x : Prop := forall obj2, + Serialized obj1 x -> + Serialized obj2 x -> + Valid obj1 -> + Valid obj2 -> + obj1 = obj2. + +Ltac straightfoward := + intros; + unfold Soundness; + intros obj2 Hs1 Hs2 V1 V2; + inversion Hs2; + reflexivity. + +Lemma soundness_nil: + Soundness Nil ["192"]. +Proof. +straightfoward. +Qed. + +Lemma soundness_true : + Soundness (Bool true) ["195"]. +Proof. +straightfoward. +Qed. + +Lemma soundness_false : + Soundness (Bool false) ["194"]. +Proof. +straightfoward. +Qed. + +Lemma soundness_pfixnum: forall x1 x2 x3 x4 x5 x6 x7, + Soundness (PFixnum (Ascii x1 x2 x3 x4 x5 x6 x7 false)) + [Ascii x1 x2 x3 x4 x5 x6 x7 false]. +Proof. +straightfoward. +Qed. + +Lemma soundness_nfixnum: forall x1 x2 x3 x4 x5, + Soundness (NFixnum (Ascii x1 x2 x3 x4 x5 true true true)) + [Ascii x1 x2 x3 x4 x5 true true true]. +Proof. +straightfoward. +Qed. + +Lemma soundness_uint8 : forall c, + Soundness (Uint8 c) ("204"::list_of_ascii8 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +rewrite_for obj2. +auto. +Qed. + +Lemma soundness_uint16 : forall c, + Soundness (Uint16 c) ("205"::list_of_ascii16 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_uint32 : forall c, + Soundness (Uint32 c) ("206"::list_of_ascii32 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_uint64 : forall c, + Soundness (Uint64 c) ("207"::list_of_ascii64 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_int8 : forall c, + Soundness (Int8 c) ("208"::list_of_ascii8 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_int16 : forall c, + Soundness (Int16 c) ("209"::list_of_ascii16 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_int32 : forall c, + Soundness (Int32 c) ("210"::list_of_ascii32 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_int64 : forall c, + Soundness (Int64 c) ("211"::list_of_ascii64 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_float : forall c, + Soundness (Float c) ("202"::list_of_ascii32 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_double : forall c, + Soundness (Double c) ("203"::list_of_ascii64 c). +Proof. +intros. +unfold Soundness. +intros obj2 Hs1 Hs2 V1 V2. +inversion Hs2. +assert (c = c0); [| rewrite_for c ]; auto with ascii. +Qed. + +Lemma soundness_fixraw : forall cs b1 b2 b3 b4 b5, + Ascii b1 b2 b3 b4 b5 false false false = ascii8_of_nat (length cs) -> + Soundness (FixRaw cs) ((Ascii b1 b2 b3 b4 b5 true false true)::cs). +Proof. +straightfoward. +Qed. + +Lemma soundness_raw16: forall cs s1 s2, + (s1,s2) = ascii16_of_nat (length cs) -> + Soundness (Raw16 cs) ("218"::s1::s2::cs). +Proof. +straightfoward. +Qed. + +Lemma soundness_raw32 : forall cs s1 s2 s3 s4, + ((s1,s2),(s3,s4)) = ascii32_of_nat (length cs) -> + Soundness (Raw32 cs) ("219"::s1::s2::s3::s4::cs). +Proof. +straightfoward. +Qed. + +Lemma soundness_fixarray_nil : + Soundness (FixArray []) ["144"]. +Proof. +unfold Soundness. +intros. +inversion H0; auto. +apply ascii8_not_O in H10; [ contradiction |]. +split; [ simpl; omega |]. +rewrite_for obj2. +inversion H2. +transitivity (pow 4); [ assumption |]. +apply pow_lt. +auto. +Qed. + +Lemma soundness_array16_nil : + Soundness (Array16 []) ["220"; "000"; "000"]. +Proof. +unfold Soundness. +intros. +inversion H0; auto. +apply ascii16_not_O in H8; [ contradiction |]. +split; [ simpl; omega |]. +rewrite_for obj2. +inversion H2. +assumption. +Qed. + +Lemma soundness_array32_nil: + Soundness (Array32 []) ["221"; "000"; "000";"000"; "000"]. +Proof. +unfold Soundness. +intros. +inversion H0; auto. +apply ascii32_not_O in H10; [ contradiction |]. +split; [ simpl; omega |]. +rewrite_for obj2. +inversion H2. +assumption. +Qed. + +Lemma soundness_fixmap_nil: + Soundness (FixMap []) ["128"]. +Proof. +unfold Soundness. +intros. +inversion H0; auto. +apply ascii8_not_O in H10; [ contradiction |]. +split; [ simpl; omega |]. +rewrite_for obj2. +inversion H2. +transitivity (pow 4); [ assumption |]. +apply pow_lt. +auto. +Qed. + +Lemma soundness_map16_nil: + Soundness (Map16 []) ["222"; "000"; "000"]. +Proof. +unfold Soundness. +intros. +inversion H0; auto. +apply ascii16_not_O in H7; [ contradiction |]. +split; [ simpl; omega |]. +rewrite_for obj2. +inversion H2. +assumption. +Qed. + +Lemma soundness_map32_nil: + Soundness (Map32 []) ["223"; "000"; "000";"000"; "000"]. +Proof. +unfold Soundness. +intros. +inversion H0; auto. +apply ascii32_not_O in H10; [ contradiction |]. +split; [ simpl; omega |]. +rewrite_for obj2. +inversion H2. +assumption. +Qed. + +Lemma soundness_fixarray_cons: forall x xs y ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length (x::xs)) -> + Serialized x y -> + Soundness x y -> + Serialized (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Soundness (FixArray xs) ((Ascii b1 b2 b3 b4 true false false true)::ys) -> + Soundness (FixArray (x :: xs)) ((Ascii b5 b6 b7 b8 true false false true)::y ++ ys). +Proof. +unfold Soundness. +intros. +inversion H6. + rewrite_for b5. + rewrite_for b6. + rewrite_for b7. + rewrite_for b8. + apply ascii8_not_O in H0; [ contradiction |]. + split; [ simpl; omega |]. + inversion H7. + transitivity (pow 4); [| apply pow_lt ]; auto. + + rewrite_for obj2. + inversion H7. + inversion H8. + assert (y = y0). + generalize prefix. + unfold Prefix. + intro Hprefix. + apply (Hprefix x _ x0 _ ys ys0); auto. + + rewrite_for y0. + apply H2 with (obj2:=x0) in H1; auto. + apply app_same in H15. + apply H4 with (obj2:=(FixArray xs0)) in H3; auto. + inversion H3. + rewrite H1. + reflexivity. + + rewrite H16 in H0. + apply ascii8_of_nat_eq in H0; [| transitivity (pow 4); [| apply pow_lt]; auto + | transitivity (pow 4); [| apply pow_lt]; auto]. + simpl H0. + inversion H0. + rewrite <- H29 in H. + rewrite <- H14 in H. + inversion H. + rewrite_for b9. + rewrite_for b10. + rewrite_for ys. + assumption. +Qed. + +Lemma soundness_array16_cons: forall x xs t1 t2 s1 s2 y ys, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length (x :: xs)) -> + Serialized x y -> + (Serialized x y -> Soundness x y) -> + Serialized (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + (Serialized (Array16 xs) ("220" :: t1 :: t2 :: ys) -> + Soundness (Array16 xs) ("220" :: t1 :: t2 :: ys)) -> + Soundness (Array16 (x :: xs)) ("220" :: s1 :: s2 :: y ++ ys). +Proof. +unfold Soundness. +intros. +inversion H6. + rewrite_for s1. + rewrite_for s2. + apply ascii16_not_O in H0; [ contradiction |]. + split; [ simpl; omega |]. + inversion H7. + assumption. + + rewrite_for obj2. + inversion H7. + inversion H8. + assert (y = y0). + generalize prefix. + unfold Prefix. + intro Hprefix. + apply (Hprefix x _ x0 _ ys ys0); auto. + + rewrite_for y0. + apply H2 with (obj2:=x0) in H1; auto. + apply app_same in H11. + apply H4 with (obj2:=(Array16 xs0)) in H3; auto. + inversion H3. + rewrite H1. + reflexivity. + + rewrite H14 in H0. + simpl in H0. + apply ascii16_of_nat_eq in H0; auto. + inversion H0. + rewrite <- H27 in H. + rewrite <- H12 in H. + inversion H. + rewrite_for t0. + rewrite_for t3. + rewrite_for ys. + assumption. +Qed. + +Lemma soundness_array32_cons: forall x xs y ys s1 s2 s3 s4 t1 t2 t3 t4, + ((t1,t2),(t3,t4)) = ascii32_of_nat (length xs) -> + ((s1,s2),(s3,s4)) = ascii32_of_nat (length (x::xs)) -> + Serialized x y -> + (Serialized x y -> Soundness x y) -> + Serialized (Array32 xs) ("221"::t1::t2::t3::t4::ys) -> + (Serialized (Array32 xs) ("221"::t1::t2::t3::t4::ys) -> Soundness (Array32 xs) ("221"::t1::t2::t3::t4::ys)) -> + Soundness (Array32 (x::xs)) ("221"::s1::s2::s3::s4::y ++ ys). +Proof. +unfold Soundness. +intros. +inversion H6. + rewrite_for s1. + rewrite_for s2. + rewrite_for s3. + rewrite_for s4. + apply ascii32_not_O in H0; [ contradiction |]. + split; [ simpl; omega |]. + inversion H7. + assumption. + + rewrite_for obj2. + inversion H7. + inversion H8. + assert (y = y0). + generalize prefix. + unfold Prefix. + intro Hprefix. + apply (Hprefix x _ x0 _ ys ys0); auto. + + rewrite_for y0. + apply H2 with (obj2:=x0) in H1; auto. + apply app_same in H15. + apply H4 with (obj2:=(Array32 xs0)) in H3; auto. + inversion H3. + rewrite H1. + reflexivity. + + rewrite H16 in H0. + simpl in H0. + apply ascii32_of_nat_eq in H0; auto. + inversion H0. + rewrite <- H29 in H. + rewrite <- H14 in H. + inversion H. + rewrite_for t0. + rewrite_for t5. + rewrite_for t6. + rewrite_for t7. + rewrite_for ys. + assumption. +Qed. + +Lemma soundness_fixmap_cons: forall x1 x2 xs y1 y2 ys b1 b2 b3 b4 b5 b6 b7 b8, + Ascii b1 b2 b3 b4 false false false false = ascii8_of_nat (length xs) -> + Ascii b5 b6 b7 b8 false false false false = ascii8_of_nat (length ((x1,x2)::xs)) -> + Serialized x1 y1 -> Soundness x1 y1 -> + Serialized x2 y2 -> Soundness x2 y2 -> + Serialized (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Soundness (FixMap xs) (Ascii b1 b2 b3 b4 false false false true :: ys) -> + Soundness (FixMap ((x1, x2) :: xs)) (Ascii b5 b6 b7 b8 false false false true :: y1 ++ y2 ++ ys). +Proof. +unfold Soundness. +intros. +inversion H8. + rewrite_for b5. + rewrite_for b6. + rewrite_for b7. + rewrite_for b8. + apply ascii8_not_O in H0; [ contradiction |]. + split; [ simpl; omega |]. + inversion H9. + transitivity (pow 4); [| apply pow_lt]; auto. + + rewrite_for obj2. + inversion H9. + inversion H10. + generalize prefix. + unfold Prefix. + intro Hprefix. + assert (y1 = y0). + apply (Hprefix x1 _ x0 _ (y2 ++ ys) (y3 ++ ys0)); auto. + + rewrite_for y0. + apply app_same in H15. + assert (y2 = y3). + apply (Hprefix x2 _ x3 _ ys ys0); auto. + + rewrite_for y3. + apply H2 with (obj2:=x0) in H1; auto. + apply H4 with (obj2:=x3) in H3; auto. + apply H6 with (obj2:=(FixMap xs0)) in H5; auto. + inversion H5. + rewrite H1, H3. + reflexivity. + + rewrite H18 in H0. + simpl in H0. + apply ascii8_of_nat_eq in H0; [| transitivity (pow 4); [| apply pow_lt]; auto + | transitivity (pow 4); [| apply pow_lt]; auto]. + inversion H0. + rewrite <- H36 in H. + rewrite <- H17 in H. + inversion H. + rewrite_for b0. + rewrite_for b9. + rewrite_for b10. + rewrite_for b11. + apply app_same in H15. + rewrite_for ys. + assumption. +Qed. + +Lemma soundness_map16_cons: forall x1 x2 xs y1 y2 ys s1 s2 t1 t2, + (t1, t2) = ascii16_of_nat (length xs) -> + (s1, s2) = ascii16_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Soundness x1 y1 -> + Serialized x2 y2 -> + Soundness x2 y2 -> + Serialized (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Soundness (Map16 xs) ("222" :: t1 :: t2 :: ys) -> + Soundness (Map16 ((x1, x2) :: xs)) ("222" :: s1 :: s2 :: y1 ++ y2 ++ ys). +Proof. +unfold Soundness. +intros. +inversion H8. + rewrite_for s1. + rewrite_for s2. + apply ascii16_not_O in H0; [ contradiction |]. + split; [ simpl; omega |]. + inversion H9. + assumption. + + rewrite_for obj2. + inversion H9. + inversion H10. + generalize prefix. + unfold Prefix. + intro Hprefix. + assert (y1 = y0). + apply (Hprefix x1 _ x0 _ (y2 ++ ys) (y3 ++ ys0)); auto. + + rewrite_for y0. + apply app_same in H13. + assert (y2 = y3). + apply (Hprefix x2 _ x3 _ ys ys0); auto. + + rewrite_for y3. + + apply H2 with (obj2:=x0) in H1; auto. + apply H4 with (obj2:=x3) in H3; auto. + apply H6 with (obj2:=(Map16 xs0)) in H5; auto. + inversion H5. + rewrite H1, H3. + reflexivity. + + rewrite H15 in H0. + simpl in H0. + apply ascii16_of_nat_eq in H0; auto. + inversion H0. + rewrite <- H34 in H. + rewrite <- H14 in H. + inversion H. + rewrite_for t0. + rewrite_for t3. + apply app_same in H13. + rewrite_for ys. + assumption. +Qed. + +Lemma soundness_map32_cons : forall x1 x2 xs y1 y2 ys s1 s2 s3 s4 t1 t2 t3 t4, + (t1, t2, (t3, t4)) = ascii32_of_nat (length xs) -> + (s1, s2, (s3, s4)) = ascii32_of_nat (length ((x1, x2) :: xs)) -> + Serialized x1 y1 -> + Soundness x1 y1 -> + Serialized x2 y2 -> + Soundness x2 y2 -> + Serialized (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Soundness (Map32 xs) ("223" :: t1 :: t2 :: t3 :: t4 :: ys) -> + Soundness (Map32 ((x1, x2) :: xs)) ("223" :: s1 :: s2 :: s3 :: s4 :: y1 ++ y2 ++ ys). +Proof. +unfold Soundness. +intros. +inversion H8. + rewrite_for s1. + rewrite_for s2. + rewrite_for s3. + rewrite_for s4. + apply ascii32_not_O in H0; [ contradiction |]. + split; [ simpl; omega |]. + inversion H9. + assumption. + + rewrite_for obj2. + inversion H9. + inversion H10. + generalize prefix. + unfold Prefix. + intro Hprefix. + assert (y1 = y0). + apply (Hprefix x1 _ x0 _ (y2 ++ ys) (y3 ++ ys0)); auto. + + rewrite_for y0. + apply app_same in H15. + assert (y2 = y3). + apply (Hprefix x2 _ x3 _ ys ys0); auto. + + rewrite_for y3. + apply H2 with (obj2:=x0) in H1; auto. + apply H4 with (obj2:=x3) in H3; auto. + apply H6 with (obj2:=(Map32 xs0)) in H5; auto. + inversion H5. + rewrite H1, H3. + reflexivity. + + rewrite H18 in H0. + simpl in H0. + apply ascii32_of_nat_eq in H0; auto. + inversion H0. + rewrite <- H36 in H. + rewrite <- H17 in H. + inversion H. + rewrite_for t0. + rewrite_for t5. + rewrite_for t6. + rewrite_for t7. + apply app_same in H15. + rewrite_for ys. + assumption. +Qed. + +Hint Resolve + soundness_true soundness_false + soundness_nil soundness_pfixnum soundness_nfixnum + soundness_uint8 soundness_uint16 soundness_uint32 soundness_uint64 + soundness_int8 soundness_int16 soundness_int32 soundness_int64 + soundness_float soundness_double + soundness_raw16 soundness_raw32 + soundness_fixarray_nil soundness_array16_nil soundness_array32_nil + soundness_fixmap_nil soundness_map16_nil soundness_map32_nil + : soundness. + +Lemma soundness_intro: forall obj x, + (Serialized obj x -> Soundness obj x)-> + Soundness obj x. +Proof. +unfold Soundness. +intros. +apply H in H1; auto. +Qed. + +Theorem soundness : forall obj1 x, + Soundness obj1 x. +Proof. +intros. +apply soundness_intro. +intro. +pattern obj1,x. +apply Serialized_ind; intros; auto with soundness. + apply soundness_fixraw; auto. + apply soundness_fixarray_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply soundness_array16_cons with (t1:=t1) (t2:=t2); auto. + apply soundness_array32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. + apply soundness_fixmap_cons with (b1:=b1) (b2:=b2) (b3:=b3) (b4:=b4); auto. + apply soundness_map16_cons with (t1:=t1) (t2:=t2); auto. + apply soundness_map32_cons with (t1:=t1) (t2:=t2) (t3:=t3) (t4:=t4); auto. +Qed. diff --git a/ocaml/proof/Util.v b/ocaml/proof/Util.v new file mode 100644 index 00000000..1e104b36 --- /dev/null +++ b/ocaml/proof/Util.v @@ -0,0 +1,39 @@ +Require Ascii List. +Require Import ExtractUtil. + +Definition mlchar_of_ascii a := + mlchar_of_mlint (mlint_of_nat (Ascii.nat_of_ascii a)). +Definition mlstring_of_string s := + mlstring_of_list mlchar_of_ascii (list_of_string s). +Definition ascii_of_mlchar c := + Ascii.ascii_of_nat (nat_of_mlint (mlint_of_mlchar c)). +Definition string_of_mlstring s := + string_of_list (list_of_mlstring ascii_of_mlchar s). + +Definition print s := print_mlstring (mlstring_of_string s). +Definition println s := println_mlstring (mlstring_of_string s). +Definition prerr s := prerr_mlstring (mlstring_of_string s). +Definition prerrln s := prerrln_mlstring (mlstring_of_string s). + +CoFixpoint lmap {A B:Type} (f: A -> B) (xs : llist A) : llist B := + match xs with + | LNil => LNil + | LCons x xs => LCons (f x) (lmap f xs) + end. + +Fixpoint ltake {A:Type} n (xs: llist A) := + match (n, xs) with + | (O, _) => List.nil + | (_, LNil) => List.nil + | (S n', LCons x xs) => List.cons x (ltake n' xs) + end. + +Definition get_contents := lmap ascii_of_mlchar get_contents_mlchars. + +Definition id {A:Type} (x:A) := x. + +Definition atat {A B:Type} (f:A -> B) (x: A) := f x. +Infix "@@" := atat (right associativity, at level 75). + +Definition doll {A B C:Type} (g:B->C) (f:A->B) (x:A) := g (f x). +Infix "$" := doll (at level 75). From 24a8ee436f64a050086b10c934d726623ed14ceb Mon Sep 17 00:00:00 2001 From: Watabiki Naoya Date: Sun, 3 Apr 2011 18:39:41 +0900 Subject: [PATCH 27/53] add DateTemplate and BigDecimalTemplate --- .../msgpack/template/BigDecimalTemplate.java | 40 +++++++++++++++++++ .../org/msgpack/template/DateTemplate.java | 40 +++++++++++++++++++ 2 files changed, 80 insertions(+) create mode 100644 java/src/main/java/org/msgpack/template/BigDecimalTemplate.java create mode 100644 java/src/main/java/org/msgpack/template/DateTemplate.java diff --git a/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java b/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java new file mode 100644 index 00000000..6c1a6f9e --- /dev/null +++ b/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java @@ -0,0 +1,40 @@ +package org.msgpack.template; + +import java.io.IOException; +import java.math.BigDecimal; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; + +public class BigDecimalTemplate implements Template { + + @Override + public void pack(Packer pk, Object target) throws IOException { + BigDecimal temp = (BigDecimal) target; + pk.packString(temp.toString()); + } + + @Override + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + String temp = pac.unpackString(); + return new BigDecimal(temp); + } + + @Override + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + String temp = from.asString(); + return new BigDecimal(temp); + } + + static public BigDecimalTemplate getInstance() { + return instance; + } + + static final BigDecimalTemplate instance = new BigDecimalTemplate(); + + static { + TemplateRegistry.register(BigDecimal.class, instance); + } +} diff --git a/java/src/main/java/org/msgpack/template/DateTemplate.java b/java/src/main/java/org/msgpack/template/DateTemplate.java new file mode 100644 index 00000000..95d155ec --- /dev/null +++ b/java/src/main/java/org/msgpack/template/DateTemplate.java @@ -0,0 +1,40 @@ +package org.msgpack.template; + +import java.io.IOException; +import java.util.Date; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; + +public class DateTemplate implements Template { + + @Override + public void pack(Packer pk, Object target) throws IOException { + Date temp = (Date) target; + pk.packLong(temp.getTime()); + } + + @Override + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + Long temp = pac.unpackLong(); + return new Date(temp); + } + + @Override + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + Long temp = from.asLong(); + return new Date(temp); + } + + static public DateTemplate getInstance() { + return instance; + } + + static final DateTemplate instance = new DateTemplate(); + + static { + TemplateRegistry.register(Date.class, instance); + } +} From d354f2e8c2275a443b2906396ff9f43ade6ecb23 Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Sun, 3 Apr 2011 19:09:14 +0900 Subject: [PATCH 28/53] Documentation. --- go/pack.go | 31 ++++++++++++++++++++++++++++++- go/unpack.go | 4 ++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/go/pack.go b/go/pack.go index aadd7f93..c129166e 100644 --- a/go/pack.go +++ b/go/pack.go @@ -7,6 +7,7 @@ import ( "reflect" ); +// Packs a given value and writes it into the specified writer. func PackUint8(writer io.Writer, value uint8) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -14,6 +15,7 @@ func PackUint8(writer io.Writer, value uint8) (n int, err os.Error) { return writer.Write([]byte { 0xcc, byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackUint16(writer io.Writer, value uint16) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -23,6 +25,7 @@ func PackUint16(writer io.Writer, value uint16) (n int, err os.Error) { return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackUint32(writer io.Writer, value uint32) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -34,6 +37,7 @@ func PackUint32(writer io.Writer, value uint32) (n int, err os.Error) { return writer.Write([]byte { 0xce, byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackUint64(writer io.Writer, value uint64) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -48,6 +52,7 @@ func PackUint64(writer io.Writer, value uint64) (n int, err os.Error) { } func PackUint(writer io.Writer, value uint) (n int, err os.Error) { +// Packs a given value and writes it into the specified writer. switch unsafe.Sizeof(value) { case 4: return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) @@ -57,7 +62,7 @@ func PackUint(writer io.Writer, value uint) (n int, err os.Error) { return 0, os.ENOENT // never get here } - +// Packs a given value and writes it into the specified writer. func PackInt8(writer io.Writer, value int8) (n int, err os.Error) { if value < -32 { return writer.Write([]byte { 0xd0, byte(value) }) @@ -65,6 +70,7 @@ func PackInt8(writer io.Writer, value int8) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt16(writer io.Writer, value int16) (n int, err os.Error) { if value < -128 || value >= 128 { return writer.Write([]byte { 0xd1, byte(uint16(value) >> 8), byte(value) }) @@ -74,6 +80,7 @@ func PackInt16(writer io.Writer, value int16) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt32(writer io.Writer, value int32) (n int, err os.Error) { if value < -32768 || value >= 32768 { return writer.Write([]byte { 0xd2, byte(uint32(value) >> 24), byte(uint32(value) >> 16), byte(uint32(value) >> 8), byte(value) }) @@ -87,6 +94,7 @@ func PackInt32(writer io.Writer, value int32) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt64(writer io.Writer, value int64) (n int, err os.Error) { if value < -2147483648 || value >= 2147483648 { return writer.Write([]byte { 0xd3, byte(uint64(value) >> 56), byte(uint64(value) >> 48), byte(uint64(value) >> 40), byte(uint64(value) >> 32), byte(uint64(value) >> 24), byte(uint64(value) >> 16), byte(uint64(value) >> 8), byte(value) }) @@ -100,6 +108,7 @@ func PackInt64(writer io.Writer, value int64) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt(writer io.Writer, value int) (n int, err os.Error) { switch unsafe.Sizeof(value) { case 4: @@ -110,10 +119,12 @@ func PackInt(writer io.Writer, value int) (n int, err os.Error) { return 0, os.ENOENT // never get here } +// Packs a given value and writes it into the specified writer. func PackNil(writer io.Writer) (n int, err os.Error) { return writer.Write([]byte{ 0xc0 }) } +// Packs a given value and writes it into the specified writer. func PackBool(writer io.Writer, value bool) (n int, err os.Error) { var code byte; if value { @@ -124,14 +135,17 @@ func PackBool(writer io.Writer, value bool) (n int, err os.Error) { return writer.Write([]byte{ code }) } +// Packs a given value and writes it into the specified writer. func PackFloat32(writer io.Writer, value float32) (n int, err os.Error) { return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) } +// Packs a given value and writes it into the specified writer. func PackFloat64(writer io.Writer, value float64) (n int, err os.Error) { return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) } +// Packs a given value and writes it into the specified writer. func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { if len(value) < 32 { n1, err := writer.Write([]byte { 0xa0 | uint8(len(value)) }) @@ -150,6 +164,7 @@ func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { return n1 + n2, err } +// Packs a given value and writes it into the specified writer. func PackUint16Array(writer io.Writer, value []uint16) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -179,6 +194,7 @@ func PackUint16Array(writer io.Writer, value []uint16) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackUint32Array(writer io.Writer, value []uint32) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -208,6 +224,7 @@ func PackUint32Array(writer io.Writer, value []uint32) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackUint64Array(writer io.Writer, value []uint64) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -237,6 +254,7 @@ func PackUint64Array(writer io.Writer, value []uint64) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackUintArray(writer io.Writer, value []uint) (n int, err os.Error) { switch unsafe.Sizeof(0) { case 4: @@ -247,6 +265,7 @@ func PackUintArray(writer io.Writer, value []uint) (n int, err os.Error) { return 0, os.ENOENT // never get here } +// Packs a given value and writes it into the specified writer. func PackInt8Array(writer io.Writer, value []int8) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -276,6 +295,7 @@ func PackInt8Array(writer io.Writer, value []int8) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackInt16Array(writer io.Writer, value []int16) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -305,6 +325,7 @@ func PackInt16Array(writer io.Writer, value []int16) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackInt32Array(writer io.Writer, value []int32) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -334,6 +355,7 @@ func PackInt32Array(writer io.Writer, value []int32) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackInt64Array(writer io.Writer, value []int64) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -363,6 +385,7 @@ func PackInt64Array(writer io.Writer, value []int64) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackIntArray(writer io.Writer, value []int) (n int, err os.Error) { switch unsafe.Sizeof(0) { case 4: @@ -373,6 +396,7 @@ func PackIntArray(writer io.Writer, value []int) (n int, err os.Error) { return 0, os.ENOENT // never get here } +// Packs a given value and writes it into the specified writer. func PackFloat32Array(writer io.Writer, value []float32) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -402,6 +426,7 @@ func PackFloat32Array(writer io.Writer, value []float32) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -431,6 +456,7 @@ func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { { elemType, ok := value.Type().(reflect.ArrayOrSliceType).Elem().(*reflect.UintType) @@ -468,6 +494,7 @@ func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os return n, nil } +// Packs a given value and writes it into the specified writer. func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { keys := value.Keys() if value.Len() < 16 { @@ -507,6 +534,7 @@ func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { if value == nil || value.Type() == nil { return PackNil(writer) } switch _value := value.(type) { @@ -527,6 +555,7 @@ func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { panic("unsupported type: " + value.Type().String()) } +// Packs a given value and writes it into the specified writer. func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { if value == nil { return PackNil(writer) } switch _value := value.(type) { diff --git a/go/unpack.go b/go/unpack.go index a3753112..6bf0159d 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -272,10 +272,14 @@ func unpack(reader io.Reader, reflected bool) (v reflect.Value, n int, err os.Er return retval, nbytesread, nil } +// Reads a value from the reader, unpack and returns it. func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { return unpack(reader, false) } +// Reads unpack a value from the reader, unpack and returns it. When the +// value is an array or map, leaves the elements wrapped by corresponding +// wrapper objects defined in reflect package. func UnpackReflected(reader io.Reader) (v reflect.Value, n int, err os.Error) { return unpack(reader, true) } From 193906b8cee117738cd4ee2ea1612b12ba9f8563 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Sun, 3 Apr 2011 19:10:34 +0900 Subject: [PATCH 29/53] java: insert codes for initializing BigDecimalTemplate and DateTemplate instances to Templates.java --- java/src/main/java/org/msgpack/Templates.java | 12 +++++++++++- .../msgpack/template/BigDecimalTemplate.java | 17 +++++++++++++++++ .../java/org/msgpack/template/DateTemplate.java | 17 +++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/org/msgpack/Templates.java b/java/src/main/java/org/msgpack/Templates.java index 4972670e..f268fa0b 100644 --- a/java/src/main/java/org/msgpack/Templates.java +++ b/java/src/main/java/org/msgpack/Templates.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -76,6 +76,11 @@ public class Templates { return TBigInteger; } + public static final Template TBigDecimal = BigDecimalTemplate.getInstance(); + public static Template tBigDecimal() { + return TBigDecimal; + } + public static final Template TFloat = FloatTemplate.getInstance(); public static Template tFloat() { return TFloat; @@ -105,5 +110,10 @@ public class Templates { public static Template tByteBuffer() { return TByteBuffer; } + + public static final Template TDate = DateTemplate.getInstance(); + public static Template tDate() { + return TDate; + } } diff --git a/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java b/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java index 6c1a6f9e..e8265a5d 100644 --- a/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java +++ b/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java @@ -1,3 +1,20 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2011 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; diff --git a/java/src/main/java/org/msgpack/template/DateTemplate.java b/java/src/main/java/org/msgpack/template/DateTemplate.java index 95d155ec..26adde68 100644 --- a/java/src/main/java/org/msgpack/template/DateTemplate.java +++ b/java/src/main/java/org/msgpack/template/DateTemplate.java @@ -1,3 +1,20 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2011 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; From a03418ab1274f389ac77df03b020906bef96a91f Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Sun, 3 Apr 2011 19:42:43 +0900 Subject: [PATCH 30/53] java: edit BuiltInTemplateLoader.java --- .../main/java/org/msgpack/template/BuiltInTemplateLoader.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/org/msgpack/template/BuiltInTemplateLoader.java b/java/src/main/java/org/msgpack/template/BuiltInTemplateLoader.java index 9ac9a8ed..4b8d618c 100644 --- a/java/src/main/java/org/msgpack/template/BuiltInTemplateLoader.java +++ b/java/src/main/java/org/msgpack/template/BuiltInTemplateLoader.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -21,6 +21,7 @@ public class BuiltInTemplateLoader { public static void load() { AnyTemplate.getInstance(); BigIntegerTemplate.getInstance(); + BigDecimalTemplate.getInstance(); BooleanArrayTemplate.getInstance(); BooleanTemplate.getInstance(); ByteArrayTemplate.getInstance(); @@ -28,6 +29,7 @@ public class BuiltInTemplateLoader { ByteTemplate.getInstance(); DoubleArrayTemplate.getInstance(); DoubleTemplate.getInstance(); + DateTemplate.getInstance(); FloatArrayTemplate.getInstance(); FloatTemplate.getInstance(); IntArrayTemplate.getInstance(); From d5e583b09ea084c2e091f2eaf33bbf61866bdc3c Mon Sep 17 00:00:00 2001 From: takeshita Date: Mon, 4 Apr 2011 01:37:24 +0900 Subject: [PATCH 31/53] Implement Scala MessagePack. Change Java MessagePack to fit Scala's. Minor version up for Java's MessagePack. --- java/.settings/org.eclipse.jdt.core.prefs | 6 +- java/msgpack.iml | 17 + java/pom.xml | 18 +- .../main/java/org/msgpack/MessagePack.java | 2 +- .../java/org/msgpack/annotation/Ignore.java | 2 +- .../java/org/msgpack/annotation/Index.java | 2 +- .../msgpack/annotation/MessagePackBeans.java | 35 + .../java/org/msgpack/annotation/Nullable.java | 2 +- .../java/org/msgpack/annotation/Optional.java | 2 +- .../java/org/msgpack/annotation/Required.java | 2 +- .../org/msgpack/template/BeansFieldEntry.java | 149 ++ .../template/BeansFieldEntryReader.java | 174 ++ .../BeansReflectionTemplateBuilder.java | 321 +++ .../java/org/msgpack/template/FieldEntry.java | 143 ++ .../msgpack/template/FieldEntryReader.java | 165 ++ .../java/org/msgpack/template/FieldList.java | 10 +- .../org/msgpack/template/IFieldEntry.java | 25 + .../msgpack/template/IFieldEntryReader.java | 8 + .../template/JavassistTemplateBuilder.java | 513 +--- .../template/ReflectionTemplateBuilder.java | 178 +- .../msgpack/template/TemplateRegistry.java | 47 +- .../builder/ArrayTemplateBuilder.java | 173 ++ .../builder/ArrayTemplateBuilderSelector.java | 35 + .../template/builder/BuilderSelector.java | 27 + .../builder/BuilderSelectorRegistry.java | 213 ++ .../builder/CustomTemplateBuilder.java | 53 + .../template/builder/EnumBuilderSelector.java | 26 + .../MessagePackBeansBuilderSelector.java | 40 + .../MessagePackMessageBuilderSelector.java | 38 + ...MessagePackOrdinalEnumBuilderSelector.java | 34 + .../builder/OrdinalEnumTemplateBuilder.java | 68 + .../template/builder/TemplateBuilder.java | 327 +++ .../template/javassist/BeansBuildContext.java | 273 ++ .../template/javassist/BuildContext.java | 273 ++ .../template/javassist/BuildContextBase.java | 244 ++ .../javassist/BuildContextFactory.java | 9 + .../template/javassist/JavassistTemplate.java | 36 + .../src/test/java/org/msgpack/TestArrays.java | 4 + .../template/BeansEntryReaderTest.java | 133 + .../org/msgpack/template/BeansEquals.java | 83 + ...ionTemplateBuilderJavaBeansPackUnpack.java | 2207 ++++++++++++++++ ...tReflectionTemplateBuilderPackConvert.java | 1417 +++++++++++ ...stReflectionTemplateBuilderPackUnpack.java | 1422 +++++++++++ ...estTemplateBuilderJavaBeansPackUnpack.java | 2234 +++++++++++++++++ .../TestTemplateBuilderPackConvert.java | 15 +- .../TestTemplateBuilderPackUnpack.java | 16 +- scala/.gitignore | 40 + scala/pom.xml | 158 ++ scala/src/main/scala/org/msgpack/App.scala | 15 + .../JavassistTypeScalaTemplateBuilder.scala | 521 ++++ .../scala/org/msgpack/ScalaMessagePack.scala | 76 + .../org/msgpack/ScalaTemplateBuilder.scala | 16 + .../ScalaTemplateBuilderSelector.scala | 48 + .../template/ImmutableListTemplate.scala | 49 + .../template/ImmutableMapTemplate.scala | 54 + .../template/MutableListTemplate.scala | 56 + .../msgpack/template/MutableMapTemplate.scala | 70 + .../scala/org/msgpack/ClassWithList.scala | 21 + .../test/scala/org/msgpack/ClassWithMap.scala | 19 + .../org/msgpack/CollectionPackSpec.scala | 71 + .../test/scala/org/msgpack/SampleClass.scala | 77 + .../msgpack/ScalaFieldEntryReaderSpec.scala | 120 + .../org/msgpack/ScalaMessagePackSpec.scala | 90 + 63 files changed, 12077 insertions(+), 645 deletions(-) create mode 100644 java/msgpack.iml create mode 100644 java/src/main/java/org/msgpack/annotation/MessagePackBeans.java create mode 100644 java/src/main/java/org/msgpack/template/BeansFieldEntry.java create mode 100644 java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java create mode 100644 java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/FieldEntry.java create mode 100644 java/src/main/java/org/msgpack/template/FieldEntryReader.java create mode 100644 java/src/main/java/org/msgpack/template/IFieldEntry.java create mode 100644 java/src/main/java/org/msgpack/template/IFieldEntryReader.java create mode 100644 java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/BuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java create mode 100644 java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java create mode 100644 java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BuildContext.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java create mode 100644 java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java create mode 100644 java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java create mode 100644 java/src/test/java/org/msgpack/template/BeansEquals.java create mode 100644 java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java create mode 100644 java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java create mode 100644 java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java create mode 100644 java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java create mode 100644 scala/.gitignore create mode 100644 scala/pom.xml create mode 100644 scala/src/main/scala/org/msgpack/App.scala create mode 100644 scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala create mode 100644 scala/src/main/scala/org/msgpack/ScalaMessagePack.scala create mode 100644 scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala create mode 100644 scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala create mode 100644 scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala create mode 100644 scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala create mode 100644 scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala create mode 100644 scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala create mode 100644 scala/src/test/scala/org/msgpack/ClassWithList.scala create mode 100644 scala/src/test/scala/org/msgpack/ClassWithMap.scala create mode 100644 scala/src/test/scala/org/msgpack/CollectionPackSpec.scala create mode 100644 scala/src/test/scala/org/msgpack/SampleClass.scala create mode 100644 scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala create mode 100644 scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala diff --git a/java/.settings/org.eclipse.jdt.core.prefs b/java/.settings/org.eclipse.jdt.core.prefs index c75ad473..b20b311f 100755 --- a/java/.settings/org.eclipse.jdt.core.prefs +++ b/java/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,5 @@ -#Mon Apr 19 22:18:48 JST 2010 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +#Sat Mar 26 02:44:20 JST 2011 eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.source=1.6 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/java/msgpack.iml b/java/msgpack.iml new file mode 100644 index 00000000..3a6d962d --- /dev/null +++ b/java/msgpack.iml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/java/pom.xml b/java/pom.xml index c8a19b3a..7663b30d 100755 --- a/java/pom.xml +++ b/java/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.msgpack msgpack - 0.5.1-devel + 0.5.2-SNAPSHOT MessagePack for Java MessagePack for Java @@ -81,6 +81,20 @@ scm:git://github.com/msgpack/msgpack.git + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + @@ -132,12 +146,14 @@ msgpack.org Repository at msgpack.org file://${project.build.directory}/website/maven2/ + true msgpack.org Repository at msgpack.org file://${project.build.directory}/website/maven2/ + diff --git a/java/src/main/java/org/msgpack/MessagePack.java b/java/src/main/java/org/msgpack/MessagePack.java index f3a73c06..c25023c4 100644 --- a/java/src/main/java/org/msgpack/MessagePack.java +++ b/java/src/main/java/org/msgpack/MessagePack.java @@ -22,8 +22,8 @@ import java.io.InputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.msgpack.template.TemplateRegistry; -import org.msgpack.template.TemplateBuilder; import org.msgpack.template.FieldList; +import org.msgpack.template.builder.TemplateBuilder; public class MessagePack { public static byte[] pack(Object obj) { diff --git a/java/src/main/java/org/msgpack/annotation/Ignore.java b/java/src/main/java/org/msgpack/annotation/Ignore.java index 96a37bb6..e052e58a 100644 --- a/java/src/main/java/org/msgpack/annotation/Ignore.java +++ b/java/src/main/java/org/msgpack/annotation/Ignore.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Ignore { } diff --git a/java/src/main/java/org/msgpack/annotation/Index.java b/java/src/main/java/org/msgpack/annotation/Index.java index 7c1b6598..d3b2181f 100644 --- a/java/src/main/java/org/msgpack/annotation/Index.java +++ b/java/src/main/java/org/msgpack/annotation/Index.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Index { int value(); diff --git a/java/src/main/java/org/msgpack/annotation/MessagePackBeans.java b/java/src/main/java/org/msgpack/annotation/MessagePackBeans.java new file mode 100644 index 00000000..0c361360 --- /dev/null +++ b/java/src/main/java/org/msgpack/annotation/MessagePackBeans.java @@ -0,0 +1,35 @@ +// +// 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.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import org.msgpack.template.FieldOption; + +/** + * Annotation for java beans class + * @author takeshita + * + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface MessagePackBeans { + FieldOption value() default FieldOption.DEFAULT; +} diff --git a/java/src/main/java/org/msgpack/annotation/Nullable.java b/java/src/main/java/org/msgpack/annotation/Nullable.java index e6893e72..56aea89e 100644 --- a/java/src/main/java/org/msgpack/annotation/Nullable.java +++ b/java/src/main/java/org/msgpack/annotation/Nullable.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Nullable { } diff --git a/java/src/main/java/org/msgpack/annotation/Optional.java b/java/src/main/java/org/msgpack/annotation/Optional.java index 7894f881..a137ec86 100644 --- a/java/src/main/java/org/msgpack/annotation/Optional.java +++ b/java/src/main/java/org/msgpack/annotation/Optional.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Optional { } diff --git a/java/src/main/java/org/msgpack/annotation/Required.java b/java/src/main/java/org/msgpack/annotation/Required.java index 16311085..de1d816b 100644 --- a/java/src/main/java/org/msgpack/annotation/Required.java +++ b/java/src/main/java/org/msgpack/annotation/Required.java @@ -22,7 +22,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -@Target({ElementType.FIELD, ElementType.PARAMETER}) +@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) public @interface Required { } diff --git a/java/src/main/java/org/msgpack/template/BeansFieldEntry.java b/java/src/main/java/org/msgpack/template/BeansFieldEntry.java new file mode 100644 index 00000000..00e1bcad --- /dev/null +++ b/java/src/main/java/org/msgpack/template/BeansFieldEntry.java @@ -0,0 +1,149 @@ +// +// 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.beans.PropertyDescriptor; +import java.io.IOException; +import java.lang.reflect.*; +import java.lang.annotation.*; +import java.util.List; +import java.util.ArrayList; +import java.util.EnumSet; +import org.msgpack.*; +import org.msgpack.annotation.*; + +/** + * Field entry for Java beans property. + * @author takeshita + * + */ +public class BeansFieldEntry implements IFieldEntry { + + PropertyDescriptor desc; + FieldOption option = FieldOption.DEFAULT; + + public BeansFieldEntry(PropertyDescriptor desc) { + this.desc = desc; + } + + @Override + public String getName() { + return desc.getDisplayName(); + } + public String getGetterName(){ + return desc.getReadMethod().getName(); + } + public String getSetterName(){ + return desc.getWriteMethod().getName(); + } + + @Override + public Class getType() { + return desc.getPropertyType(); + } + + @Override + public String getJavaTypeName() { + Class type = getType(); + if(type.isArray()) { + return arrayTypeToString(type); + } else { + return type.getName(); + } + } + static String arrayTypeToString(Class type) { + int dim = 1; + Class baseType = type.getComponentType(); + while(baseType.isArray()) { + baseType = baseType.getComponentType(); + dim += 1; + } + StringBuilder sb = new StringBuilder(); + sb.append(baseType.getName()); + for (int i = 0; i < dim; ++i) { + sb.append("[]"); + } + return sb.toString(); + } + + @Override + public Type getGenericType() { + return desc.getReadMethod().getGenericReturnType(); + } + + @Override + public FieldOption getOption() { + return option; + } + public void setOption(FieldOption option){ + this.option = option; + } + + @Override + public boolean isAvailable() { + return option != FieldOption.IGNORE; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isRequired() + */ + @Override + public boolean isRequired() { + return option == FieldOption.REQUIRED; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isOptional() + */ + @Override + public boolean isOptional() { + return option == FieldOption.OPTIONAL; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isNullable() + */ + @Override + public boolean isNullable() { + return option == FieldOption.NULLABLE; + } + + public Object get(Object target){ + try { + return desc.getReadMethod().invoke(target); + } catch (IllegalArgumentException e) { + throw new MessageTypeException(e); + } catch (IllegalAccessException e) { + throw new MessageTypeException(e); + } catch (InvocationTargetException e) { + throw new MessageTypeException(e); + } + } + public void set(Object target , Object value){ + try { + desc.getWriteMethod().invoke(target, value); + } catch (IllegalArgumentException e) { + throw new MessageTypeException(e); + } catch (IllegalAccessException e) { + throw new MessageTypeException(e); + } catch (InvocationTargetException e) { + throw new MessageTypeException(e); + } + } + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java b/java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java new file mode 100644 index 00000000..43536dcb --- /dev/null +++ b/java/src/main/java/org/msgpack/template/BeansFieldEntryReader.java @@ -0,0 +1,174 @@ +package org.msgpack.template; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; + +import org.msgpack.annotation.Ignore; +import org.msgpack.annotation.Index; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.Nullable; +import org.msgpack.annotation.Optional; +import org.msgpack.annotation.Required; + +/** + * List up Java beans property methods. + * @author takeshita + * + */ +public class BeansFieldEntryReader implements IFieldEntryReader{ + + + public IFieldEntry[] convertFieldEntries(Class targetClass, FieldList flist) throws NoSuchFieldException { + List src = flist.getList(); + FieldEntry[] result = new FieldEntry[src.size()]; + for(int i=0; i < src.size(); i++) { + FieldList.Entry s = src.get(i); + if(s.isAvailable()) { + result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); + } else { + result[i] = new FieldEntry(); + } + } + return result; + } + + @Override + public IFieldEntry[] readFieldEntries(Class targetClass, + FieldOption implicitOption) { + BeanInfo desc; + try { + desc = Introspector.getBeanInfo(targetClass); + } catch (IntrospectionException e1) { + throw new TemplateBuildException("Class must be java beans class:" + targetClass.getName()); + } + + PropertyDescriptor[] props = desc.getPropertyDescriptors(); + ArrayList list = new ArrayList(); + for(int i = 0;i < props.length;i++){ + PropertyDescriptor pd = props[i]; + if(!isIgnoreProp(pd)){ + list.add(pd); + } + } + props = new PropertyDescriptor[list.size()]; + list.toArray(props); + + BeansFieldEntry[] entries = new BeansFieldEntry[props.length]; + for(int i = 0;i < props.length;i++){ + PropertyDescriptor p = props[i]; + int index = readPropIndex(p); + if(index >= 0){ + if(entries[index] != null){ + throw new TemplateBuildException("duplicated index: "+index); + } + if(index >= entries.length){ + throw new TemplateBuildException("invalid index: "+index); + } + entries[index] = new BeansFieldEntry(p); + props[index] = null; + } + } + int insertIndex = 0; + for(int i = 0;i < props.length;i++){ + PropertyDescriptor p = props[i]; + if(p != null){ + while(entries[insertIndex] != null){ + insertIndex++; + } + entries[insertIndex] = new BeansFieldEntry(p); + } + + } + for(int i = 0;i < entries.length;i++){ + BeansFieldEntry e = entries[i]; + FieldOption op = readPropOption(e.desc, implicitOption); + e.setOption(op); + } + return entries; + } + + public FieldOption readImplicitFieldOption(Class targetClass) { + MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); + if(a == null) { + return FieldOption.DEFAULT; + } + return a.value(); + } + + + private FieldOption readPropOption(PropertyDescriptor desc, FieldOption implicitOption) { + + FieldOption forGetter = readMethodOption(desc.getReadMethod()); + if(forGetter != FieldOption.DEFAULT){ + return forGetter; + } + FieldOption forSetter = readMethodOption(desc.getWriteMethod()); + if(forSetter != FieldOption.DEFAULT){ + return forSetter; + }else{ + return implicitOption; + } + + } + private FieldOption readMethodOption(Method method){ + + if(isAnnotated(method, Ignore.class)) { + return FieldOption.IGNORE; + } else if(isAnnotated(method, Required.class)) { + return FieldOption.REQUIRED; + } else if(isAnnotated(method, Optional.class)) { + return FieldOption.OPTIONAL; + } else if(isAnnotated(method, Nullable.class)) { + if(method.getDeclaringClass().isPrimitive()) { + return FieldOption.REQUIRED; + } else { + return FieldOption.NULLABLE; + } + } + return FieldOption.DEFAULT; + } + + private int readPropIndex(PropertyDescriptor desc) { + + int forGetter = readMethodIndex(desc.getReadMethod()); + if(forGetter >= 0){ + return forGetter; + } + int forSetter = readMethodIndex(desc.getWriteMethod()); + return forSetter; + } + private int readMethodIndex(Method method){ + Index a = method.getAnnotation(Index.class); + if(a == null) { + return -1; + } else { + return a.value(); + } + } + + private boolean isAnnotated(AccessibleObject ao, Class with) { + return ao.getAnnotation(with) != null; + } + boolean isIgnoreProp(PropertyDescriptor desc){ + if(desc == null)return true; + Method getter = desc.getReadMethod(); + Method setter = desc.getWriteMethod(); + return getter == null || + setter == null || + !Modifier.isPublic(getter.getModifiers()) || + !Modifier.isPublic(setter.getModifiers()) || + isAnnotated(getter,Ignore.class) || + isAnnotated(setter, Ignore.class); + } +} diff --git a/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java new file mode 100644 index 00000000..8899399f --- /dev/null +++ b/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java @@ -0,0 +1,321 @@ +package org.msgpack.template; + +import java.io.IOException; +import java.lang.reflect.Field; + +import org.msgpack.AbstractTemplate; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.template.ReflectionTemplateBuilder.BooleanFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.ByteFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.DoubleFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.FloatFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.IntFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.LongFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.NullFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.ObjectFieldEntry; +import org.msgpack.template.ReflectionTemplateBuilder.ShortFieldEntry; +import org.msgpack.template.builder.CustomTemplateBuilder; + +/** + * Class for building java reflection template builder for java beans class. + * @author takeshita + * + */ +public class BeansReflectionTemplateBuilder extends CustomTemplateBuilder{ + + IFieldEntryReader reader = new BeansFieldEntryReader(); + + public BeansReflectionTemplateBuilder(){} + + @Override + public IFieldEntryReader getFieldEntryReader(){ + return reader; + } + + static class ReflectionEntry{ + BeansFieldEntry entry; + public ReflectionEntry(BeansFieldEntry entry){ + this.entry = entry; + } + + public void pack(Object value , Packer packer) throws IOException{ + packer.pack(value); + } + public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException { + entry.set(target, obj.convert(entry.getType())); + } + + public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException { + entry.set(target, unpacker.unpack(entry.getType())); + } + + public void setNull(Object target){ + entry.set(target, null); + } + + public boolean isRequired(){ + return entry.isRequired(); + } + public boolean isNullable(){ + return entry.isNullable(); + } + public boolean isAvailable(){ + return entry.isAvailable(); + } + public boolean isOptional(){ + return entry.isOptional(); + } + public Object get(Object target){ + return entry.get(target); + } + + } + + static class ObjectFieldEntry extends ReflectionEntry{ + Template template; + public ObjectFieldEntry(BeansFieldEntry entry,Template template){ + super(entry); + this.template = template; + } + public void pack(Object value , Packer packer) throws IOException{ + template.pack(packer,value); + } + public void convert(Object target, MessagePackObject obj) throws MessageTypeException, IllegalAccessException { + Class type = (Class)entry.getType(); + Object fieldReference = entry.get(target); + Object valueReference = template.convert(obj, fieldReference); + if(valueReference != fieldReference) { + entry.set(target, valueReference); + } + } + + public void unpack(Object target, Unpacker unpacker) throws IOException, MessageTypeException, IllegalAccessException { + + Class type = (Class)entry.getType(); + Object fieldReference = entry.get(target); + Object valueReference = template.unpack(unpacker, fieldReference); + if(valueReference != fieldReference) { + entry.set(target, valueReference); + } + } + } + + static class BeansReflectionTemplate extends AbstractTemplate{ + + Class targetClass; + ReflectionEntry[] entries = null; + protected int minimumArrayLength; + + public BeansReflectionTemplate( + Class targetClass, + ReflectionEntry[] entries){ + this.targetClass = targetClass; + this.entries = entries; + this.minimumArrayLength = 0; + for(int i=0; i < entries.length; i++) { + ReflectionEntry e = entries[i]; + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + } + } + + + @Override + public void pack(Packer pk, Object target) throws IOException { + + pk.packArray(entries.length); + for(ReflectionEntry e : entries){ + if(!e.isAvailable()){ + pk.packNil(); + continue; + } + Object obj = e.get(target); + if(obj == null) { + if(!e.isNullable() && !e.isOptional()) { + throw new MessageTypeException(); + } + pk.packNil(); + } else { + pk.pack(obj); + } + } + + } + @Override + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + try { + if(to == null) { + to = targetClass.newInstance(); + } + + int length = pac.unpackArray(); + if(length < minimumArrayLength) { + throw new MessageTypeException(); + } + + int i; + for(i=0; i < minimumArrayLength; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + pac.unpackObject(); + continue; + } + + if(pac.tryUnpackNull()) { + if(e.isRequired()) { + // Required + nil => exception + throw new MessageTypeException(); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + e.setNull(to); + } + } else { + e.unpack(to,pac); + //e.set(to, pac.unpack(e.getType())); + } + } + + int max = length < entries.length ? length : entries.length; + for(; i < max; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + pac.unpackObject(); + continue; + } + + if(pac.tryUnpackNull()) { + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + } else { + e.unpack(to, pac); + //e.set(to, pac.unpack(e.getType())); + } + } + + // latter entries are all Optional + nil => keep default value + + for(; i < length; i++) { + pac.unpackObject(); + } + + return to; + + } catch (MessageTypeException e) { + throw e; + } catch (IOException e) { + throw e; + } catch (Exception e) { + throw new MessageTypeException(e); + } + } + + @Override + public Object convert(MessagePackObject from, Object to) + throws MessageTypeException { + try { + if(to == null) { + to = targetClass.newInstance(); + } + + MessagePackObject[] array = from.asArray(); + int length = array.length; + if(length < minimumArrayLength) { + throw new MessageTypeException(); + } + + int i; + for(i=0; i < minimumArrayLength; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + MessagePackObject obj = array[i]; + if(obj.isNil()) { + if(e.isRequired()) { + // Required + nil => exception + throw new MessageTypeException(); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + e.setNull(to); + //e.set(to,null); + } + } else { + e.convert(to, obj); + //e.set(to, from.convert(e.getType())); + } + } + + int max = length < entries.length ? length : entries.length; + for(; i < max; i++) { + ReflectionEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + MessagePackObject obj = array[i]; + if(obj.isNil()) { + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + } else { + e.convert(to, obj); + //e.set(to, obj.convert(e.getType())); + } + } + + // latter entries are all Optional + nil => keep default value + + return to; + + } catch (MessageTypeException e) { + throw e; + } catch (Exception e) { + throw new MessageTypeException(e); + } + } + + } + + + @Override + public Template buildTemplate(Class targetClass, IFieldEntry[] entries) { + + ReflectionEntry[] refEntries = new ReflectionEntry[entries.length]; + for(int i = 0;i < entries.length;i++){ + BeansFieldEntry e = (BeansFieldEntry)entries[i]; + Class type = e.getType(); + if(type.equals(boolean.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(byte.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(short.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(int.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(long.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(float.class)) { + refEntries[i] = new ReflectionEntry(e); + } else if(type.equals(double.class)) { + refEntries[i] = new ReflectionEntry(e); + } else { + Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true); + refEntries[i] = new ObjectFieldEntry(e, tmpl); + } + } + + + return new BeansReflectionTemplate(targetClass,refEntries); + } + + +} diff --git a/java/src/main/java/org/msgpack/template/FieldEntry.java b/java/src/main/java/org/msgpack/template/FieldEntry.java new file mode 100644 index 00000000..2c474ec3 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/FieldEntry.java @@ -0,0 +1,143 @@ +// +// 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.lang.reflect.*; +import java.lang.annotation.*; +import java.util.List; +import java.util.ArrayList; +import java.util.EnumSet; +import org.msgpack.*; +import org.msgpack.annotation.*; + +public class FieldEntry implements IFieldEntry { + private Field field; + private FieldOption option; + + public FieldEntry() { + this.field = null; + this.option = FieldOption.IGNORE; + } + + public FieldEntry(FieldEntry e) { + this.field = e.field; + this.option = e.option; + } + + public FieldEntry(Field field, FieldOption option) { + this.field = field; + this.option = option; + } + + public Field getField() { + return field; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getName() + */ + @Override + public String getName() { + return field.getName(); + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getType() + */ + @Override + public Class getType() { + return field.getType(); + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getJavaTypeName() + */ + @Override + public String getJavaTypeName() { + Class type = field.getType(); + if(type.isArray()) { + return arrayTypeToString(type); + } else { + return type.getName(); + } + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getGenericType() + */ + @Override + public Type getGenericType() { + return field.getGenericType(); + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#getOption() + */ + @Override + public FieldOption getOption() { + return option; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isAvailable() + */ + @Override + public boolean isAvailable() { + return option != FieldOption.IGNORE; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isRequired() + */ + @Override + public boolean isRequired() { + return option == FieldOption.REQUIRED; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isOptional() + */ + @Override + public boolean isOptional() { + return option == FieldOption.OPTIONAL; + } + + /* (non-Javadoc) + * @see org.msgpack.template.IFieldEntry#isNullable() + */ + @Override + public boolean isNullable() { + return option == FieldOption.NULLABLE; + } + + static String arrayTypeToString(Class type) { + int dim = 1; + Class baseType = type.getComponentType(); + while(baseType.isArray()) { + baseType = baseType.getComponentType(); + dim += 1; + } + StringBuilder sb = new StringBuilder(); + sb.append(baseType.getName()); + for (int i = 0; i < dim; ++i) { + sb.append("[]"); + } + return sb.toString(); + } +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/FieldEntryReader.java b/java/src/main/java/org/msgpack/template/FieldEntryReader.java new file mode 100644 index 00000000..9d477465 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/FieldEntryReader.java @@ -0,0 +1,165 @@ +package org.msgpack.template; + +import java.lang.annotation.Annotation; +import java.lang.reflect.AccessibleObject; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.List; + +import org.msgpack.annotation.Ignore; +import org.msgpack.annotation.Index; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.Nullable; +import org.msgpack.annotation.Optional; +import org.msgpack.annotation.Required; + +public class FieldEntryReader implements IFieldEntryReader{ + + + public IFieldEntry[] convertFieldEntries(Class targetClass, FieldList flist) throws NoSuchFieldException { + List src = flist.getList(); + FieldEntry[] result = new FieldEntry[src.size()]; + for(int i=0; i < src.size(); i++) { + FieldList.Entry s = src.get(i); + if(s.isAvailable()) { + result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); + } else { + result[i] = new FieldEntry(); + } + } + return result; + } + + @Override + public IFieldEntry[] readFieldEntries(Class targetClass, + FieldOption implicitOption) { + Field[] allFields = readAllFields(targetClass); + + /* index: + * @Index(0) int field_a; // 0 + * int field_b; // 1 + * @Index(3) int field_c; // 3 + * int field_d; // 4 + * @Index(2) int field_e; // 2 + * int field_f; // 5 + */ + List indexed = new ArrayList(); + int maxIndex = -1; + for(Field f : allFields) { + FieldOption opt = readFieldOption(f, implicitOption); + if(opt == FieldOption.IGNORE) { + // skip + continue; + } + + int index = readFieldIndex(f, maxIndex); + + if(indexed.size() > index && indexed.get(index) != null) { + throw new TemplateBuildException("duplicated index: "+index); + } + if(index < 0) { + throw new TemplateBuildException("invalid index: "+index); + } + + while(indexed.size() <= index) { + indexed.add(null); + } + indexed.set(index, new FieldEntry(f, opt)); + + if(maxIndex < index) { + maxIndex = index; + } + } + + FieldEntry[] result = new FieldEntry[maxIndex+1]; + for(int i=0; i < indexed.size(); i++) { + FieldEntry e = indexed.get(i); + if(e == null) { + result[i] = new FieldEntry(); + } else { + result[i] = e; + } + } + + return result; + } + + public FieldOption readImplicitFieldOption(Class targetClass) { + MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); + if(a == null) { + return FieldOption.DEFAULT; + } + return a.value(); + } + + private Field[] readAllFields(Class targetClass) { + // order: [fields of super class, ..., fields of this class] + List succ = new ArrayList(); + int total = 0; + for(Class c = targetClass; c != Object.class; c = c.getSuperclass()) { + Field[] fields = c.getDeclaredFields(); + total += fields.length; + succ.add(fields); + } + Field[] result = new Field[total]; + int off = 0; + for(int i=succ.size()-1; i >= 0; i--) { + Field[] fields = succ.get(i); + System.arraycopy(fields, 0, result, off, fields.length); + off += fields.length; + } + return result; + } + + private static FieldOption readFieldOption(Field field, FieldOption implicitOption) { + int mod = field.getModifiers(); + if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) { + return FieldOption.IGNORE; + } + + if(isAnnotated(field, Ignore.class)) { + return FieldOption.IGNORE; + } else if(isAnnotated(field, Required.class)) { + return FieldOption.REQUIRED; + } else if(isAnnotated(field, Optional.class)) { + return FieldOption.OPTIONAL; + } else if(isAnnotated(field, Nullable.class)) { + if(field.getDeclaringClass().isPrimitive()) { + return FieldOption.REQUIRED; + } else { + return FieldOption.NULLABLE; + } + } + + if(implicitOption != FieldOption.DEFAULT) { + return implicitOption; + } + + // default mode: + // transient : Ignore + // public : Required + // others : Ignore + if(Modifier.isTransient(mod)) { + return FieldOption.IGNORE; + } else if(Modifier.isPublic(mod)) { + return FieldOption.REQUIRED; + } else { + return FieldOption.IGNORE; + } + } + + private static int readFieldIndex(Field field, int maxIndex) { + Index a = field.getAnnotation(Index.class); + if(a == null) { + return maxIndex + 1; + } else { + return a.value(); + } + } + + private static boolean isAnnotated(AccessibleObject ao, Class with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/FieldList.java b/java/src/main/java/org/msgpack/template/FieldList.java index daf59f5b..a5b141d9 100644 --- a/java/src/main/java/org/msgpack/template/FieldList.java +++ b/java/src/main/java/org/msgpack/template/FieldList.java @@ -43,19 +43,19 @@ public class FieldList { return option; } - boolean isAvailable() { + public boolean isAvailable() { return this.option != FieldOption.IGNORE; } - boolean isRequired() { + public boolean isRequired() { return this.option == FieldOption.REQUIRED; } - boolean isOptional() { + public boolean isOptional() { return this.option == FieldOption.OPTIONAL; } - boolean isNullable() { + public boolean isNullable() { return this.option == FieldOption.NULLABLE; } } @@ -89,7 +89,7 @@ public class FieldList { } } - List getList() { + public List getList() { return list; } } diff --git a/java/src/main/java/org/msgpack/template/IFieldEntry.java b/java/src/main/java/org/msgpack/template/IFieldEntry.java new file mode 100644 index 00000000..d12f7a8d --- /dev/null +++ b/java/src/main/java/org/msgpack/template/IFieldEntry.java @@ -0,0 +1,25 @@ +package org.msgpack.template; + +import java.lang.reflect.Type; + +public interface IFieldEntry { + + public abstract String getName(); + + public abstract Class getType(); + + public abstract String getJavaTypeName(); + + public abstract Type getGenericType(); + + public abstract FieldOption getOption(); + + public abstract boolean isAvailable(); + + public abstract boolean isRequired(); + + public abstract boolean isOptional(); + + public abstract boolean isNullable(); + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/IFieldEntryReader.java b/java/src/main/java/org/msgpack/template/IFieldEntryReader.java new file mode 100644 index 00000000..07a8f877 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/IFieldEntryReader.java @@ -0,0 +1,8 @@ +package org.msgpack.template; + +public interface IFieldEntryReader { + + public IFieldEntry[] convertFieldEntries(Class targetClass, FieldList flist) throws NoSuchFieldException; + public IFieldEntry[] readFieldEntries(Class targetClass, FieldOption implicitOption); + public FieldOption readImplicitFieldOption(Class targetClass) ; +} diff --git a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java index a4d2e4db..03d7f15d 100644 --- a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java @@ -22,6 +22,7 @@ import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Type; +import java.lang.Thread; import org.msgpack.*; @@ -34,11 +35,14 @@ import javassist.CtNewConstructor; import javassist.CtNewMethod; import javassist.LoaderClassPath; import javassist.NotFoundException; +import javassist.ClassClassPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.javassist.*; -public class JavassistTemplateBuilder extends TemplateBuilder { +public class JavassistTemplateBuilder extends CustomTemplateBuilder { private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class); private static JavassistTemplateBuilder instance; @@ -54,12 +58,33 @@ public class JavassistTemplateBuilder extends TemplateBuilder { getInstance().pool.appendClassPath(new LoaderClassPath(cl)); } - private JavassistTemplateBuilder() { + + IFieldEntryReader reader = new FieldEntryReader(); + + public void setFieldEntryReader(IFieldEntryReader reader){ + this.reader = reader; + } + + BuildContextFactory buildContextFactory = new BuildContextFactory() { + + @Override + public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) { + + return new BuildContext(builder); + } + }; + public void setBuildContextFactory(BuildContextFactory factory){ + this.buildContextFactory = factory; + } + + + + public JavassistTemplateBuilder() { pool = new ClassPool(); boolean appended = false; ClassLoader cl = null; try { - Thread.currentThread().getContextClassLoader(); + cl = Thread.currentThread().getContextClassLoader(); if (cl != null) { pool.appendClassPath(new LoaderClassPath(cl)); appended = true; @@ -80,471 +105,40 @@ public class JavassistTemplateBuilder extends TemplateBuilder { pool.appendSystemPath(); } } + /** + * Replace FieldEntryReader and BuilderContextFactory. + * you can replace field entry rules and generated codes easily. + * @param reader + * @param buildContextFactory + */ + public JavassistTemplateBuilder(IFieldEntryReader reader,BuildContextFactory buildContextFactory ){ + this(); + this.reader = reader; + this.buildContextFactory = buildContextFactory; + } + protected ClassPool pool; private int seqId = 0; - CtClass makeCtClass(String className) { + public CtClass makeCtClass(String className) { return pool.makeClass(className); } - CtClass getCtClass(String className) throws NotFoundException { + public CtClass getCtClass(String className) throws NotFoundException { return pool.get(className); } - int nextSeqId() { + public int nextSeqId() { return seqId++; } - private static abstract class BuildContextBase { - protected JavassistTemplateBuilder director; - protected String tmplName; - protected CtClass tmplCtClass; - protected abstract void setSuperClass() throws CannotCompileException, NotFoundException; - - protected abstract void buildConstructor() throws CannotCompileException, NotFoundException; - - protected void buildMethodInit() { } - - protected abstract String buildPackMethodBody(); - - protected abstract String buildUnpackMethodBody(); - - protected abstract String buildConvertMethodBody(); - - protected abstract Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException; - - public BuildContextBase(JavassistTemplateBuilder director) { - this.director = director; - } - - protected Template build(final String className) { - try { - reset(className); - buildClass(); - buildConstructor(); - buildMethodInit(); - buildPackMethod(); - buildUnpackMethod(); - buildConvertMethod(); - return buildInstance(createClass()); - } catch (Exception e) { - String code = getBuiltString(); - if(code != null) { - LOG.error("builder: " + code, e); - throw new TemplateBuildException("cannot compile: " + code, e); - } else { - throw new TemplateBuildException(e); - } - } - } - - protected void reset(String className) { - tmplName = className + "_$$_Template" + director.nextSeqId(); - tmplCtClass = director.makeCtClass(tmplName); - } - - protected void buildClass() throws CannotCompileException, NotFoundException { - setSuperClass(); - tmplCtClass.addInterface(director.getCtClass(Template.class.getName())); - } - - protected void buildPackMethod() throws CannotCompileException, NotFoundException { - String mbody = buildPackMethodBody(); - int mod = javassist.Modifier.PUBLIC; - CtClass returnType = CtClass.voidType; - String mname = "pack"; - CtClass[] paramTypes = new CtClass[] { - director.getCtClass(Packer.class.getName()), - director.getCtClass(Object.class.getName()) - }; - CtClass[] exceptTypes = new CtClass[] { - director.getCtClass(IOException.class.getName()) - }; - CtMethod newCtMethod = CtNewMethod.make( - mod, returnType, mname, - paramTypes, exceptTypes, mbody, tmplCtClass); - tmplCtClass.addMethod(newCtMethod); - } - - protected void buildUnpackMethod() throws CannotCompileException, NotFoundException { - String mbody = buildUnpackMethodBody(); - int mod = javassist.Modifier.PUBLIC; - CtClass returnType = director.getCtClass(Object.class.getName()); - String mname = "unpack"; - CtClass[] paramTypes = new CtClass[] { - director.getCtClass(Unpacker.class.getName()), - director.getCtClass(Object.class.getName()) - }; - CtClass[] exceptTypes = new CtClass[] { - director.getCtClass(MessageTypeException.class.getName()) - }; - CtMethod newCtMethod = CtNewMethod.make( - mod, returnType, mname, - paramTypes, exceptTypes, mbody, tmplCtClass); - tmplCtClass.addMethod(newCtMethod); - } - - protected void buildConvertMethod() throws CannotCompileException, NotFoundException { - String mbody = buildConvertMethodBody(); - int mod = javassist.Modifier.PUBLIC; - CtClass returnType = director.getCtClass(Object.class.getName()); - String mname = "convert"; - CtClass[] paramTypes = new CtClass[] { - director.getCtClass(MessagePackObject.class.getName()), - director.getCtClass(Object.class.getName()) - }; - CtClass[] exceptTypes = new CtClass[] { - director.getCtClass(MessageTypeException.class.getName()) - }; - CtMethod newCtMethod = CtNewMethod.make( - mod, returnType, mname, - paramTypes, exceptTypes, mbody, tmplCtClass); - tmplCtClass.addMethod(newCtMethod); - } - - protected Class createClass() throws CannotCompileException { - return (Class) tmplCtClass.toClass(null, null); - } - - protected StringBuilder stringBuilder = null; - - protected void resetStringBuilder() { - stringBuilder = new StringBuilder(); - } - - protected void buildString(String str) { - stringBuilder.append(str); - } - - protected void buildString(String format, Object... args) { - stringBuilder.append(String.format(format, args)); - } - - protected String getBuiltString() { - if(stringBuilder == null) { - return null; - } - return stringBuilder.toString(); - } - } - - public static abstract class JavassistTemplate extends AbstractTemplate { - public Class targetClass; - public Template[] templates; - - public JavassistTemplate(Class targetClass, Template[] templates) { - this.targetClass = targetClass; - this.templates = templates; - } - } - - private static class BuildContext extends BuildContextBase { - protected FieldEntry[] entries; - protected Class origClass; - protected String origName; - protected Template[] templates; - protected int minimumArrayLength; - - public BuildContext(JavassistTemplateBuilder director) { - super(director); - } - - public Template buildTemplate(Class targetClass, FieldEntry[] entries, Template[] templates) { - this.entries = entries; - this.templates = templates; - this.origClass = targetClass; - this.origName = this.origClass.getName(); - return build(this.origName); - } - - protected void setSuperClass() throws CannotCompileException, NotFoundException { - this.tmplCtClass.setSuperclass( - director.getCtClass(JavassistTemplate.class.getName())); - } - - protected void buildConstructor() throws CannotCompileException, NotFoundException { - // Constructor(Class targetClass, Template[] templates) - CtConstructor newCtCons = CtNewConstructor.make( - new CtClass[] { - director.getCtClass(Class.class.getName()), - director.getCtClass(Template.class.getName()+"[]") - }, - new CtClass[0], - this.tmplCtClass); - this.tmplCtClass.addConstructor(newCtCons); - } - - protected Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { - Constructor cons = c.getConstructor(new Class[] { - Class.class, - Template[].class - }); - Object tmpl = cons.newInstance(new Object[] { - this.origClass, - this.templates - }); - return (Template)tmpl; - } - - protected void buildMethodInit() { - this.minimumArrayLength = 0; - for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; - if(e.isRequired() || e.isNullable()) { - this.minimumArrayLength = i+1; - } - } - } - - protected String buildPackMethodBody() { - resetStringBuilder(); - buildString("{"); - buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); - buildString("$1.packArray(%d);", entries.length); - for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - buildString("$1.packNil();"); - continue; - } - Class type = e.getType(); - if(type.isPrimitive()) { - buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName()); - } else { - buildString("if(_$$_t.%s == null) {", e.getName()); - if(!e.isNullable() && !e.isOptional()) { - buildString("throw new %s();", MessageTypeException.class.getName()); - } else { - buildString("$1.packNil();"); - } - buildString("} else {"); - buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName()); - buildString("}"); - } - } - buildString("}"); - return getBuiltString(); - } - - protected String buildUnpackMethodBody() { - resetStringBuilder(); - buildString("{ "); - - buildString("%s _$$_t;", this.origName); - buildString("if($2 == null) {"); - buildString(" _$$_t = new %s();", this.origName); - buildString("} else {"); - buildString(" _$$_t = (%s)$2;", this.origName); - buildString("}"); - - buildString("int length = $1.unpackArray();"); - buildString("if(length < %d) {", this.minimumArrayLength); - buildString(" throw new %s();", MessageTypeException.class.getName()); - buildString("}"); - - int i; - for(i=0; i < this.minimumArrayLength; i++) { - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - buildString("$1.unpackObject();"); - continue; - } - - buildString("if($1.tryUnpackNull()) {"); - if(e.isRequired()) { - // Required + nil => exception - buildString("throw new %s();", MessageTypeException.class.getName()); - } else if(e.isOptional()) { - // Optional + nil => keep default value - } else { // Nullable - // Nullable + nil => set null - buildString("_$$_t.%s = null;", e.getName()); - } - buildString("} else {"); - Class type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - for(; i < entries.length; i++) { - buildString("if(length <= %d) { return _$$_t; }", i); - - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - buildString("$1.unpackObject();"); - continue; - } - - buildString("if($1.tryUnpackNull()) {"); - // this is Optional field becaue i >= minimumArrayLength - // Optional + nil => keep default value - buildString("} else {"); - Class type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - // latter entries are all Optional + nil => keep default value - - buildString("for(int i=%d; i < length; i++) {", i); - buildString(" $1.unpackObject();"); - buildString("}"); - - buildString("return _$$_t;"); - - buildString("}"); - return getBuiltString(); - } - - protected String buildConvertMethodBody() { - resetStringBuilder(); - buildString("{ "); - - buildString("%s _$$_t;", this.origName); - buildString("if($2 == null) {"); - buildString(" _$$_t = new %s();", this.origName); - buildString("} else {"); - buildString(" _$$_t = (%s)$2;", this.origName); - buildString("}"); - - buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName()); - buildString("int length = array.length;"); - buildString("if(length < %d) {", this.minimumArrayLength); - buildString(" throw new %s();", MessageTypeException.class.getName()); - buildString("}"); - - buildString("%s obj;", MessagePackObject.class.getName()); - - int i; - for(i=0; i < this.minimumArrayLength; i++) { - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - continue; - } - - buildString("obj = array[%d];", i); - buildString("if(obj.isNil()) {"); - if(e.isRequired()) { - // Required + nil => exception - buildString("throw new %s();", MessageTypeException.class.getName()); - } else if(e.isOptional()) { - // Optional + nil => keep default value - } else { // Nullable - // Nullable + nil => set null - buildString("_$$_t.%s = null;", e.getName()); - } - buildString("} else {"); - Class type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - for(; i < entries.length; i++) { - buildString("if(length <= %d) { return _$$_t; }", i); - - FieldEntry e = entries[i]; - if(!e.isAvailable()) { - continue; - } - - buildString("obj = array[%d];", i); - buildString("if(obj.isNil()) {"); - // this is Optional field becaue i >= minimumArrayLength - // Optional + nil => keep default value - buildString("} else {"); - Class type = e.getType(); - if(type.isPrimitive()) { - buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); - } else { - buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); - } - buildString("}"); - } - - // latter entries are all Optional + nil => keep default value - - buildString("return _$$_t;"); - - buildString("}"); - return getBuiltString(); - } - - protected String primitivePackName(Class type) { - if(type == boolean.class) { - return "packBoolean"; - } else if(type == byte.class) { - return "packByte"; - } else if(type == short.class) { - return "packShort"; - } else if(type == int.class) { - return "packInt"; - } else if(type == long.class) { - return "packLong"; - } else if(type == float.class) { - return "packFloat"; - } else if(type == double.class) { - return "packDouble"; - } - return null; - } - - protected String primitiveUnpackName(Class type) { - if(type == boolean.class) { - return "unpackBoolean"; - } else if(type == byte.class) { - return "unpackByte"; - } else if(type == short.class) { - return "unpackShort"; - } else if(type == int.class) { - return "unpackInt"; - } else if(type == long.class) { - return "unpackLong"; - } else if(type == float.class) { - return "unpackFloat"; - } else if(type == double.class) { - return "unpackDouble"; - } - return null; - } - - protected String primitiveConvertName(Class type) { - if(type == boolean.class) { - return "asBoolean"; - } else if(type == byte.class) { - return "asByte"; - } else if(type == short.class) { - return "asShort"; - } else if(type == int.class) { - return "asInt"; - } else if(type == long.class) { - return "asLong"; - } else if(type == float.class) { - return "asFloat"; - } else if(type == double.class) { - return "asDouble"; - } - return null; - } - } - - public Template buildTemplate(Class targetClass, FieldEntry[] entries) { + @Override + public Template buildTemplate(Class targetClass, IFieldEntry[] entries) { // FIXME private / packagefields //for(FieldEntry e : entries) { // Field f = e.getField(); @@ -556,7 +150,7 @@ public class JavassistTemplateBuilder extends TemplateBuilder { Template[] tmpls = new Template[entries.length]; for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; + IFieldEntry e = entries[i]; if(!e.isAvailable()) { tmpls[i] = null; } else { @@ -565,10 +159,21 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } - BuildContext bc = new BuildContext(this); + BuildContextBase bc = getBuildContextFacotry().createBuildContext(this); return bc.buildTemplate(targetClass, entries, tmpls); } + @Override + public IFieldEntryReader getFieldEntryReader() { + return reader; + } + + public BuildContextFactory getBuildContextFacotry() { + return buildContextFactory; + } + + + /* static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate { JavassistOrdinalEnumTemplate(Enum[] entries) { super(entries); @@ -610,6 +215,6 @@ public class JavassistTemplateBuilder extends TemplateBuilder { Class componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass(); return new ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); } - } + }*/ } diff --git a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java index 03ff2067..c85b69f9 100644 --- a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java @@ -22,17 +22,26 @@ import java.lang.reflect.*; import java.util.Map; import java.util.HashMap; import org.msgpack.*; +import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.builder.TemplateBuilder; -public class ReflectionTemplateBuilder extends TemplateBuilder { - private static ReflectionTemplateBuilder instance; +public class ReflectionTemplateBuilder extends CustomTemplateBuilder { + /*private static ReflectionTemplateBuilder instance; public synchronized static ReflectionTemplateBuilder getInstance() { if(instance == null) { instance = new ReflectionTemplateBuilder(); } return instance; + }*/ + + IFieldEntryReader reader = new FieldEntryReader(); + + @Override + public IFieldEntryReader getFieldEntryReader(){ + return reader; } - private ReflectionTemplateBuilder() { + public ReflectionTemplateBuilder() { } static abstract class ReflectionFieldEntry extends FieldEntry { @@ -373,9 +382,10 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } - public Template buildTemplate(Class targetClass, FieldEntry[] entries) { - for(FieldEntry e : entries) { - Field f = e.getField(); + public Template buildTemplate(Class targetClass, IFieldEntry[] entries) { + // TODO Now it is simply cast. + for(IFieldEntry e : entries) { + Field f = ((FieldEntry)e).getField(); int mod = f.getModifiers(); if(!Modifier.isPublic(mod)) { f.setAccessible(true); @@ -384,7 +394,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length]; for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; + FieldEntry e = (FieldEntry)entries[i]; Class type = e.getType(); if(!e.isAvailable()) { res[i] = new NullFieldEntry(e); @@ -411,159 +421,5 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { return new ReflectionTemplate(targetClass, res); } - static class ReflectionOrdinalEnumTemplate extends AbstractTemplate { - protected Enum[] entries; - protected Map, Integer> reverse; - - ReflectionOrdinalEnumTemplate(Enum[] entries) { - this.entries = entries; - this.reverse = new HashMap, Integer>(); - for(int i=0; i < entries.length; i++) { - this.reverse.put(entries[i], i); - } - } - - public void pack(Packer pk, Object target) throws IOException { - Integer ord = reverse.get(target); - if(ord == null) { - throw new MessageTypeException(); - } - pk.pack((int)ord); - } - - public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { - int ord = pac.unpackInt(); - if(entries.length <= ord) { - throw new MessageTypeException(); - } - return entries[ord]; - } - - public Object convert(MessagePackObject from, Object to) throws MessageTypeException { - int ord = from.asInt(); - if(entries.length <= ord) { - throw new MessageTypeException(); - } - return entries[ord]; - } - } - - public Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries) { - return new ReflectionOrdinalEnumTemplate(entries); - } - - - static class ReflectionObjectArrayTemplate extends AbstractTemplate { - private Class componentClass; - private Template elementTemplate; - - public ReflectionObjectArrayTemplate(Class componentClass, Template elementTemplate) { - this.componentClass = componentClass; - this.elementTemplate = elementTemplate; - } - - public void pack(Packer pk, Object target) throws IOException { - if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) { - throw new MessageTypeException(); - } - Object[] array = (Object[])target; - int length = array.length; - pk.packArray(length); - for(int i=0; i < length; i++) { - elementTemplate.pack(pk, array[i]); - } - } - - public Object unpack(Unpacker pac, Object to) throws IOException { - int length = pac.unpackArray(); - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = elementTemplate.unpack(pac, null); - } - return array; - } - - public Object convert(MessagePackObject from, Object to) throws MessageTypeException { - MessagePackObject[] src = from.asArray(); - int length = src.length; - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = elementTemplate.convert(src[i], null); - } - return array; - } - } - - static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate { - private Class componentClass; - private Template componentTemplate; - - public ReflectionMultidimentionalArrayTemplate(Class componentClass, Template componentTemplate) { - this.componentClass = componentClass; - this.componentTemplate = componentTemplate; - } - - Class getComponentClass() { - return componentClass; - } - - public void pack(Packer pk, Object target) throws IOException { - Object[] array = (Object[])target; - int length = array.length; - pk.packArray(length); - for(int i=0; i < length; i++) { - componentTemplate.pack(pk, array[i]); - } - } - - public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { - int length = pac.unpackArray(); - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = componentTemplate.unpack(pac, null); - } - return array; - } - - public Object convert(MessagePackObject from, Object to) throws MessageTypeException { - MessagePackObject[] src = from.asArray(); - int length = src.length; - Object[] array = (Object[])Array.newInstance(componentClass, length); - for(int i=0; i < length; i++) { - array[i] = componentTemplate.convert(src[i], null); - } - return array; - } - } - - public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { - if(dim == 1) { - if(baseClass == boolean.class) { - return BooleanArrayTemplate.getInstance(); - } else if(baseClass == short.class) { - return ShortArrayTemplate.getInstance(); - } else if(baseClass == int.class) { - return IntArrayTemplate.getInstance(); - } else if(baseClass == long.class) { - return LongArrayTemplate.getInstance(); - } else if(baseClass == float.class) { - return FloatArrayTemplate.getInstance(); - } else if(baseClass == double.class) { - return DoubleArrayTemplate.getInstance(); - } else { - Template baseTemplate = TemplateRegistry.lookup(genericBaseType); - return new ReflectionObjectArrayTemplate(baseClass, baseTemplate); - } - } else if(dim == 2) { - Class componentClass = Array.newInstance(baseClass, 0).getClass(); - Template componentTemplate = buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1); - return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); - } else { - ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate) - buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1); - Class componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass(); - return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); - } - } } diff --git a/java/src/main/java/org/msgpack/template/TemplateRegistry.java b/java/src/main/java/org/msgpack/template/TemplateRegistry.java index 3f98fb46..9c447cc2 100644 --- a/java/src/main/java/org/msgpack/template/TemplateRegistry.java +++ b/java/src/main/java/org/msgpack/template/TemplateRegistry.java @@ -26,33 +26,55 @@ import java.lang.annotation.Annotation; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackDelegate; import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.builder.TemplateBuilder; import org.msgpack.Template; import org.msgpack.Templates; public class TemplateRegistry { private static Map map; private static Map genericMap; + + private static BuilderSelectorRegistry builderSelectorRegistry; static { map = new HashMap(); genericMap = new HashMap(); BuiltInTemplateLoader.load(); + builderSelectorRegistry = BuilderSelectorRegistry.getInstance(); } public static void register(Class target) { // auto-detect - if(target.isEnum()) { + TemplateBuilder builder = builderSelectorRegistry.select(target); + if(builder != null){ + register(target,builder.buildTemplate(target)); + }else{ + register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target)); + } + /*if(target.isEnum()) { register(target, TemplateBuilder.buildOrdinalEnum(target)); } else { register(target, TemplateBuilder.build(target)); - } + }*/ } public static void register(Class target, FieldOption implicitOption) { - register(target, TemplateBuilder.build(target, implicitOption)); + TemplateBuilder builder = builderSelectorRegistry.select(target); + if(builder != null && builder instanceof CustomTemplateBuilder){ + register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, implicitOption)); + }else{ + throw new TemplateBuildException("cannot build template with filed option"); + } } public static void register(Class target, FieldList flist) throws NoSuchFieldException { - register(target, TemplateBuilder.build(target, flist)); + TemplateBuilder builder = builderSelectorRegistry.select(target); + if(builder != null && builder instanceof CustomTemplateBuilder){ + register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, flist)); + }else{ + throw new TemplateBuildException("cannot build template with filed list"); + } } public static synchronized void register(Type rawType, Template tmpl) { @@ -102,7 +124,7 @@ public class TemplateRegistry { return tmpl; } - if(targetType instanceof GenericArrayType) { + /*if(targetType instanceof GenericArrayType) { // GenericArrayType is not a Class tmpl = TemplateBuilder.buildArray(targetType); register(targetType, tmpl); @@ -129,7 +151,17 @@ public class TemplateRegistry { tmpl = TemplateBuilder.buildOrdinalEnum(target); register(target, tmpl); return tmpl; + }*/ + // find match TemplateBuilder + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetType); + if(builder != null){ + tmpl = builder.buildTemplate(targetType); + register(targetType,tmpl); + return tmpl; } + + + Class target = (Class)targetType; for(Class i : target.getInterfaces()) { tmpl = map.get(i); @@ -150,7 +182,7 @@ public class TemplateRegistry { } if(forceBuild) { - tmpl = TemplateBuilder.build(target); + tmpl = builderSelectorRegistry.getForceBuilder().buildTemplate(target); register(target, tmpl); return tmpl; } @@ -198,8 +230,5 @@ public class TemplateRegistry { return ao.getAnnotation(with) != null; } - public static void setTemplateBuilder(TemplateBuilder builder) { - TemplateBuilder.setInstance(builder); - } } diff --git a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java new file mode 100644 index 00000000..93a8aba8 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java @@ -0,0 +1,173 @@ +package org.msgpack.template.builder; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import org.msgpack.AbstractTemplate; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.template.BooleanArrayTemplate; +import org.msgpack.template.DoubleArrayTemplate; +import org.msgpack.template.FloatArrayTemplate; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.IntArrayTemplate; +import org.msgpack.template.LongArrayTemplate; +import org.msgpack.template.ShortArrayTemplate; +import org.msgpack.template.TemplateRegistry; + +public class ArrayTemplateBuilder extends TemplateBuilder { + + + + + static class ReflectionObjectArrayTemplate extends AbstractTemplate { + private Class componentClass; + private Template elementTemplate; + + public ReflectionObjectArrayTemplate(Class componentClass, Template elementTemplate) { + this.componentClass = componentClass; + this.elementTemplate = elementTemplate; + } + + public void pack(Packer pk, Object target) throws IOException { + if(!(target instanceof Object[]) || !componentClass.isAssignableFrom(target.getClass().getComponentType())) { + throw new MessageTypeException(); + } + Object[] array = (Object[])target; + int length = array.length; + pk.packArray(length); + for(int i=0; i < length; i++) { + elementTemplate.pack(pk, array[i]); + } + } + + public Object unpack(Unpacker pac, Object to) throws IOException { + int length = pac.unpackArray(); + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = elementTemplate.unpack(pac, null); + } + return array; + } + + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + MessagePackObject[] src = from.asArray(); + int length = src.length; + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = elementTemplate.convert(src[i], null); + } + return array; + } + } + + static class ReflectionMultidimentionalArrayTemplate extends AbstractTemplate { + private Class componentClass; + private Template componentTemplate; + + public ReflectionMultidimentionalArrayTemplate(Class componentClass, Template componentTemplate) { + this.componentClass = componentClass; + this.componentTemplate = componentTemplate; + } + + Class getComponentClass() { + return componentClass; + } + + public void pack(Packer pk, Object target) throws IOException { + Object[] array = (Object[])target; + int length = array.length; + pk.packArray(length); + for(int i=0; i < length; i++) { + componentTemplate.pack(pk, array[i]); + } + } + + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + int length = pac.unpackArray(); + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = componentTemplate.unpack(pac, null); + } + return array; + } + + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + MessagePackObject[] src = from.asArray(); + int length = src.length; + Object[] array = (Object[])Array.newInstance(componentClass, length); + for(int i=0; i < length; i++) { + array[i] = componentTemplate.convert(src[i], null); + } + return array; + } + } + @Override + public Template buildTemplate(Type arrayType) { + Type baseType; + Class baseClass; + int dim = 1; + if(arrayType instanceof GenericArrayType) { + GenericArrayType type = (GenericArrayType)arrayType; + baseType = type.getGenericComponentType(); + while(baseType instanceof GenericArrayType) { + baseType = ((GenericArrayType)baseType).getGenericComponentType(); + dim += 1; + } + if(baseType instanceof ParameterizedType) { + baseClass = (Class)((ParameterizedType)baseType).getRawType(); + } else { + baseClass = (Class)baseType; + } + } else { + Class type = (Class)arrayType; + baseClass = type.getComponentType(); + while(baseClass.isArray()) { + baseClass = baseClass.getComponentType(); + dim += 1; + } + baseType = baseClass; + } + return toTemplate(arrayType, baseType, baseClass, dim); + + } + private Template toTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { + if(dim == 1) { + if(baseClass == boolean.class) { + return BooleanArrayTemplate.getInstance(); + } else if(baseClass == short.class) { + return ShortArrayTemplate.getInstance(); + } else if(baseClass == int.class) { + return IntArrayTemplate.getInstance(); + } else if(baseClass == long.class) { + return LongArrayTemplate.getInstance(); + } else if(baseClass == float.class) { + return FloatArrayTemplate.getInstance(); + } else if(baseClass == double.class) { + return DoubleArrayTemplate.getInstance(); + } else { + Template baseTemplate = TemplateRegistry.lookup(genericBaseType); + return new ReflectionObjectArrayTemplate(baseClass, baseTemplate); + } + } else if(dim == 2) { + Class componentClass = Array.newInstance(baseClass, 0).getClass(); + Template componentTemplate = toTemplate(arrayType, genericBaseType, baseClass, dim-1); + return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); + } else { + ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionMultidimentionalArrayTemplate) + toTemplate(arrayType, genericBaseType, baseClass, dim-1); + Class componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass(); + return new ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); + } + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java new file mode 100644 index 00000000..30417dd0 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java @@ -0,0 +1,35 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.GenericArrayType; +import java.lang.reflect.Type; + +import org.msgpack.Template; + +public class ArrayTemplateBuilderSelector implements BuilderSelector { + + public static final String NAME = "ArrayTemplateBuilder"; + + @Override + public String getName(){ + return NAME; + } + + + @Override + public boolean matchType(Type targetType) { + if(targetType instanceof GenericArrayType){ + return true; + } + Class targetClass = (Class)targetType; + return targetClass.isArray(); + } + + ArrayTemplateBuilder templateBuilder = new ArrayTemplateBuilder(); + + @Override + public TemplateBuilder getTemplateBuilder(Type target) { + return templateBuilder; + } + + +} diff --git a/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java new file mode 100644 index 00000000..d30aa90b --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java @@ -0,0 +1,27 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; + +/** + * Match condition for TemplateBuilder. + * @author takeshita + * + */ +public interface BuilderSelector { + + + /** + * Name of this. + * @return + */ + public String getName(); + + + public abstract boolean matchType(Type targetType); + + + public abstract TemplateBuilder getTemplateBuilder(Type targetType); + + + +} diff --git a/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java b/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java new file mode 100644 index 00000000..329f882b --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java @@ -0,0 +1,213 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; +import java.util.LinkedList; +import java.util.List; + +import org.msgpack.template.BeansFieldEntryReader; +import org.msgpack.template.BeansReflectionTemplateBuilder; +import org.msgpack.template.JavassistTemplateBuilder; +import org.msgpack.template.ReflectionTemplateBuilder; +import org.msgpack.template.javassist.BeansBuildContext; +import org.msgpack.template.javassist.BuildContext; +import org.msgpack.template.javassist.BuildContextBase; +import org.msgpack.template.javassist.BuildContextFactory; + +/** + * Registry for BuilderSelectors. + * You can modify BuilderSelector chain throw this class. + * + * @author takeshita + * + */ +public class BuilderSelectorRegistry { + + private static BuilderSelectorRegistry instance = new BuilderSelectorRegistry(); + static{ + initForJava(); + } + + public static BuilderSelectorRegistry getInstance(){ + return instance; + } + + TemplateBuilder forceBuilder; + + + List builderSelectors = new LinkedList(); + + private BuilderSelectorRegistry(){ + } + /** + * initialize BuilderSelectors for basic java enviroment. + */ + private static void initForJava(){ + + instance.append(new ArrayTemplateBuilderSelector()); + + if(isSupportJavassist()){ + instance.append( + new MessagePackMessageBuilderSelector( + new JavassistTemplateBuilder())); + instance.forceBuilder = new JavassistTemplateBuilder(); + + //Java beans + instance.append(new MessagePackBeansBuilderSelector( + new JavassistTemplateBuilder( + new BeansFieldEntryReader(), + new BuildContextFactory() { + @Override + public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) { + return new BeansBuildContext(builder); + } + } + ))); + }else{ + instance.append( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.forceBuilder = new ReflectionTemplateBuilder(); + + //Java beans + instance.append(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + } + + instance.append(new MessagePackOrdinalEnumBuilderSelector()); + instance.append(new EnumBuilderSelector()); + } + public static boolean isSupportJavassist(){ + try { + return System.getProperty("java.vm.name").equals("Dalvik"); + } catch (Exception e) { + return true; + } + } + + /** + * Check whether same name BuilderSelector is registered. + * @param builderSelectorName + * @return + */ + public boolean contains(String builderSelectorName){ + for(BuilderSelector bs : builderSelectors){ + if(bs.getName().equals(builderSelectorName)){ + return true; + } + } + return false; + } + /** + * Append BuilderSelector to tail + * @param builderSelector + */ + public void append(BuilderSelector builderSelector){ + + if(contains(builderSelector.getName())){ + throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName()); + } + this.builderSelectors.add(builderSelector); + } + /** + * Insert BuiderSelector to head + * @param builderSelector + */ + public void prepend(BuilderSelector builderSelector){ + if(contains(builderSelector.getName())){ + throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName()); + } + if(builderSelectors.size() > 0){ + this.builderSelectors.add(0, builderSelector); + }else{ + this.builderSelectors.add(builderSelector); + } + } + + /** + * Insert BuilderSelector + * @param index + * @param builderSelector + */ + public void insert(int index,BuilderSelector builderSelector){ + if(contains(builderSelector.getName())){ + throw new RuntimeException("Duplicate BuilderSelector name:" + builderSelector.getName()); + } + if(builderSelectors.size() > 0){ + this.builderSelectors.add(index, builderSelector); + + }else{ + this.builderSelectors.add(builderSelector); + } + } + /** + * Replace same name BuilderSelector + * @param builderSelector + */ + public void replace(BuilderSelector builderSelector){ + String name = builderSelector.getName(); + int index = getIndex(name); + builderSelectors.add(index, builderSelector); + builderSelectors.remove(index + 1); + } + + /** + * Insert the BuilderSelector before BuilderSelector named "builderSelectorName". + * @param builderSelectorName + * @param builderSelector + */ + public void insertBefore(String builderSelectorName,BuilderSelector builderSelector){ + int index = getIndex(builderSelectorName); + + builderSelectors.add(index,builderSelector); + } + /** + * Insert the BuilderSelector after BuilderSelector named "builderSelectorName". + * @param builderSelectorName + * @param builderSelector + */ + public void insertAfter(String builderSelectorName,BuilderSelector builderSelector){ + int index = getIndex(builderSelectorName); + if(index + 1 == builderSelectors.size()){ + builderSelectors.add(builderSelector); + }else{ + builderSelectors.add(index + 1 , builderSelector); + } + } + private int getIndex(String builderSelectorName){ + int index = 0; + for(BuilderSelector bs : builderSelectors){ + if(bs.getName().equals(builderSelectorName)){ + break; + } + index++; + } + if(index >= builderSelectors.size()){ + throw new RuntimeException( + String.format("BuilderSelector named %s does not exist",builderSelectorName)); + } + return index; + } + + + public TemplateBuilder select(Type target){ + for(BuilderSelector selector : builderSelectors){ + if(selector.matchType(target)){ + return selector.getTemplateBuilder(target); + } + } + return null; + } + + public TemplateBuilder getForceBuilder() { + return forceBuilder; + } + + + public void setForceBuilder(TemplateBuilder forceBuilder) { + this.forceBuilder = forceBuilder; + } + + + + +} diff --git a/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java new file mode 100644 index 00000000..6f7f45cb --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java @@ -0,0 +1,53 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; + +import org.msgpack.Template; +import org.msgpack.template.FieldList; +import org.msgpack.template.FieldOption; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.TemplateBuildException; +import org.msgpack.template.javassist.BuildContextFactory; + +public abstract class CustomTemplateBuilder extends TemplateBuilder { + + + public abstract IFieldEntryReader getFieldEntryReader(); + + + public abstract Template buildTemplate(Class targetClass , IFieldEntry[] entries); + + public Template buildTemplate(Class targetClass ,FieldOption implicitOption ){ + checkValidation(targetClass); + return buildTemplate(targetClass, + getFieldEntryReader().readFieldEntries(targetClass, implicitOption)); + } + public Template buildTemplate(Class targetClass, FieldList flist) throws NoSuchFieldException { + checkValidation(targetClass); + return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist)); + } + + @Override + public Template buildTemplate(Type targetType) { + Class targetClass = (Class)targetType; + IFieldEntryReader reader = getFieldEntryReader(); + FieldOption implicitOption = reader.readImplicitFieldOption(targetClass); + checkValidation(targetClass); + + IFieldEntry[] entries = reader.readFieldEntries(targetClass, implicitOption); + + return buildTemplate(targetClass,entries); + } + private void checkValidation(Class targetClass) { + if(targetClass.isInterface()) { + throw new TemplateBuildException("cannot build template of interface"); + } + if(targetClass.isArray()) { + throw new TemplateBuildException("cannot build template of array class"); + } + if(targetClass.isPrimitive()) { + throw new TemplateBuildException("cannot build template of primitive type"); + } + } +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java new file mode 100644 index 00000000..b8a2701c --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java @@ -0,0 +1,26 @@ +package org.msgpack.template.builder; + +import java.lang.reflect.Type; + +public class EnumBuilderSelector implements BuilderSelector { + + public static final String NAME = "EnumTemplateBuilder"; + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + return ((Class)targetType).isEnum(); + } + + + OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java new file mode 100644 index 00000000..3b4a5903 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java @@ -0,0 +1,40 @@ +package org.msgpack.template.builder; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import org.msgpack.annotation.MessagePackBeans; +import org.msgpack.annotation.MessagePackMessage; + +public class MessagePackBeansBuilderSelector implements BuilderSelector{ + + public static final String NAME = "MessagePackBeansTemplateBuilder"; + + + TemplateBuilder builder; + public MessagePackBeansBuilderSelector(TemplateBuilder builder){ + this.builder = builder; + } + + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + Class target = (Class)targetType; + return isAnnotated(target, MessagePackBeans.class); + } + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + + + private boolean isAnnotated(Class ao, Class with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java new file mode 100644 index 00000000..008b8f06 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java @@ -0,0 +1,38 @@ +package org.msgpack.template.builder; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import org.msgpack.annotation.MessagePackMessage; + +public class MessagePackMessageBuilderSelector implements BuilderSelector{ + + public static final String NAME = "MessagePackMessageTemplateBuilder"; + + + TemplateBuilder builder; + public MessagePackMessageBuilderSelector(TemplateBuilder builder){ + this.builder = builder; + } + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + Class target = (Class)targetType; + return isAnnotated(target, MessagePackMessage.class); + } + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + + + private boolean isAnnotated(Class ao, Class with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java new file mode 100644 index 00000000..2d32cb47 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java @@ -0,0 +1,34 @@ +package org.msgpack.template.builder; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; + +import org.msgpack.annotation.MessagePackOrdinalEnum; + +public class MessagePackOrdinalEnumBuilderSelector implements BuilderSelector { + + public static final String NAME = "MessagePackOrdinalEnumBuilderTemplate"; + + public String getName(){ + return NAME; + } + + @Override + public boolean matchType(Type targetType) { + Class target = (Class)targetType; + return isAnnotated(target, MessagePackOrdinalEnum.class); + } + + OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); + + @Override + public TemplateBuilder getTemplateBuilder(Type targetType) { + return builder; + } + + + private boolean isAnnotated(Class ao, Class with) { + return ao.getAnnotation(with) != null; + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java new file mode 100644 index 00000000..1d4752fc --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java @@ -0,0 +1,68 @@ +package org.msgpack.template.builder; + +import java.io.IOException; +import java.lang.reflect.Type; +import java.util.HashMap; +import java.util.Map; + +import org.msgpack.AbstractTemplate; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.template.TemplateBuildException; + +public class OrdinalEnumTemplateBuilder extends TemplateBuilder{ + + static class ReflectionOrdinalEnumTemplate extends AbstractTemplate { + protected Enum[] entries; + protected Map, Integer> reverse; + + ReflectionOrdinalEnumTemplate(Enum[] entries) { + this.entries = entries; + this.reverse = new HashMap, Integer>(); + for(int i=0; i < entries.length; i++) { + this.reverse.put(entries[i], i); + } + } + + public void pack(Packer pk, Object target) throws IOException { + Integer ord = reverse.get(target); + if(ord == null) { + throw new MessageTypeException(); + } + pk.pack((int)ord); + } + + public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { + int ord = pac.unpackInt(); + if(entries.length <= ord) { + throw new MessageTypeException(); + } + return entries[ord]; + } + + public Object convert(MessagePackObject from, Object to) throws MessageTypeException { + int ord = from.asInt(); + if(entries.length <= ord) { + throw new MessageTypeException(); + } + return entries[ord]; + } + } + @Override + public Template buildTemplate(Type targetType) { + Class targetClass = (Class)targetType; + checkOrdinalEnumValidation(targetClass); + Enum[] entries = (Enum[])targetClass.getEnumConstants(); + + return new ReflectionOrdinalEnumTemplate(entries); + } + private void checkOrdinalEnumValidation(Class targetClass) { + if(!targetClass.isEnum()) { + throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); + } + } + +} diff --git a/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java new file mode 100644 index 00000000..0dd36ffc --- /dev/null +++ b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java @@ -0,0 +1,327 @@ +// +// 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.builder; + +import java.io.IOException; +import java.lang.reflect.*; +import java.lang.annotation.*; +import java.util.List; +import java.util.ArrayList; +import java.util.EnumSet; +import org.msgpack.*; +import org.msgpack.annotation.*; +import org.msgpack.template.FieldList; +import org.msgpack.template.FieldOption; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.JavassistTemplateBuilder; +import org.msgpack.template.ReflectionTemplateBuilder; + +public abstract class TemplateBuilder { + + public abstract Template buildTemplate(Type targetType); + /* + // Override this method + public abstract Template buildTemplate(Class targetClass, IFieldEntry[] entries); + + // Override this method + public abstract Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries); + + // Override this method + public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim); + + public abstract IFieldEntryReader getFieldEntryReader(); + + public Template buildTemplate(Class targetClass, FieldList flist) throws NoSuchFieldException { + checkValidation(targetClass); + return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist)); + } + + public Template buildTemplate(Class targetClass, FieldOption implicitOption) { + checkValidation(targetClass); + return buildTemplate(targetClass, getFieldEntryReader().readFieldEntries(targetClass, implicitOption)); + } + + public Template buildTemplate(Class targetClass) { + FieldOption implicitOption = getFieldEntryReader().readImplicitFieldOption(targetClass); + return buildTemplate(targetClass, implicitOption); + } + + public Template buildOrdinalEnumTemplate(Class targetClass) { + checkOrdinalEnumValidation(targetClass); + Enum[] entries = (Enum[])targetClass.getEnumConstants(); + return buildOrdinalEnumTemplate(targetClass, entries); + } + + public Template buildArrayTemplate(Type arrayType) { + Type baseType; + Class baseClass; + int dim = 1; + if(arrayType instanceof GenericArrayType) { + GenericArrayType type = (GenericArrayType)arrayType; + baseType = type.getGenericComponentType(); + while(baseType instanceof GenericArrayType) { + baseType = ((GenericArrayType)baseType).getGenericComponentType(); + dim += 1; + } + if(baseType instanceof ParameterizedType) { + baseClass = (Class)((ParameterizedType)baseType).getRawType(); + } else { + baseClass = (Class)baseType; + } + } else { + Class type = (Class)arrayType; + baseClass = type.getComponentType(); + while(baseClass.isArray()) { + baseClass = baseClass.getComponentType(); + dim += 1; + } + baseType = baseClass; + } + return buildArrayTemplate(arrayType, baseType, baseClass, dim); + } + + private static Type getComponentType(Type arrayType) { + if(arrayType instanceof GenericArrayType) { + return ((GenericArrayType)arrayType).getGenericComponentType(); + } else { + return ((Class)arrayType).getComponentType(); + } + } + private void checkValidation(Class targetClass) { + if(targetClass.isInterface()) { + throw new TemplateBuildException("cannot build template of interface"); + } + if(targetClass.isArray()) { + throw new TemplateBuildException("cannot build template of array class"); + } + if(targetClass.isPrimitive()) { + throw new TemplateBuildException("cannot build template of primitive type"); + } + } + private void checkOrdinalEnumValidation(Class targetClass) { + if(!targetClass.isEnum()) { + throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); + } + } + + + private static TemplateBuilder instance; + static { + instance = selectDefaultTemplateBuilder(); + } + + private static TemplateBuilder selectDefaultTemplateBuilder() { + try { + // FIXME JavassistTemplateBuilder doesn't work on DalvikVM + if(System.getProperty("java.vm.name").equals("Dalvik")) { + return ReflectionTemplateBuilder.getInstance(); + } + } catch (Exception e) { + } + return JavassistTemplateBuilder.getInstance(); + } + + public synchronized static void setInstance(TemplateBuilder builder) { + instance = builder; + } + + public static Template build(Class targetClass) { + return instance.buildTemplate(targetClass); + } + + public static Template build(Class targetClass, FieldOption implicitOption) { + return instance.buildTemplate(targetClass, implicitOption); + } + + public static Template build(Class targetClass, FieldList flist) throws NoSuchFieldException { + return instance.buildTemplate(targetClass, flist); + } + + public static Template buildOrdinalEnum(Class targetClass) { + return instance.buildOrdinalEnumTemplate(targetClass); + } + + public static Template buildArray(Type arrayType) { + return instance.buildArrayTemplate(arrayType); + }*/ + + /* + private static void checkValidation(Class targetClass) { + if(targetClass.isInterface()) { + throw new TemplateBuildException("cannot build template of interface"); + } + if(targetClass.isArray()) { + throw new TemplateBuildException("cannot build template of array class"); + } + if(targetClass.isPrimitive()) { + throw new TemplateBuildException("cannot build template of primitive type"); + } + } + + private static void checkOrdinalEnumValidation(Class targetClass) { + if(!targetClass.isEnum()) { + throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); + } + }*/ + + /* + static IFieldEntry[] convertFieldEntries(Class targetClass, FieldList flist) throws NoSuchFieldException { + List src = flist.getList(); + FieldEntry[] result = new FieldEntry[src.size()]; + for(int i=0; i < src.size(); i++) { + FieldList.Entry s = src.get(i); + if(s.isAvailable()) { + result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); + } else { + result[i] = new FieldEntry(); + } + } + return result; + }*/ + + /*static IFieldEntry[] readFieldEntries(Class targetClass, FieldOption implicitOption) { + Field[] allFields = readAllFields(targetClass); + + /* index: + * @Index(0) int field_a; // 0 + * int field_b; // 1 + * @Index(3) int field_c; // 3 + * int field_d; // 4 + * @Index(2) int field_e; // 2 + * int field_f; // 5 + *//* + List indexed = new ArrayList(); + int maxIndex = -1; + for(Field f : allFields) { + FieldOption opt = readFieldOption(f, implicitOption); + if(opt == FieldOption.IGNORE) { + // skip + continue; + } + + int index = readFieldIndex(f, maxIndex); + + if(indexed.size() > index && indexed.get(index) != null) { + throw new TemplateBuildException("duplicated index: "+index); + } + if(index < 0) { + throw new TemplateBuildException("invalid index: "+index); + } + + while(indexed.size() <= index) { + indexed.add(null); + } + indexed.set(index, new FieldEntry(f, opt)); + + if(maxIndex < index) { + maxIndex = index; + } + } + + FieldEntry[] result = new FieldEntry[maxIndex+1]; + for(int i=0; i < indexed.size(); i++) { + FieldEntry e = indexed.get(i); + if(e == null) { + result[i] = new FieldEntry(); + } else { + result[i] = e; + } + } + + return result; + }*/ + /* + private static Field[] readAllFields(Class targetClass) { + // order: [fields of super class, ..., fields of this class] + List succ = new ArrayList(); + int total = 0; + for(Class c = targetClass; c != Object.class; c = c.getSuperclass()) { + Field[] fields = c.getDeclaredFields(); + total += fields.length; + succ.add(fields); + } + Field[] result = new Field[total]; + int off = 0; + for(int i=succ.size()-1; i >= 0; i--) { + Field[] fields = succ.get(i); + System.arraycopy(fields, 0, result, off, fields.length); + off += fields.length; + } + return result; + } + + private static FieldOption readImplicitFieldOption(Class targetClass) { + MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); + if(a == null) { + return FieldOption.DEFAULT; + } + return a.value(); + } + + private static FieldOption readFieldOption(Field field, FieldOption implicitOption) { + int mod = field.getModifiers(); + if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) { + return FieldOption.IGNORE; + } + + if(isAnnotated(field, Ignore.class)) { + return FieldOption.IGNORE; + } else if(isAnnotated(field, Required.class)) { + return FieldOption.REQUIRED; + } else if(isAnnotated(field, Optional.class)) { + return FieldOption.OPTIONAL; + } else if(isAnnotated(field, Nullable.class)) { + if(field.getDeclaringClass().isPrimitive()) { + return FieldOption.REQUIRED; + } else { + return FieldOption.NULLABLE; + } + } + + if(implicitOption != FieldOption.DEFAULT) { + return implicitOption; + } + + // default mode: + // transient : Ignore + // public : Required + // others : Ignore + if(Modifier.isTransient(mod)) { + return FieldOption.IGNORE; + } else if(Modifier.isPublic(mod)) { + return FieldOption.REQUIRED; + } else { + return FieldOption.IGNORE; + } + } + + private static int readFieldIndex(Field field, int maxIndex) { + Index a = field.getAnnotation(Index.class); + if(a == null) { + return maxIndex + 1; + } else { + return a.value(); + } + } + + private static boolean isAnnotated(AccessibleObject ao, Class with) { + return ao.getAnnotation(with) != null; + }*/ +} + diff --git a/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java b/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java new file mode 100644 index 00000000..74d477fd --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java @@ -0,0 +1,273 @@ + +package org.msgpack.template.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class BeansBuildContext extends BuildContextBase { + protected BeansFieldEntry[] entries; + protected Class origClass; + protected String origName; + protected Template[] templates; + protected int minimumArrayLength; + + public BeansBuildContext(JavassistTemplateBuilder director) { + super(director); + } + + public Template buildTemplate(Class targetClass, BeansFieldEntry[] entries, Template[] templates) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + return build(this.origName); + } + + protected void setSuperClass() throws CannotCompileException, NotFoundException { + this.tmplCtClass.setSuperclass( + director.getCtClass(JavassistTemplate.class.getName())); + } + + protected void buildConstructor() throws CannotCompileException, NotFoundException { + // Constructor(Class targetClass, Template[] templates) + CtConstructor newCtCons = CtNewConstructor.make( + new CtClass[] { + director.getCtClass(Class.class.getName()), + director.getCtClass(Template.class.getName()+"[]") + }, + new CtClass[0], + this.tmplCtClass); + this.tmplCtClass.addConstructor(newCtCons); + } + + protected Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + Constructor cons = c.getConstructor(new Class[] { + Class.class, + Template[].class + }); + Object tmpl = cons.newInstance(new Object[] { + this.origClass, + this.templates + }); + return (Template)tmpl; + } + + protected void buildMethodInit() { + this.minimumArrayLength = 0; + for(int i=0; i < entries.length; i++) { + IFieldEntry e = entries[i]; + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + } + } + + protected String buildPackMethodBody() { + resetStringBuilder(); + buildString("{"); + buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); + buildString("$1.packArray(%d);", entries.length); + for(int i=0; i < entries.length; i++) { + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.packNil();"); + continue; + } + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("$1.%s(_$$_t.%s());", primitivePackName(type), e.getGetterName()); + } else { + buildString("if(_$$_t.%s() == null) {", e.getGetterName()); + if(!e.isNullable() && !e.isOptional()) { + buildString("throw new %s();", MessageTypeException.class.getName()); + } else { + buildString("$1.packNil();"); + } + buildString("} else {"); + buildString(" this.templates[%d].pack($1, _$$_t.%s());", i, e.getGetterName()); + buildString("}"); + } + } + buildString("}"); + return getBuiltString(); + } + + protected String buildUnpackMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("int length = $1.unpackArray();"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s(null);", e.getSetterName()); + } + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.set%s( $1.%s() );", e.getName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.set%s( (%s)this.templates[%d].unpack($1, _$$_t.get%s()) );", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s( $1.%s() );", e.getSetterName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.%s( (%s)this.templates[%d].unpack($1, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("for(int i=%d; i < length; i++) {", i); + buildString(" $1.unpackObject();"); + buildString("}"); + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + + protected String buildConvertMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName()); + buildString("int length = array.length;"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + buildString("%s obj;", MessagePackObject.class.getName()); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s( null );", e.getSetterName()); + } + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + BeansFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s( obj.%s() );", e.getSetterName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getSetterName(), e.getJavaTypeName(), i, e.getGetterName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContext.java b/java/src/main/java/org/msgpack/template/javassist/BuildContext.java new file mode 100644 index 00000000..ff1c2fc2 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BuildContext.java @@ -0,0 +1,273 @@ + +package org.msgpack.template.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + + +public class BuildContext extends BuildContextBase { + protected IFieldEntry[] entries; + protected Class origClass; + protected String origName; + protected Template[] templates; + protected int minimumArrayLength; + + public BuildContext(JavassistTemplateBuilder director) { + super(director); + } + + public Template buildTemplate(Class targetClass, FieldEntry[] entries, Template[] templates) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + return build(this.origName); + } + + protected void setSuperClass() throws CannotCompileException, NotFoundException { + this.tmplCtClass.setSuperclass( + director.getCtClass(JavassistTemplate.class.getName())); + } + + protected void buildConstructor() throws CannotCompileException, NotFoundException { + // Constructor(Class targetClass, Template[] templates) + CtConstructor newCtCons = CtNewConstructor.make( + new CtClass[] { + director.getCtClass(Class.class.getName()), + director.getCtClass(Template.class.getName()+"[]") + }, + new CtClass[0], + this.tmplCtClass); + this.tmplCtClass.addConstructor(newCtCons); + } + + protected Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { + Constructor cons = c.getConstructor(new Class[] { + Class.class, + Template[].class + }); + Object tmpl = cons.newInstance(new Object[] { + this.origClass, + this.templates + }); + return (Template)tmpl; + } + + protected void buildMethodInit() { + this.minimumArrayLength = 0; + for(int i=0; i < entries.length; i++) { + IFieldEntry e = entries[i]; + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + } + } + + protected String buildPackMethodBody() { + resetStringBuilder(); + buildString("{"); + buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); + buildString("$1.packArray(%d);", entries.length); + for(int i=0; i < entries.length; i++) { + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.packNil();"); + continue; + } + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("$1.%s(_$$_t.%s);", primitivePackName(type), e.getName()); + } else { + buildString("if(_$$_t.%s == null) {", e.getName()); + if(!e.isNullable() && !e.isOptional()) { + buildString("throw new %s();", MessageTypeException.class.getName()); + } else { + buildString("$1.packNil();"); + } + buildString("} else {"); + buildString(" this.templates[%d].pack($1, _$$_t.%s);", i, e.getName()); + buildString("}"); + } + } + buildString("}"); + return getBuiltString(); + } + + protected String buildUnpackMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("int length = $1.unpackArray();"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s = null;", e.getName()); + } + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + continue; + } + + buildString("if($1.tryUnpackNull()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = $1.%s();", e.getName(), primitiveUnpackName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].unpack($1, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("for(int i=%d; i < length; i++) {", i); + buildString(" $1.unpackObject();"); + buildString("}"); + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + + protected String buildConvertMethodBody() { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("%s[] array = $1.asArray();", MessagePackObject.class.getName()); + buildString("int length = array.length;"); + buildString("if(length < %d) {", this.minimumArrayLength); + buildString(" throw new %s();", MessageTypeException.class.getName()); + buildString("}"); + + buildString("%s obj;", MessagePackObject.class.getName()); + + int i; + for(i=0; i < this.minimumArrayLength; i++) { + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", MessageTypeException.class.getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s = null;", e.getName()); + } + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + for(; i < entries.length; i++) { + buildString("if(length <= %d) { return _$$_t; }", i); + + IFieldEntry e = entries[i]; + if(!e.isAvailable()) { + continue; + } + + buildString("obj = array[%d];", i); + buildString("if(obj.isNil()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + Class type = e.getType(); + if(type.isPrimitive()) { + buildString("_$$_t.%s = obj.%s();", e.getName(), primitiveConvertName(type)); + } else { + buildString("_$$_t.%s = (%s)this.templates[%d].convert(obj, _$$_t.%s);", e.getName(), e.getJavaTypeName(), i, e.getName()); + } + buildString("}"); + } + + // latter entries are all Optional + nil => keep default value + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java b/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java new file mode 100644 index 00000000..635dc47c --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java @@ -0,0 +1,244 @@ +// +// 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.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public abstract class BuildContextBase { + + private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class); + + + protected JavassistTemplateBuilder director; + + protected String tmplName; + + protected CtClass tmplCtClass; + + protected abstract void setSuperClass() throws CannotCompileException, NotFoundException; + + protected abstract void buildConstructor() throws CannotCompileException, NotFoundException; + + protected void buildMethodInit() { } + + protected abstract String buildPackMethodBody(); + + protected abstract String buildUnpackMethodBody(); + + protected abstract String buildConvertMethodBody(); + + protected abstract Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException; + + public BuildContextBase(JavassistTemplateBuilder director) { + this.director = director; + } + + + public abstract Template buildTemplate(Class targetClass, T[] entries, Template[] templates); + + + protected Template build(final String className) { + try { + reset(className); + buildClass(); + buildConstructor(); + buildMethodInit(); + buildPackMethod(); + buildUnpackMethod(); + buildConvertMethod(); + return buildInstance(createClass()); + } catch (Exception e) { + String code = getBuiltString(); + if(code != null) { + LOG.error("builder: " + code, e); + throw new TemplateBuildException("cannot compile: " + code, e); + } else { + throw new TemplateBuildException(e); + } + } + } + + protected void reset(String className) { + tmplName = className + "_$$_Template" + director.nextSeqId(); + tmplCtClass = director.makeCtClass(tmplName); + } + + protected void buildClass() throws CannotCompileException, NotFoundException { + setSuperClass(); + tmplCtClass.addInterface(director.getCtClass(Template.class.getName())); + } + + protected void buildPackMethod() throws CannotCompileException, NotFoundException { + String mbody = buildPackMethodBody(); + int mod = javassist.Modifier.PUBLIC; + CtClass returnType = CtClass.voidType; + String mname = "pack"; + CtClass[] paramTypes = new CtClass[] { + director.getCtClass(Packer.class.getName()), + director.getCtClass(Object.class.getName()) + }; + CtClass[] exceptTypes = new CtClass[] { + director.getCtClass(IOException.class.getName()) + }; + CtMethod newCtMethod = CtNewMethod.make( + mod, returnType, mname, + paramTypes, exceptTypes, mbody, tmplCtClass); + tmplCtClass.addMethod(newCtMethod); + } + + protected void buildUnpackMethod() throws CannotCompileException, NotFoundException { + String mbody = buildUnpackMethodBody(); + int mod = javassist.Modifier.PUBLIC; + CtClass returnType = director.getCtClass(Object.class.getName()); + String mname = "unpack"; + CtClass[] paramTypes = new CtClass[] { + director.getCtClass(Unpacker.class.getName()), + director.getCtClass(Object.class.getName()) + }; + CtClass[] exceptTypes = new CtClass[] { + director.getCtClass(MessageTypeException.class.getName()) + }; + CtMethod newCtMethod = CtNewMethod.make( + mod, returnType, mname, + paramTypes, exceptTypes, mbody, tmplCtClass); + tmplCtClass.addMethod(newCtMethod); + } + + protected void buildConvertMethod() throws CannotCompileException, NotFoundException { + String mbody = buildConvertMethodBody(); + int mod = javassist.Modifier.PUBLIC; + CtClass returnType = director.getCtClass(Object.class.getName()); + String mname = "convert"; + CtClass[] paramTypes = new CtClass[] { + director.getCtClass(MessagePackObject.class.getName()), + director.getCtClass(Object.class.getName()) + }; + CtClass[] exceptTypes = new CtClass[] { + director.getCtClass(MessageTypeException.class.getName()) + }; + CtMethod newCtMethod = CtNewMethod.make( + mod, returnType, mname, + paramTypes, exceptTypes, mbody, tmplCtClass); + tmplCtClass.addMethod(newCtMethod); + } + + protected Class createClass() throws CannotCompileException { + return (Class) tmplCtClass.toClass(null, null); + } + + protected StringBuilder stringBuilder = null; + + protected void resetStringBuilder() { + stringBuilder = new StringBuilder(); + } + + protected void buildString(String str) { + stringBuilder.append(str); + } + + protected void buildString(String format, Object... args) { + stringBuilder.append(String.format(format, args)); + } + + protected String getBuiltString() { + if(stringBuilder == null) { + return null; + } + return stringBuilder.toString(); + } + + protected String primitivePackName(Class type) { + if(type == boolean.class) { + return "packBoolean"; + } else if(type == byte.class) { + return "packByte"; + } else if(type == short.class) { + return "packShort"; + } else if(type == int.class) { + return "packInt"; + } else if(type == long.class) { + return "packLong"; + } else if(type == float.class) { + return "packFloat"; + } else if(type == double.class) { + return "packDouble"; + } + return null; + } + + protected String primitiveUnpackName(Class type) { + if(type == boolean.class) { + return "unpackBoolean"; + } else if(type == byte.class) { + return "unpackByte"; + } else if(type == short.class) { + return "unpackShort"; + } else if(type == int.class) { + return "unpackInt"; + } else if(type == long.class) { + return "unpackLong"; + } else if(type == float.class) { + return "unpackFloat"; + } else if(type == double.class) { + return "unpackDouble"; + } + return null; + } + + protected String primitiveConvertName(Class type) { + if(type == boolean.class) { + return "asBoolean"; + } else if(type == byte.class) { + return "asByte"; + } else if(type == short.class) { + return "asShort"; + } else if(type == int.class) { + return "asInt"; + } else if(type == long.class) { + return "asLong"; + } else if(type == float.class) { + return "asFloat"; + } else if(type == double.class) { + return "asDouble"; + } + return null; + } +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java b/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java new file mode 100644 index 00000000..d44ed090 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java @@ -0,0 +1,9 @@ +package org.msgpack.template.javassist; + +import org.msgpack.template.JavassistTemplateBuilder; + +public interface BuildContextFactory { + + public BuildContextBase createBuildContext(JavassistTemplateBuilder builder); + +} diff --git a/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java b/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java new file mode 100644 index 00000000..24e7082d --- /dev/null +++ b/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java @@ -0,0 +1,36 @@ + +package org.msgpack.template.javassist; + +import java.io.IOException; +import java.lang.reflect.Array; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; +import java.lang.Thread; + +import org.msgpack.*; +import org.msgpack.template.*; + +import javassist.CannotCompileException; +import javassist.ClassPool; +import javassist.CtClass; +import javassist.CtConstructor; +import javassist.CtMethod; +import javassist.CtNewConstructor; +import javassist.CtNewMethod; +import javassist.LoaderClassPath; +import javassist.NotFoundException; +import javassist.ClassClassPath; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class JavassistTemplate extends AbstractTemplate { + public Class targetClass; + public Template[] templates; + + public JavassistTemplate(Class targetClass, Template[] templates) { + this.targetClass = targetClass; + this.templates = templates; + } +} \ No newline at end of file diff --git a/java/src/test/java/org/msgpack/TestArrays.java b/java/src/test/java/org/msgpack/TestArrays.java index 92bb44c2..40fa5d69 100644 --- a/java/src/test/java/org/msgpack/TestArrays.java +++ b/java/src/test/java/org/msgpack/TestArrays.java @@ -13,6 +13,10 @@ import org.junit.Test; import junit.framework.TestCase; public class TestArrays extends TestCase { + + + + @MessagePackMessage public static class PrimitiveTest { public PrimitiveTest() { } diff --git a/java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java b/java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java new file mode 100644 index 00000000..78880582 --- /dev/null +++ b/java/src/test/java/org/msgpack/template/BeansEntryReaderTest.java @@ -0,0 +1,133 @@ +package org.msgpack.template; + +import java.beans.BeanDescriptor; +import java.beans.BeanInfo; +import java.beans.IntrospectionException; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.msgpack.template.BeansFieldEntryReader; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.*; + +/** + * + * @author takeshita + * + */ +public class BeansEntryReaderTest { + + public static class VariableProps{ + + public int getCollect(){ + return 0; + } + public void setCollect(int v){} + + public int getOnlyGetter(){ + return 0; + } + + public void setOnlySetter(int v){} + + public boolean isBoolean(){ + return true; + } + public void setBoolean(boolean b){} + + + private int getPrivateBoth(){return 1;} + private void setPrivateBoth(int v){} + + private int getPrivateGetter(){return 1;} + public void setPrivateGetter(int v){} + + public int getPrivateSetter(){return 1;} + private void setPrivateSetter(int v){} + + protected int getProtected(){return 1;} + protected void setProtected(int v){} + + int getInternal(){return 1;} + void setInternal(int v){} + + public int getWrongGetter(int v){return 1;} + public void setWrongGetter(int v){} + + public void getWrongGetter2(){} + public void setWrongGetter2(int v){} + + public int isWrongGetter3(){return 1;} + public void setWrongGetter3(int v){} + + public int getWrongSetter(){return 1;} + public int setWrongSetter(int v){return 1;} + + public int getWrongSetter2(){return 1;} + public void setWrongSetter2(){} + } + + @Before + public void before(){ + reader = new BeansFieldEntryReader(); + + try { + info = Introspector.getBeanInfo(VariableProps.class); + } catch (IntrospectionException e) { + e.printStackTrace(); + Assert.fail(); + } + } + BeansFieldEntryReader reader; + BeanInfo info; + @Test + public void testIgnorePropertyDesc(){ + BeanDescriptor desc = info.getBeanDescriptor(); + + assertThat(reader.isIgnoreProp(getProp(info,"collect")),is(false)); + assertThat(reader.isIgnoreProp(getProp(info,"boolean")),is(false)); + + + assertThat(reader.isIgnoreProp(getProp(info,"onlyGetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"onlySetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"privateBoth")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"privateGetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"privateSetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"protected")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"internal")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter2")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongGetter3")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongSetter")),is(true)); + assertThat(reader.isIgnoreProp(getProp(info,"wrongSetter2")),is(true)); + + } + @Test + public void testReadEntries(){ + + IFieldEntry[] entries = reader.readFieldEntries(VariableProps.class, FieldOption.DEFAULT); + + assertThat(entries.length, is(2)); + + + } + + + public PropertyDescriptor getProp(BeanInfo info , String name){ + PropertyDescriptor[] props = info.getPropertyDescriptors(); + for(int i = 0;i < props.length;i++){ + PropertyDescriptor d = props[i]; + if(d.getDisplayName().equalsIgnoreCase(name)){ + return d; + } + } + return null; + } + + + +} diff --git a/java/src/test/java/org/msgpack/template/BeansEquals.java b/java/src/test/java/org/msgpack/template/BeansEquals.java new file mode 100644 index 00000000..e07a224d --- /dev/null +++ b/java/src/test/java/org/msgpack/template/BeansEquals.java @@ -0,0 +1,83 @@ +package org.msgpack.template; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.HashSet; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.CoreMatchers; +import org.hamcrest.Description; +import org.junit.Assert; + +/** + * This matcher compares all get***() methods(except getClass) + * @author takeshita + * + */ +public class BeansEquals extends BaseMatcher{ + + Object expected; + + HashSet ignoreNames = new HashSet(); + + public BeansEquals(Object expected){ + this.expected = expected; + } + public BeansEquals(Object expected,String[] ignoreNames){ + this.expected = expected; + for(int i = 0;i < ignoreNames.length;i++){ + this.ignoreNames.add(ignoreNames[i]); + } + } + + static String errorMessage = "hoge"; + + @Override + public boolean matches(Object actual) { + if(expected == actual){ + return true; + } + if(!actual.getClass().equals(expected.getClass())){ + errorMessage = String.format("Expected class is %s but actual %s", + expected.getClass().getName(), + actual.getClass().getName()); + return false; + } + + for(Method m : expected.getClass().getMethods()){ + String n = m.getName(); + if(n.startsWith("get") && + !n.equals("getClass") && + !ignoreNames.contains(n)){ + + if(m.getParameterTypes().length == 0 && + !m.getReturnType().equals(void.class)){ + try { + Object exp = m.invoke(expected); + Object act = m.invoke(actual); + + Assert.assertThat("@" + n,act, CoreMatchers.is(exp)); + + } catch (Exception e) { + throw new RuntimeException(String.format( + "Exception occured while comparing %s",n), e); + } + + } + + } + + } + + return true; + } + + + @Override + public void describeTo(Description desc) { + + desc.appendText(errorMessage); + } + + +} diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java new file mode 100644 index 00000000..951b401c --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java @@ -0,0 +1,2207 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.hamcrest.CoreMatchers; +import org.hamcrest.Matcher; +import org.junit.Ignore; +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackBeans; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.MessagePackBeansBuilderSelector; +import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.TemplateBuilder; + +import org.junit.Assert; +import junit.framework.TestCase; +import static org.hamcrest.CoreMatchers.*; +import static org.junit.Assert.assertThat; + +public class TestReflectionTemplateBuilderJavaBeansPackUnpack extends TestCase { + static { + //Replace template selectors from javassist to reflection. + BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); + + instance.replace( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.setForceBuilder( new ReflectionTemplateBuilder()); + instance.replace(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + Matcher beansEquals(Object actual){ + return new BeansEquals(actual); + } + Matcher beansEquals(Object actual,String[] ignoreNames){ + return new BeansEquals(actual,ignoreNames); + } + String[] ignoring(String ... strings){ + return strings; + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + + assertThat(dst,beansEquals(src)); + } + + @MessagePackBeans + public static class PrimitiveTypeFieldsClass { + byte f0; + short f1; + int f2; + long f3; + float f4; + double f5; + boolean f6; + + public byte getF0() { + return f0; + } + + public void setF0(byte f0) { + this.f0 = f0; + } + + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + @Optional + public byte getF0() { + return f0; + } + + @Optional + public void setF0(byte f0) { + this.f0 = f0; + } + + @Optional + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + @Optional + public void setF2(int f2) { + this.f2 = f2; + } + + @Optional + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + @Optional + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + @Optional + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + @Optional + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public Byte getF0() { + return f0; + } + + public void setF0(Byte f0) { + this.f0 = f0; + } + + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + public void setF2(Integer f2) { + this.f2 = f2; + } + + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + + + assertThat(dst,beansEquals(src)); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + @Optional + public Byte getF0() { + return f0; + } + + @Optional + public void setF0(Byte f0) { + this.f0 = f0; + } + + @Optional + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + @Optional + public void setF2(Integer f2) { + this.f2 = f2; + } + + @Optional + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + @Optional + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + @Optional + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + @Optional + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + @Optional + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + @Optional + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + @Optional + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + @Optional + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.integerListSize0 = new ArrayList(); + src.integerList = new ArrayList(); + src.integerList.add(1); + src.integerList.add(2); + src.integerList.add(3); + src.stringList = new ArrayList(); + src.stringList.add("e1"); + src.stringList.add("e2"); + src.stringList.add("e3"); + src.stringListList = new ArrayList>(); + src.stringListList.add(src.stringList); + src.sampleListNestedTypeList = new ArrayList(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.sampleListNestedTypeList.add(slnt); + src.byteBufferList = new ArrayList(); + src.byteBufferList.add(ByteBuffer.wrap("e1".getBytes())); + src.byteBufferList.add(ByteBuffer.wrap("e2".getBytes())); + src.byteBufferList.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + + //ignore sampleListNestedTypeList, + //because SampleListNestedType is not implemented equals() correctly. + assertThat(dst,beansEquals(src, ignoring("getF4"))); + + assertEquals(src.sampleListNestedTypeList.size(), dst.sampleListNestedTypeList.size()); + for (int i = 0; i < src.sampleListNestedTypeList.size(); ++i) { + SampleListNestedType s = src.sampleListNestedTypeList.get(i); + SampleListNestedType d = dst.sampleListNestedTypeList.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleListTypes { + public List integerListSize0; + public List integerList; + public List stringList; + public List> stringListList; + public List sampleListNestedTypeList; + public List byteBufferList; + + public List getF0() { + return integerListSize0; + } + + public void setF0(List f0) { + this.integerListSize0 = f0; + } + + public List getF1() { + return integerList; + } + + public void setF1(List f1) { + this.integerList = f1; + } + + public List getF2() { + return stringList; + } + + public void setF2(List f2) { + this.stringList = f2; + } + + public List> getF3() { + return stringListList; + } + + public void setF3(List> f3) { + this.stringListList = f3; + } + + public List getF4() { + return sampleListNestedTypeList; + } + + public void setF4(List f4) { + this.sampleListNestedTypeList = f4; + } + + public List getF5() { + return byteBufferList; + } + + public void setF5(List f5) { + this.byteBufferList = f5; + } + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList>(); + src.f3.add(src.f2); + src.f4 = new ArrayList(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.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)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List srclist = src.f3.get(i); + List dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = null; + src.f2 = new ArrayList(); + src.f3 = new ArrayList>(); + src.f4 = null; + src.f5 = new ArrayList(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalListTypes { + @Optional + public List f0; + @Optional + public List f1; + @Optional + public List f2; + @Optional + public List> f3; + @Optional + public List f4; + @Optional + public List f5; + + @Optional + public List getF0() { + return f0; + } + + @Optional + public void setF0(List f0) { + this.f0 = f0; + } + + @Optional + public List getF1() { + return f1; + } + + public void setF1(List f1) { + this.f1 = f1; + } + + public List getF2() { + return f2; + } + + @Optional + public void setF2(List f2) { + this.f2 = f2; + } + + @Optional + public List> getF3() { + return f3; + } + + public void setF3(List> f3) { + this.f3 = f3; + } + + @Optional + public List getF4() { + return f4; + } + + public void setF4(List f4) { + this.f4 = f4; + } + + @Optional + public List getF5() { + return f5; + } + + public void setF5(List f5) { + this.f5 = f5; + } + + public SampleOptionalListTypes() { + } + } + + @MessagePackBeans + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + @Optional + public byte[] getF0() { + return f0; + } + + public void setF0(byte[] f0) { + this.f0 = f0; + } + + @Optional + public String getF1() { + return f1; + } + + public void setF1(String f1) { + this.f1 = f1; + } + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleMapTypes { + public Map f0; + public Map f1; + public Map f2; + + public Map getF0() { + return f0; + } + + public void setF0(Map f0) { + this.f0 = f0; + } + + public Map getF1() { + return f1; + } + + public void setF1(Map f1) { + this.f1 = f1; + } + + public Map getF2() { + return f2; + } + + public void setF2(Map f2) { + this.f2 = f2; + } + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = null; + src.f2 = new HashMap(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalMapTypes { + @Optional + public Map f0; + @Optional + public Map f1; + @Optional + public Map f2; + + @Optional + public Map getF0() { + return f0; + } + + public void setF0(Map f0) { + this.f0 = f0; + } + + @Optional + public Map getF1() { + return f1; + } + + public void setF1(Map f1) { + this.f1 = f1; + } + + @Optional + public Map getF2() { + return f2; + } + + public void setF2(Map f2) { + this.f2 = f2; + } + + public SampleOptionalMapTypes() { + } + } + + + @MessagePackBeans + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 23; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst,is(src)); + } + + @MessagePackBeans + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleEnum getF1() { + return f1; + } + + public void setF1(SampleEnum f1) { + this.f1 = f1; + } + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public SampleOptionalEnum getF1() { + return f1; + } + + public void setF1(SampleOptionalEnum f1) { + this.f1 = f1; + } + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw, FieldModifiersClass.class); + Assert.assertEquals(src.f1,dst.f1); + Assert.assertThat(dst.f2, is( not(src.f2))); + Assert.assertThat(dst.f3, is( not(src.f3))); + Assert.assertThat(dst.f4, is( not(src.f4))); + } + + @MessagePackBeans + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + private void setF2(int f2) { + this.f2 = f2; + } + + public int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw, OptionalFieldModifiersClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + Assert.assertThat(dst.f2, is(not(src.f2))); + Assert.assertThat(dst.f3, is(not(src.f3))); + Assert.assertThat(dst.f4, is(not(src.f4))); + } + + @MessagePackBeans + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + protected int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass { + public int f0; + public NestedClass f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public NestedClass getF1() { + return f1; + } + + public void setF1(NestedClass f1) { + this.f1 = f1; + } + + public BaseClass() { + } + } + + @MessagePackBeans + public static class NestedClass { + public int f2; + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalNestedClass getF1() { + return f1; + } + + public void setF1(OptionalNestedClass f1) { + this.f1 = f1; + } + + public OptionalBaseClass() { + } + } + + @MessagePackBeans + public static class OptionalNestedClass { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public MessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(MessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public BaseClass2() { + } + } + + @MessagePackBeans + public static class MessagePackMessageClass2 { + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalMessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(OptionalMessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public OptionalBaseClass2() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public SampleSubClass() { + } + } + + @MessagePackBeans + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.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); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleOptionalSubClass() { + } + } + + @MessagePackBeans + public static class SampleOptionalSuperClass { + @Optional + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List f2; + + public MessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(MessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public List getF2() { + return f2; + } + + public void setF2(List f2) { + this.f2 = f2; + } + + public BaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List f2; + + @Optional + public OptionalMessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(OptionalMessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public List getF2() { + return f2; + } + + public void setF2(List f2) { + this.f2 = f2; + } + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java new file mode 100644 index 00000000..dcb039f7 --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java @@ -0,0 +1,1417 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.MessagePackBeansBuilderSelector; +import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.TemplateBuilder; + +import junit.framework.Assert; +import junit.framework.TestCase; + +public class TestReflectionTemplateBuilderPackConvert extends TestCase { + static { + //Replace template selectors from javassist to reflection. + BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); + + instance.replace( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.setForceBuilder( new ReflectionTemplateBuilder()); + instance.replace(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(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); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(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); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(PrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class PrimitiveTypeFieldsClass { + public byte f0; + public short f1; + public int f2; + public long f3; + public float f4; + public double f5; + public boolean f6; + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(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); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(OptionalPrimitiveTypeFieldsClass.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); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw).convert(OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(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]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralOptionalReferenceTypeFieldsClass.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]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralOptionalReferenceTypeFieldsClass.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, dst.f9); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw).convert(GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList>(); + src.f3.add(src.f2); + src.f4 = new ArrayList(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw).convert(SampleListTypes.class); + 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)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List srclist = src.f3.get(i); + List dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleListNestedType s = src.f4.get(i); + SampleListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw).convert(SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleListTypes { + public List f0; + public List f1; + public List f2; + public List> f3; + public List f4; + public List f5; + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList>(); + src.f3.add(src.f2); + src.f4 = new ArrayList(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalListTypes.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)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List srclist = src.f3.get(i); + List dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = null; + src.f2 = new ArrayList(); + src.f3 = new ArrayList>(); + src.f4 = null; + src.f5 = new ArrayList(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw).convert(SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalListTypes { + @Optional + public List f0; + @Optional + public List f1; + @Optional + public List f2; + @Optional + public List> f3; + @Optional + public List f4; + @Optional + public List f5; + + public SampleOptionalListTypes() { + } + } + + @MessagePackMessage + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw).convert(SampleMapTypes.class); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw).convert(SampleMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleMapTypes { + public Map f0; + public Map f1; + public Map f2; + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = null; + src.f2 = new HashMap(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalMapTypes { + @Optional + public Map f0; + @Optional + public Map f1; + @Optional + public Map f2; + + public SampleOptionalMapTypes() { + } + } + + @Test + public void testFinalClass() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); + assertTrue(true); + } catch (TemplateBuildException e) { + fail(); + } + assertTrue(true); + } + + public final static class FinalModifierClass { + } + + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleEnumFieldClass.class); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw).convert(SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw).convert(FieldModifiersClass.class); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + } + + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw).convert(OptionalFieldModifiersClass.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); + } + + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw).convert(BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw).convert(BaseClass.class); + assertEquals(src, dst); + } + + public static class BaseClass { + public int f0; + public NestedClass f1; + + public BaseClass() { + } + } + + public static class NestedClass { + public int f2; + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw).convert(OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw).convert(OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw).convert(OptionalBaseClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + public OptionalBaseClass() { + } + } + + public static class OptionalNestedClass { + @Optional + public int f2; + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw).convert(BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw).convert(BaseClass2.class); + assertEquals(src, dst); + } + + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public BaseClass2() { + } + } + + @MessagePackMessage + public static class MessagePackMessageClass2 { + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw).convert(OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw).convert(OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw).convert(OptionalBaseClass2.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + public OptionalBaseClass2() { + } + } + + @MessagePackMessage + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw).convert(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); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw).convert(SampleSubClass.class); + assertEquals(src, dst); + } + + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleSubClass() { + } + } + + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw).convert(SampleOptionalSubClass.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); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw).convert(SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleOptionalSubClass() { + } + } + + public static class SampleOptionalSuperClass { + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List f2; + + public BaseMessagePackableUnpackableClass() { + } + } + + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw).convert(OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List f2; + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java new file mode 100644 index 00000000..6080df6e --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java @@ -0,0 +1,1422 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.MessagePackBeansBuilderSelector; +import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.TemplateBuilder; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import static org.junit.Assert.assertThat; + +public class TestReflectionTemplateBuilderPackUnpack extends TestCase { + static { + //Replace template selectors from javassist to reflection. + BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); + + instance.replace( + new MessagePackMessageBuilderSelector( + new ReflectionTemplateBuilder())); + instance.setForceBuilder( new ReflectionTemplateBuilder()); + instance.replace(new MessagePackBeansBuilderSelector( + new BeansReflectionTemplateBuilder())); + + + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class PrimitiveTypeFieldsClass { + public byte f0; + public short f1; + public int f2; + public long f3; + public float f4; + public double f5; + public boolean f6; + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.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); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, 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]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.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]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.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, dst.f9); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList>(); + src.f3.add(src.f2); + src.f4 = new ArrayList(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + 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)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List srclist = src.f3.get(i); + List dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleListNestedType s = src.f4.get(i); + SampleListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleListTypes { + public List f0; + public List f1; + public List f2; + public List> f3; + public List f4; + public List f5; + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList>(); + src.f3.add(src.f2); + src.f4 = new ArrayList(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.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)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List srclist = src.f3.get(i); + List dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = null; + src.f2 = new ArrayList(); + src.f3 = new ArrayList>(); + src.f4 = null; + src.f5 = new ArrayList(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalListTypes { + @Optional + public List f0; + @Optional + public List f1; + @Optional + public List f2; + @Optional + public List> f3; + @Optional + public List f4; + @Optional + public List f5; + + public SampleOptionalListTypes() { + } + } + + @MessagePackMessage + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleMapTypes { + public Map f0; + public Map f1; + public Map f2; + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = null; + src.f2 = new HashMap(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + public static class SampleOptionalMapTypes { + @Optional + public Map f0; + @Optional + public Map f1; + @Optional + public Map f2; + + public SampleOptionalMapTypes() { + } + } + + @Test + public void testFinalClass() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); + assertTrue(true); + } catch (TemplateBuildException e) { + fail(); + } + assertTrue(true); + } + + public final static class FinalModifierClass { + } + + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw, FieldModifiersClass.class); + assertTrue(src.f1 == dst.f1); + assertTrue(src.f2 != dst.f2); + assertTrue(src.f3 != dst.f3); + assertTrue(src.f4 != dst.f4); + } + + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw, OptionalFieldModifiersClass.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); + } + + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertEquals(src, dst); + } + + public static class BaseClass { + public int f0; + public NestedClass f1; + + public BaseClass() { + } + } + + public static class NestedClass { + public int f2; + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + public OptionalBaseClass() { + } + } + + public static class OptionalNestedClass { + @Optional + public int f2; + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertEquals(src, dst); + } + + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public BaseClass2() { + } + } + + @MessagePackMessage + public static class MessagePackMessageClass2 { + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertEquals(src, dst); + } + + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + public OptionalBaseClass2() { + } + } + + @MessagePackMessage + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertEquals(src, dst); + } + + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleSubClass() { + } + } + + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.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); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public SampleOptionalSubClass() { + } + } + + public static class SampleOptionalSuperClass { + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List f2; + + public BaseMessagePackableUnpackableClass() { + } + } + + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List f2; + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java new file mode 100644 index 00000000..1310cddb --- /dev/null +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java @@ -0,0 +1,2234 @@ +package org.msgpack.template; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.hamcrest.CoreMatchers; +import org.junit.Ignore; +import org.junit.Test; + +import org.msgpack.MessagePack; +import org.msgpack.MessagePackable; +import org.msgpack.MessagePacker; +import org.msgpack.MessageTypeException; +import org.msgpack.MessageUnpackable; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; +import org.msgpack.annotation.MessagePackBeans; +import org.msgpack.annotation.MessagePackMessage; +import org.msgpack.annotation.MessagePackOrdinalEnum; +import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.TemplateBuilder; + +import org.junit.Assert; +import junit.framework.TestCase; +import static org.hamcrest.CoreMatchers.*; + +public class TestTemplateBuilderJavaBeansPackUnpack extends TestCase { + static { + MessagePack.register(PrimitiveTypeFieldsClass.class); + MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); + MessagePack.register(GeneralReferenceTypeFieldsClass.class); + MessagePack.register(GeneralOptionalReferenceTypeFieldsClass.class); + MessagePack.register(SampleListTypes.class); + MessagePack.register(SampleOptionalListTypes.class); + MessagePack.register(SampleMapTypes.class); + MessagePack.register(SampleOptionalMapTypes.class); + MessagePack.register(SampleEnumFieldClass.class); + MessagePack.register(SampleOptionalEnumFieldClass.class); + MessagePack.register(FieldModifiersClass.class); + MessagePack.register(OptionalFieldModifiersClass.class); + MessagePack.register(BaseClass.class); + MessagePack.register(NestedClass.class); + MessagePack.register(BaseClass2.class); + MessagePack.register(OptionalBaseClass.class); + MessagePack.register(OptionalNestedClass.class); + MessagePack.register(OptionalBaseClass2.class); + MessagePack.register(SampleSubClass.class); + MessagePack.register(SampleSuperClass.class); + MessagePack.register(SampleOptionalSubClass.class); + MessagePack.register(SampleOptionalSuperClass.class); + MessagePack.register(BaseMessagePackableUnpackableClass.class); + MessagePack.register(MessagePackableUnpackableClass.class); + MessagePack.register(OptionalBaseMessagePackableUnpackableClass.class); + MessagePack.register(OptionalMessagePackableUnpackableClass.class); + } + + @Test + public void testPrimitiveTypeFields00() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + PrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class PrimitiveTypeFieldsClass { + byte f0; + short f1; + int f2; + long f3; + float f4; + double f5; + boolean f6; + + public byte getF0() { + return f0; + } + + public void setF0(byte f0) { + this.f0 = f0; + } + + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public PrimitiveTypeFieldsClass() { + } + } + + @Test + public void testOptionalPrimitiveTypeFields00() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + byte[] raw = MessagePack.pack(src); + + PrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testOptionalPrimitiveTypeFields01() throws Exception { + OptionalPrimitiveTypeFieldsClass src = new OptionalPrimitiveTypeFieldsClass(); + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.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); + } + + @Test + public void testOptionalPrimitiveTypeFields02() throws Exception { + OptionalPrimitiveTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalPrimitiveTypeFieldsClass dst = + MessagePack.unpack(raw, OptionalPrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalPrimitiveTypeFieldsClass { + @Optional + public byte f0; + @Optional + public short f1; + @Optional + public int f2; + @Optional + public long f3; + @Optional + public float f4; + @Optional + public double f5; + @Optional + public boolean f6; + + @Optional + public byte getF0() { + return f0; + } + + @Optional + public void setF0(byte f0) { + this.f0 = f0; + } + + @Optional + public short getF1() { + return f1; + } + + public void setF1(short f1) { + this.f1 = f1; + } + + public int getF2() { + return f2; + } + + @Optional + public void setF2(int f2) { + this.f2 = f2; + } + + @Optional + public long getF3() { + return f3; + } + + public void setF3(long f3) { + this.f3 = f3; + } + + @Optional + public float getF4() { + return f4; + } + + public void setF4(float f4) { + this.f4 = f4; + } + + @Optional + public double getF5() { + return f5; + } + + public void setF5(double f5) { + this.f5 = f5; + } + + @Optional + public boolean isF6() { + return f6; + } + + public void setF6(boolean f6) { + this.f6 = f6; + } + + public OptionalPrimitiveTypeFieldsClass() { + } + } + + @Test + public void testGeneralReferenceTypeFieldsClass00() throws Exception { + GeneralReferenceTypeFieldsClass src = new GeneralReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, 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]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralReferenceTypeFieldsClass01() throws Exception { + GeneralReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralReferenceTypeFieldsClass { + public Byte f0; + public Short f1; + public Integer f2; + public Long f3; + public Float f4; + public Double f5; + public Boolean f6; + public BigInteger f7; + public String f8; + public byte[] f9; + public ByteBuffer f10; + + public Byte getF0() { + return f0; + } + + public void setF0(Byte f0) { + this.f0 = f0; + } + + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + public void setF2(Integer f2) { + this.f2 = f2; + } + + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralReferenceTypeFieldsClass() { + } + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass00() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + 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 }; + src.f10 = ByteBuffer.wrap("muga".getBytes()); + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.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]); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass01() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = new GeneralOptionalReferenceTypeFieldsClass(); + src.f0 = null; + src.f1 = null; + src.f2 = null; + src.f3 = null; + src.f4 = null; + src.f5 = null; + src.f6 = null; + src.f7 = null; + src.f8 = null; + src.f9 = null; + src.f10 = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.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, dst.f9); + assertEquals(src.f10, dst.f10); + } + + @Test + public void testGeneralOptionalReferenceTypeFieldsClass02() + throws Exception { + GeneralOptionalReferenceTypeFieldsClass src = null; + + byte[] raw = MessagePack.pack(src); + + GeneralOptionalReferenceTypeFieldsClass dst = + MessagePack.unpack(raw, GeneralOptionalReferenceTypeFieldsClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class GeneralOptionalReferenceTypeFieldsClass { + @Optional + public Byte f0; + @Optional + public Short f1; + @Optional + public Integer f2; + @Optional + public Long f3; + @Optional + public Float f4; + @Optional + public Double f5; + @Optional + public Boolean f6; + @Optional + public BigInteger f7; + @Optional + public String f8; + @Optional + public byte[] f9; + @Optional + public ByteBuffer f10; + + @Optional + public Byte getF0() { + return f0; + } + + @Optional + public void setF0(Byte f0) { + this.f0 = f0; + } + + @Optional + public Short getF1() { + return f1; + } + + public void setF1(Short f1) { + this.f1 = f1; + } + + public Integer getF2() { + return f2; + } + + @Optional + public void setF2(Integer f2) { + this.f2 = f2; + } + + @Optional + public Long getF3() { + return f3; + } + + public void setF3(Long f3) { + this.f3 = f3; + } + + @Optional + public Float getF4() { + return f4; + } + + public void setF4(Float f4) { + this.f4 = f4; + } + + @Optional + public Double getF5() { + return f5; + } + + public void setF5(Double f5) { + this.f5 = f5; + } + + @Optional + public Boolean getF6() { + return f6; + } + + public void setF6(Boolean f6) { + this.f6 = f6; + } + + @Optional + public BigInteger getF7() { + return f7; + } + + public void setF7(BigInteger f7) { + this.f7 = f7; + } + + @Optional + public String getF8() { + return f8; + } + + public void setF8(String f8) { + this.f8 = f8; + } + + @Optional + public byte[] getF9() { + return f9; + } + + public void setF9(byte[] f9) { + this.f9 = f9; + } + + @Optional + public ByteBuffer getF10() { + return f10; + } + + public void setF10(ByteBuffer f10) { + this.f10 = f10; + } + + public GeneralOptionalReferenceTypeFieldsClass() { + } + } + + @Test + public void testListTypes00() throws Exception { + SampleListTypes src = new SampleListTypes(); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList>(); + src.f3.add(src.f2); + src.f4 = new ArrayList(); + SampleListNestedType slnt = new SampleListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + 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)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List srclist = src.f3.get(i); + List dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleListNestedType s = src.f4.get(i); + SampleListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testListTypes01() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleListTypes { + public List f0; + public List f1; + public List f2; + public List> f3; + public List f4; + public List f5; + + public List getF0() { + return f0; + } + + public void setF0(List f0) { + this.f0 = f0; + } + + public List getF1() { + return f1; + } + + public void setF1(List f1) { + this.f1 = f1; + } + + public List getF2() { + return f2; + } + + public void setF2(List f2) { + this.f2 = f2; + } + + public List> getF3() { + return f3; + } + + public void setF3(List> f3) { + this.f3 = f3; + } + + public List getF4() { + return f4; + } + + public void setF4(List f4) { + this.f4 = f4; + } + + public List getF5() { + return f5; + } + + public void setF5(List f5) { + this.f5 = f5; + } + + public SampleListTypes() { + } + } + + @MessagePackMessage + public static class SampleListNestedType { + public byte[] f0; + public String f1; + + public SampleListNestedType() { + } + } + + @Test + public void testOptionalListTypes00() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = new ArrayList(); + src.f1.add(1); + src.f1.add(2); + src.f1.add(3); + src.f2 = new ArrayList(); + src.f2.add("e1"); + src.f2.add("e2"); + src.f2.add("e3"); + src.f3 = new ArrayList>(); + src.f3.add(src.f2); + src.f4 = new ArrayList(); + SampleOptionalListNestedType slnt = new SampleOptionalListNestedType(); + slnt.f0 = new byte[] { 0x01, 0x02 }; + slnt.f1 = "muga"; + src.f4.add(slnt); + src.f5 = new ArrayList(); + src.f5.add(ByteBuffer.wrap("e1".getBytes())); + src.f5.add(ByteBuffer.wrap("e2".getBytes())); + src.f5.add(ByteBuffer.wrap("e3".getBytes())); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.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)); + } + assertEquals(src.f3.size(), dst.f3.size()); + for (int i = 0; i < src.f3.size(); ++i) { + List srclist = src.f3.get(i); + List dstlist = dst.f3.get(i); + assertEquals(srclist.size(), dstlist.size()); + for (int j = 0; j < srclist.size(); ++j) { + assertEquals(srclist.get(j), dstlist.get(j)); + } + } + assertEquals(src.f4.size(), dst.f4.size()); + for (int i = 0; i < src.f4.size(); ++i) { + SampleOptionalListNestedType s = src.f4.get(i); + SampleOptionalListNestedType d = dst.f4.get(i); + assertEquals(s.f0[0], d.f0[0]); + assertEquals(s.f0[1], d.f0[1]); + assertEquals(s.f1, d.f1); + } + assertEquals(src.f5.size(), dst.f5.size()); + for (int i = 0; i < src.f5.size(); ++i) { + ByteBuffer s = src.f5.get(i); + ByteBuffer d = dst.f5.get(i); + assertEquals(s, d); + } + } + + @Test + public void testOptionalListTypes01() throws Exception { + SampleOptionalListTypes src = new SampleOptionalListTypes(); + src.f0 = new ArrayList(); + src.f1 = null; + src.f2 = new ArrayList(); + src.f3 = new ArrayList>(); + src.f4 = null; + src.f5 = new ArrayList(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalListTypes dst = + MessagePack.unpack(raw, SampleOptionalListTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f3.size(), dst.f3.size()); + assertEquals(src.f4, dst.f4); + assertEquals(src.f5.size(), dst.f5.size()); + } + + @Test + public void testOptionalListTypes02() throws Exception { + SampleListTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleListTypes dst = + MessagePack.unpack(raw, SampleListTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalListTypes { + @Optional + public List f0; + @Optional + public List f1; + @Optional + public List f2; + @Optional + public List> f3; + @Optional + public List f4; + @Optional + public List f5; + + @Optional + public List getF0() { + return f0; + } + + @Optional + public void setF0(List f0) { + this.f0 = f0; + } + + @Optional + public List getF1() { + return f1; + } + + public void setF1(List f1) { + this.f1 = f1; + } + + public List getF2() { + return f2; + } + + @Optional + public void setF2(List f2) { + this.f2 = f2; + } + + @Optional + public List> getF3() { + return f3; + } + + public void setF3(List> f3) { + this.f3 = f3; + } + + @Optional + public List getF4() { + return f4; + } + + public void setF4(List f4) { + this.f4 = f4; + } + + @Optional + public List getF5() { + return f5; + } + + public void setF5(List f5) { + this.f5 = f5; + } + + public SampleOptionalListTypes() { + } + } + + @MessagePackBeans + public static class SampleOptionalListNestedType { + @Optional + public byte[] f0; + @Optional + public String f1; + + @Optional + public byte[] getF0() { + return f0; + } + + public void setF0(byte[] f0) { + this.f0 = f0; + } + + @Optional + public String getF1() { + return f1; + } + + public void setF1(String f1) { + this.f1 = f1; + } + + public SampleOptionalListNestedType() { + } + } + + @Test + public void testMapTypes00() throws Exception { + SampleMapTypes src = new SampleMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testMapTypes01() throws Exception { + SampleMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleMapTypes dst = + MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleMapTypes { + public Map f0; + public Map f1; + public Map f2; + + public Map getF0() { + return f0; + } + + public void setF0(Map f0) { + this.f0 = f0; + } + + public Map getF1() { + return f1; + } + + public void setF1(Map f1) { + this.f1 = f1; + } + + public Map getF2() { + return f2; + } + + public void setF2(Map f2) { + this.f2 = f2; + } + + public SampleMapTypes() { + } + } + + @Test + public void testOptionalMapTypes00() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = new HashMap(); + src.f1.put(1, 1); + src.f1.put(2, 2); + src.f1.put(3, 3); + src.f2 = new HashMap(); + src.f2.put("k1", 1); + src.f2.put("k2", 2); + src.f2.put("k3", 3); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); + Iterator srcf1 = src.f1.keySet().iterator(); + Iterator 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 srcf2 = src.f2.keySet().iterator(); + Iterator 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)); + } + } + + @Test + public void testOptionalMapTypes01() throws Exception { + SampleOptionalMapTypes src = new SampleOptionalMapTypes(); + src.f0 = new HashMap(); + src.f1 = null; + src.f2 = new HashMap(); + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + } + + @Test + public void testOptionalMapTypes02() throws Exception { + SampleOptionalMapTypes src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalMapTypes dst = + MessagePack.unpack(raw, SampleOptionalMapTypes.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalMapTypes { + @Optional + public Map f0; + @Optional + public Map f1; + @Optional + public Map f2; + + @Optional + public Map getF0() { + return f0; + } + + public void setF0(Map f0) { + this.f0 = f0; + } + + @Optional + public Map getF1() { + return f1; + } + + public void setF1(Map f1) { + this.f1 = f1; + } + + @Optional + public Map getF2() { + return f2; + } + + public void setF2(Map f2) { + this.f2 = f2; + } + + public SampleOptionalMapTypes() { + } + } + + + @MessagePackBeans + public abstract static class AbstractModifierClass { + } + + @Test + public void testInterfaceType00() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + @Test + public void testInterfaceType01() throws Exception { + try { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); + fail(); + } catch (TemplateBuildException e) { + assertTrue(true); + } + assertTrue(true); + } + + public interface SampleInterface { + } + + @Test + public void testEnumTypeForOrdinal00() throws Exception { + SampleEnumFieldClass src = new SampleEnumFieldClass(); + src.f0 = 23; + src.f1 = SampleEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + } + + @Test + public void testEnumTypeForOrdinal01() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + Assert.assertThat(dst,is(src)); + } + + @MessagePackBeans + public static class SampleEnumFieldClass { + public int f0; + + public SampleEnum f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleEnum getF1() { + return f1; + } + + public void setF1(SampleEnum f1) { + this.f1 = f1; + } + + public SampleEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleEnum { + ONE, TWO, THREE; + } + + @Test + public void testOptionalEnumTypeForOrdinal00() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f0 = 0; + src.f1 = SampleOptionalEnum.ONE; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal01() throws Exception { + SampleOptionalEnumFieldClass src = new SampleOptionalEnumFieldClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalEnumFieldClass dst = + MessagePack.unpack(raw, SampleOptionalEnumFieldClass.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalEnumTypeForOrdinal02() throws Exception { + SampleEnumFieldClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleEnumFieldClass dst = + MessagePack.unpack(raw, SampleEnumFieldClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalEnumFieldClass { + @Optional + public int f0; + + @Optional + public SampleOptionalEnum f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public SampleOptionalEnum getF1() { + return f1; + } + + public void setF1(SampleOptionalEnum f1) { + this.f1 = f1; + } + + public SampleOptionalEnumFieldClass() { + } + } + + @MessagePackOrdinalEnum + public enum SampleOptionalEnum { + ONE, TWO, THREE; + } + + @Test + public void testFieldModifiers() throws Exception { + FieldModifiersClass src = new FieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + FieldModifiersClass dst = + MessagePack.unpack(raw, FieldModifiersClass.class); + Assert.assertEquals(src.f1,dst.f1); + Assert.assertThat(dst.f2, is( not(src.f2))); + Assert.assertThat(dst.f3, is( not(src.f3))); + Assert.assertThat(dst.f4, is( not(src.f4))); + } + + @MessagePackBeans + public static class FieldModifiersClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + private void setF2(int f2) { + this.f2 = f2; + } + + public int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public FieldModifiersClass() { + } + } + + @Test + public void testOptionalFieldModifiers() throws Exception { + OptionalFieldModifiersClass src = new OptionalFieldModifiersClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + + byte[] raw = MessagePack.pack(src); + + OptionalFieldModifiersClass dst = + MessagePack.unpack(raw, OptionalFieldModifiersClass.class); + Assert.assertThat(dst.f0, is(src.f0)); + Assert.assertThat(dst.f1, is(src.f1)); + Assert.assertThat(dst.f2, is(not(src.f2))); + Assert.assertThat(dst.f3, is(not(src.f3))); + Assert.assertThat(dst.f4, is(not(src.f4))); + } + + @MessagePackBeans + public static class OptionalFieldModifiersClass { + @Optional + public int f0; + @Optional + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + private int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + protected int getF3() { + return f3; + } + + protected void setF3(int f3) { + this.f3 = f3; + } + + public int getF4() { + return f4; + } + + void setF4(int f4) { + this.f4 = f4; + } + + public int getF1() { + return f1; + } + + public OptionalFieldModifiersClass() { + } + } + + @Test + public void testNestedFieldClass00() throws Exception { + BaseClass src = new BaseClass(); + NestedClass src2 = new NestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testNestedFieldClass01() throws Exception { + BaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass dst = + MessagePack.unpack(raw, BaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass { + public int f0; + public NestedClass f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public NestedClass getF1() { + return f1; + } + + public void setF1(NestedClass f1) { + this.f1 = f1; + } + + public BaseClass() { + } + } + + @MessagePackBeans + public static class NestedClass { + public int f2; + + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public NestedClass() { + } + } + + @Test + public void testOptionalNestedFieldClass00() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + OptionalNestedClass src2 = new OptionalNestedClass(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalNestedFieldClass01() throws Exception { + OptionalBaseClass src = new OptionalBaseClass(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1 == dst.f1); + } + + @Test + public void testOptionalNestedFieldClass02() throws Exception { + OptionalBaseClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass dst = + MessagePack.unpack(raw, OptionalBaseClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass { + @Optional + public int f0; + @Optional + public OptionalNestedClass f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalNestedClass getF1() { + return f1; + } + + public void setF1(OptionalNestedClass f1) { + this.f1 = f1; + } + + public OptionalBaseClass() { + } + } + + @MessagePackBeans + public static class OptionalNestedClass { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalNestedClass() { + } + } + + @Test + public void testMessagePackMessageFieldClass00() throws Exception { + BaseClass2 src = new BaseClass2(); + MessagePackMessageClass2 src2 = new MessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testMessagePackMessageFieldClass01() throws Exception { + BaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + BaseClass2 dst = + MessagePack.unpack(raw, BaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseClass2 { + public int f0; + public MessagePackMessageClass2 f1; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public MessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(MessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public BaseClass2() { + } + } + + @MessagePackBeans + public static class MessagePackMessageClass2 { + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public int f2; + + public MessagePackMessageClass2() { + } + } + + @Test + public void testOptionalMessagePackMessageFieldClass00() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + OptionalMessagePackMessageClass2 src2 = new OptionalMessagePackMessageClass2(); + src.f0 = 0; + src2.f2 = 2; + src.f1 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertTrue(src.f1.f2 == dst.f1.f2); + } + + @Test + public void testOptionalMessagePackMessageFieldClass01() throws Exception { + OptionalBaseClass2 src = new OptionalBaseClass2(); + src.f1 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertTrue(src.f0 == dst.f0); + assertEquals(src.f1, dst.f1); + } + + @Test + public void testOptionalMessagePackMessageFieldClass02() throws Exception { + OptionalBaseClass2 src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseClass2 dst = + MessagePack.unpack(raw, OptionalBaseClass2.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseClass2 { + @Optional + public int f0; + @Optional + public OptionalMessagePackMessageClass2 f1; + + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public OptionalMessagePackMessageClass2 getF1() { + return f1; + } + + public void setF1(OptionalMessagePackMessageClass2 f1) { + this.f1 = f1; + } + + public OptionalBaseClass2() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackMessageClass2 { + @Optional + public int f2; + + @Optional + public int getF2() { + return f2; + } + + public void setF2(int f2) { + this.f2 = f2; + } + + public OptionalMessagePackMessageClass2() { + } + } + + @Test + public void testExtendedClass00() throws Exception { + SampleSubClass src = new SampleSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, 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); + } + + @Test + public void testExtendedClass01() throws Exception { + SampleSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleSubClass dst = + MessagePack.unpack(raw, SampleSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleSubClass extends SampleSuperClass { + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public SampleSubClass() { + } + } + + @MessagePackBeans + public static class SampleSuperClass { + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + public SampleSuperClass() { + } + } + + @Test + public void testOptionalExtendedClass00() throws Exception { + SampleOptionalSubClass src = new SampleOptionalSubClass(); + src.f0 = 0; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f8 = 8; + src.f9 = 9; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.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); + } + + @Test + public void testOptionalExtendedClass01() throws Exception { + SampleOptionalSubClass src = null; + + byte[] raw = MessagePack.pack(src); + + SampleOptionalSubClass dst = + MessagePack.unpack(raw, SampleOptionalSubClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class SampleOptionalSubClass extends SampleOptionalSuperClass { + @Optional + public int f0; + public final int f1 = 1; + private int f2; + protected int f3; + int f4; + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public SampleOptionalSubClass() { + } + } + + @MessagePackBeans + public static class SampleOptionalSuperClass { + @Optional + public int getF5() { + return f5; + } + + public void setF5(int f5) { + this.f5 = f5; + } + + @Optional + public int f5; + public final int f6 = 2; + @SuppressWarnings("unused") + private int f7; + protected int f8; + int f9; + + public SampleOptionalSuperClass() { + } + } + + @Test + public void testMessagePackableUnpackableClass00() throws Exception { + BaseMessagePackableUnpackableClass src = new BaseMessagePackableUnpackableClass(); + MessagePackableUnpackableClass src1 = new MessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testMessagePackableUnpackableClass01() throws Exception { + BaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + BaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, BaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class BaseMessagePackableUnpackableClass { + public MessagePackableUnpackableClass f0; + public int f1; + public List f2; + + public MessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(MessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public List getF2() { + return f2; + } + + public void setF2(List f2) { + this.f2 = f2; + } + + public BaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class MessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + public int f0; + public int f1; + + public MessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } + + @Test + public void testOptionalMessagePackableUnpackableClass00() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + OptionalMessagePackableUnpackableClass src1 = new OptionalMessagePackableUnpackableClass(); + List src2 = new ArrayList(); + src1.f0 = 0; + src1.f1 = 1; + src.f0 = src1; + src.f1 = 1; + src2.add(src1); + src.f2 = src2; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0.f0, dst.f0.f0); + assertEquals(src.f0.f1, dst.f0.f1); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2.size(), dst.f2.size()); + assertEquals(src.f2.get(0).f0, dst.f2.get(0).f0); + assertEquals(src.f2.get(0).f1, dst.f2.get(0).f1); + } + + @Test + public void testOptionalMessagePackableUnpackableClass01() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = new OptionalBaseMessagePackableUnpackableClass(); + src.f0 = null; + src.f1 = 1; + src.f2 = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src.f0, dst.f0); + assertEquals(src.f1, dst.f1); + assertEquals(src.f2, dst.f2); + } + + @Test + public void testOptionalMessagePackableUnpackableClass02() throws Exception { + OptionalBaseMessagePackableUnpackableClass src = null; + + byte[] raw = MessagePack.pack(src); + + OptionalBaseMessagePackableUnpackableClass dst = + MessagePack.unpack(raw, OptionalBaseMessagePackableUnpackableClass.class); + assertEquals(src, dst); + } + + @MessagePackBeans + public static class OptionalBaseMessagePackableUnpackableClass { + @Optional + public OptionalMessagePackableUnpackableClass f0; + @Optional + public int f1; + @Optional + public List f2; + + @Optional + public OptionalMessagePackableUnpackableClass getF0() { + return f0; + } + + public void setF0(OptionalMessagePackableUnpackableClass f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public List getF2() { + return f2; + } + + public void setF2(List f2) { + this.f2 = f2; + } + + public OptionalBaseMessagePackableUnpackableClass() { + } + } + + @MessagePackBeans + public static class OptionalMessagePackableUnpackableClass implements + MessagePackable, MessageUnpackable { + @Optional + public int getF0() { + return f0; + } + + public void setF0(int f0) { + this.f0 = f0; + } + + @Optional + public int getF1() { + return f1; + } + + public void setF1(int f1) { + this.f1 = f1; + } + + @Optional + public int f0; + @Optional + public int f1; + + public OptionalMessagePackableUnpackableClass() { + } + + @Override + public void messagePack(Packer packer) throws IOException { + packer.packArray(2); + packer.pack(f0); + packer.pack(f1); + } + + @Override + public void messageUnpack(Unpacker unpacker) throws IOException, + MessageTypeException { + if (unpacker.tryUnpackNull()) { + return; + } + unpacker.unpackArray(); + f0 = unpacker.unpackInt(); + f1 = unpacker.unpackInt(); + } + } +} + diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java index a99fa260..f316e64a 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java @@ -24,7 +24,10 @@ import org.msgpack.Unpacker; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.TemplateBuilder; +import junit.framework.Assert; import junit.framework.TestCase; public class TestTemplateBuilderPackConvert extends TestCase { @@ -714,7 +717,9 @@ public class TestTemplateBuilderPackConvert extends TestCase { @Test public void testFinalClass() throws Exception { try { - TemplateBuilder.build(FinalModifierClass.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); assertTrue(true); } catch (TemplateBuildException e) { fail(); @@ -731,7 +736,9 @@ public class TestTemplateBuilderPackConvert extends TestCase { @Test public void testInterfaceType00() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); @@ -742,7 +749,9 @@ public class TestTemplateBuilderPackConvert extends TestCase { @Test public void testInterfaceType01() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder);// no available builder + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java index a2430a43..9ac94ef7 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java @@ -24,7 +24,11 @@ import org.msgpack.Unpacker; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; +import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.TemplateBuilder; +import junit.framework.Assert; import junit.framework.TestCase; public class TestTemplateBuilderPackUnpack extends TestCase { @@ -714,7 +718,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase { @Test public void testFinalClass() throws Exception { try { - TemplateBuilder.build(FinalModifierClass.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class); assertTrue(true); } catch (TemplateBuildException e) { fail(); @@ -731,7 +737,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase { @Test public void testInterfaceType00() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); @@ -742,7 +750,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase { @Test public void testInterfaceType01() throws Exception { try { - TemplateBuilder.build(SampleInterface.class); + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class); + Assert.assertNull(builder); + BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class); fail(); } catch (TemplateBuildException e) { assertTrue(true); diff --git a/scala/.gitignore b/scala/.gitignore new file mode 100644 index 00000000..97250138 --- /dev/null +++ b/scala/.gitignore @@ -0,0 +1,40 @@ +# use glob syntax. +syntax: glob +*.ser +*.class +*~ +*.bak +#*.off +*.old + +# eclipse conf file +.settings +.classpath +.project +.manager +.scala_dependencies + +# idea +.idea +*.iml + +# building +target +build +null +tmp* +dist +test-output +build.log + +# other scm +.svn +.CVS +.hg* + +# switch to regexp syntax. +# syntax: regexp +# ^\.pc/ + +#SHITTY output not in target directory +build.log diff --git a/scala/pom.xml b/scala/pom.xml new file mode 100644 index 00000000..b6a14f2c --- /dev/null +++ b/scala/pom.xml @@ -0,0 +1,158 @@ + + 4.0.0 + org.msgpack + scala-msgpack + 0.0.1-SNAPSHOT + ${project.artifactId} + My wonderfull scala app + 2010 + + + My License + http://.... + repo + + + + + 1.5 + 1.5 + UTF-8 + 2.8.1 + + + + msgpack.org + MessagePack Repository for Maven + http://msgpack.org/maven2/ + + + + + + + org.scala-lang + scala-library + ${scala.version} + + + + + junit + junit + 4.8.1 + test + + + org.scala-tools.testing + specs_${scala.version} + 1.6.6 + test + + + org.msgpack + msgpack + 0.5.2-SNAPSHOT + + + + + + false + msgpack.org + Repository at msgpack.org + + ${deploy-release-url} + + + true + msgpack.org + Repository at msgpack.org + + ${deploy-snapshot-url} + + + + + src/main/scala + src/test/scala + + + org.scala-tools + maven-scala-plugin + 2.15.0 + + + + compile + testCompile + + + + -make:transitive + -dependencyfile + ${project.build.directory}/.scala_dependencies + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.6 + + false + true + + + + **/*Test.* + **/*Suite.* + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + maven-assembly-plugin + + + + jar-with-dependencies + + + + + + + make-assembly + package + + single + + + + + + + + diff --git a/scala/src/main/scala/org/msgpack/App.scala b/scala/src/main/scala/org/msgpack/App.scala new file mode 100644 index 00000000..f80d7a0d --- /dev/null +++ b/scala/src/main/scala/org/msgpack/App.scala @@ -0,0 +1,15 @@ +package org.msgpack + +/** + * @author ${user.name} + */ +object App { + + def foo(x : Array[String]) = x.foldLeft("")((a,b) => a + b) + + def main(args : Array[String]) { + println( "Hello World!" ) + println("concat arguments = " + foo(args)) + } + +} diff --git a/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala new file mode 100644 index 00000000..879bddea --- /dev/null +++ b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala @@ -0,0 +1,521 @@ +package org.msgpack + +import _root_.javassist.{CtClass, CtNewConstructor} +import annotation._ +import template._ +import java.lang.Class +import collection.immutable.{ListMap, TreeMap} +import java.lang.reflect.{Type, Modifier, Method, Field} +import java.lang.annotation.{Annotation => JavaAnnotation} +import javassist.{JavassistTemplate, BuildContextBase, BuildContext} +import scala.collection.JavaConverters._ +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 12:29 + */ + + + class BuildContextForScala(builder : JavassistTemplateBuilder) extends BuildContextBase[IFieldEntry](builder){ + + var entries : Array[IFieldEntry] = null + var origClass : Class[_] = null + var origName : String = null + var templates : Array[Template] = null + var minimumArrayLength : Int = 0 + + def buildTemplate(targetClass : Class[_] , entries : Array[IFieldEntry], templates : Array[Template]) = { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + build(this.origName); + } + + def setSuperClass() = { + tmplCtClass.setSuperclass(director.getCtClass(classOf[JavassistTemplate].getName)) + } + + def buildConstructor() = { + val newCtCons = CtNewConstructor.make( + Array[CtClass]( + director.getCtClass(classOf[Class[_]].getName), + director.getCtClass(classOf[Template].getName + "[]") + ), + new Array[CtClass](0), + tmplCtClass + ) + this.tmplCtClass.addConstructor(newCtCons) + } + def buildInstance(c : Class[_]) = { + val cons = c.getConstructor(classOf[Class[_]], classOf[Array[Template]]) + val tmpl = cons.newInstance(origClass,templates) + tmpl.asInstanceOf[Template] + } + override def buildMethodInit() = { + this.minimumArrayLength = 0; + var i : Int = 0 + for(e <- entries) { + if(e.isRequired() || e.isNullable()) { + this.minimumArrayLength = i+1; + } + i += 1 + } + } + + lazy val newInstanceDeclaration : String = { + + def defCon = "new " + origClass.getName + "();" + try{ + val c = origClass.getClassLoader.loadClass(origClass.getName + "$") + if(Modifier.isPublic(c.getModifiers)){ + val method = c.getMethod("apply") + + if(Modifier.isPublic(method.getModifiers) && + origClass.isAssignableFrom(method.getReturnType)){ + val staticField = c.getDeclaredField("MODULE$") + "%s.%s.apply();".format(c.getName,staticField.getName) + }else{ + defCon + } + }else{ + defCon + } + }catch{ + case e : ClassNotFoundException => { + defCon + } + } + } + + protected def buildPackMethodBody() : String = { + resetStringBuilder(); + buildString("{"); + buildString("%s _$$_t = (%s)$2;", this.origName, this.origName); + buildString("$1.packArray(%d);", entries.length.asInstanceOf[AnyRef]); + for(i <- 0 until entries.length) { + val e = entries(i) + + if(!e.isAvailable) { + buildString("$1.packNil();"); + }else{ + val t = e.getType; + if(t.isPrimitive()) { + buildString("$1.%s(_$$_t.%s());", primitivePackName(t), e.getName()); + } else { + buildString("if(_$$_t.%s() == null) {", e.getName()); + if(!e.isNullable() && !e.isOptional()) { + buildString("throw new %s();", classOf[MessageTypeException].getName()); + } else { + buildString("$1.packNil();"); + } + buildString("} else {"); + buildString(" this.templates[%d].pack($1, _$$_t.%s());", i.asInstanceOf[AnyRef], e.getName()); + buildString("}"); + } + } + + } + buildString("}"); + return getBuiltString(); + } + + + def buildUnpackMethodBody() : String = { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = " + newInstanceDeclaration) //new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("int length = $1.unpackArray();"); + buildString("if(length < %d) {", this.minimumArrayLength.asInstanceOf[AnyRef]); + buildString(" throw new %s();", classOf[MessageTypeException].getName()); + buildString("}"); + + for(i <- 0 until this.minimumArrayLength) { + val e = entries(i); + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + }else{ + + buildString("if($1.tryUnpackNull()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", classOf[MessageTypeException].getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s_$eq(null);", e.getName()); + } + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( $1.%s() );", e.getName(), primitiveUnpackName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].unpack($1, _$$_t.%s()));", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + for(i <- this.minimumArrayLength until entries.length) { + buildString("if(length <= %d) { return _$$_t; }", i.asInstanceOf[AnyRef]); + + val e = entries(i); + if(!e.isAvailable()) { + buildString("$1.unpackObject();"); + }else{ + + buildString("if($1.tryUnpackNull()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( $1.%s());", e.getName(), primitiveUnpackName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].unpack($1, _$$_t.%s) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + // latter entries are all Optional + nil => keep default value + + buildString("for(int i=%d; i < length; i++) {", entries.length.asInstanceOf[AnyRef]); + buildString(" $1.unpackObject();"); + buildString("}"); + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + + protected override def buildConvertMethodBody() : String = { + resetStringBuilder(); + buildString("{ "); + + buildString("%s _$$_t;", this.origName); + buildString("if($2 == null) {"); + buildString(" _$$_t = " + newInstanceDeclaration) //new %s();", this.origName); + buildString("} else {"); + buildString(" _$$_t = (%s)$2;", this.origName); + buildString("}"); + + buildString("%s[] array = $1.asArray();", classOf[MessagePackObject].getName()); + buildString("int length = array.length;"); + buildString("if(length < %d) {", this.minimumArrayLength.asInstanceOf[AnyRef]); + buildString(" throw new %s();", classOf[MessageTypeException].getName()); + buildString("}"); + + buildString("%s obj;", classOf[MessagePackObject].getName()); + + for(i <- 0 until this.minimumArrayLength) { + val e = entries(i); + if(e.isAvailable()) { + buildString("obj = array[%d];", i.asInstanceOf[AnyRef]); + buildString("if(obj.isNil()) {"); + if(e.isRequired()) { + // Required + nil => exception + buildString("throw new %s();", classOf[MessageTypeException].getName()); + } else if(e.isOptional()) { + // Optional + nil => keep default value + } else { // Nullable + // Nullable + nil => set null + buildString("_$$_t.%s_$eq( null );", e.getName()); + } + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( obj.%s());", e.getName(), primitiveConvertName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].convert(obj, _$$_t.%s()) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + for(i <- this.minimumArrayLength until entries.length) { + buildString("if(length <= %d) { return _$$_t; }", i.asInstanceOf[AnyRef]); + + val e = entries(i); + if(e.isAvailable()) { + + + buildString("obj = array[%d];", i.asInstanceOf[AnyRef]); + buildString("if(obj.isNil()) {"); + // this is Optional field becaue i >= minimumArrayLength + // Optional + nil => keep default value + buildString("} else {"); + val t = e.getType(); + if(t.isPrimitive()) { + buildString("_$$_t.%s_$eq( obj.%s());", e.getName(), primitiveConvertName(t)); + } else { + buildString("_$$_t.%s_$eq( (%s)this.templates[%d].convert(obj, _$$_t.%s) );", e.getName(), e.getJavaTypeName(), i.asInstanceOf[AnyRef], e.getName()); + } + buildString("}"); + } + } + + // latter entries are all Optional + nil => keep default value + + buildString("return _$$_t;"); + + buildString("}"); + return getBuiltString(); + } + } + +class ScalaFieldEntryReader extends IFieldEntryReader{ + + type Property = (Method,Method,Field) + type PropertySet = (String,Property) + + def readImplicitFieldOption(targetClass: Class[_]) = { + FieldOption.NULLABLE + } + + def convertFieldEntries(targetClass: Class[_], flist: FieldList) = { + + val list : List[FieldList.Entry] = flist.getList.asScala.toList + + list.map( s => { + if(s.isAvailable){ + val getter = targetClass.getMethod(s.getName) + if(getter.getReturnType.getName != "void"){ + val setter = targetClass.getMethod(s.getName + "_$eq",getter.getReturnType) + if(setter.getReturnType.getName == "void"){ + val f = try{targetClass.getDeclaredField(s.getName)} + catch{ + case e : NoSuchFieldException => null + } + val prop = (s.getName,(getter,setter,f)) + convertToScalaFieldEntry(prop) + }else{ + new ScalaFieldEntry("") + } + }else new ScalaFieldEntry("") + }else{ + new ScalaFieldEntry("") + } + }).toArray + } + + def readFieldEntries(targetClass: Class[_], implicitOption: FieldOption) = { + val props = findPropertyMethods(targetClass) filter( !hasAnnotation(_,classOf[Ignore])) + + val indexed = indexing(props) + indexed.map(convertToScalaFieldEntry(_)) + } + + + def setter_?(method : Method) : Boolean = { + Modifier.isPublic(method.getModifiers) && + method.getReturnType.getName == "void" && + method.getName.endsWith("_$eq") && + method.getParameterTypes.length == 1 + } + + def getter_?(method : Method) : Boolean = { + Modifier.isPublic(method.getModifiers) && + method.getReturnType.getName != "void" && + method.getParameterTypes.length == 0 + + } + + + + + def findPropertyMethods(targetClass: Class[_]) : Map[String,Property] = { + var getters : Map[String,Method] = ListMap.empty + var setters : Map[String,Method] = ListMap.empty + + def extractName( n : String) = { + n.substring(0,n.length - 4) + } + + //Find getters and setters + for( m <- targetClass.getMethods){ + if(setter_?(m)){ + setters +=(extractName(m.getName) -> m) + }else if(getter_?(m)){ + getters +=(m.getName -> m) + } + } + + var props : Map[String,Property] = ListMap.empty + + def sameType_?( getter : Method,setter : Method) = { + getter.getReturnType == setter.getParameterTypes()(0) + } + + for(g <- getters){ + setters.get(g._1).map( s => { + if(sameType_?(g._2,s)){ + + val name = g._1 + val f = try{targetClass.getDeclaredField(name)} + catch{ + case e : NoSuchFieldException => null + } + + //TODO add validation for field + props +=( name -> (g._2,s,f)) + } + }) + } + props + } + + def indexing( props : Map[String , Property]) : Array[PropertySet] = { + val indexed = new Array[PropertySet](props.size) + + var notIndexed : List[PropertySet] = Nil + + for(s <- props){ + val i = getAnnotation(s,classOf[Index]) + if(i == null){ + notIndexed = notIndexed :+ s + }else{ + val index = i.value + if(indexed(index) != null){ + throw new TemplateBuildException("duplicated index: "+index); + }else{ + try{ + indexed(index) = s + }catch{ + case e : Exception => { + throw new TemplateBuildException("invalid index: %s index must be 0 <= x < %s".format(index,indexed.length)); + } + } + } + } + } + + for( i <- 0 until indexed.length ){ + if(indexed(i) == null){ + indexed(i) = notIndexed.head + notIndexed = notIndexed.drop(1) + } + } + + + indexed + } + + def convertToScalaFieldEntry( propInfo : PropertySet) = { + val entry = new ScalaFieldEntry(propInfo._1) + entry.option = readFieldOption(propInfo,FieldOption.NULLABLE) + entry.normalType = readValueType(propInfo) + entry.genericType = readGenericType(propInfo) + + entry + } + + + def hasAnnotation[T <: JavaAnnotation](prop : PropertySet , classOfAnno : Class[T]) : Boolean = { + val getter = prop._2._1 + val setter = prop._2._2 + val field = prop._2._3 + getter.getAnnotation(classOfAnno) != null || + setter.getAnnotation(classOfAnno) != null || + {if(field != null) field.getAnnotation(classOfAnno) != null + else false} + } + def getAnnotation[T <: JavaAnnotation](prop : PropertySet , classOfAnno : Class[T]) : T = { + val getter = prop._2._1 + val setter = prop._2._2 + val field = prop._2._3 + + + + val a = getter.getAnnotation(classOfAnno) + if(a != null){ + a + }else{ + val b = setter.getAnnotation(classOfAnno) + if(b != null){ + b + }else if(field != null){ + field.getAnnotation(classOfAnno) + }else{ + null.asInstanceOf[T] + } + } + } + + def readFieldOption(prop : PropertySet , implicitOption : FieldOption) = { + if(hasAnnotation(prop,classOf[Required])){ + FieldOption.REQUIRED + } else if(hasAnnotation(prop,classOf[Optional])){ + FieldOption.OPTIONAL + } else if(hasAnnotation(prop,classOf[Nullable])){ + if(readValueType(prop).isPrimitive){ + FieldOption.REQUIRED + }else{ + FieldOption.NULLABLE + } + } else{ + if(implicitOption == FieldOption.NULLABLE){ + if(readValueType(prop).isPrimitive){ + FieldOption.REQUIRED + }else{ + FieldOption.NULLABLE + } + }else{ + implicitOption + } + } + + } + + def readValueType(prop : PropertySet) = { + prop._2._1.getReturnType + } + def readGenericType(prop : PropertySet) = { + prop._2._1.getGenericReturnType + } +} + +class ScalaFieldEntry(name : String) extends IFieldEntry{ + + def getName() = name + + def isNullable() = {getOption == FieldOption.NULLABLE} + + def isOptional = {getOption == FieldOption.OPTIONAL} + + def isRequired = {getOption == FieldOption.REQUIRED} + + def isAvailable = {getOption != FieldOption.IGNORE} + + var option : FieldOption = null + + var genericType : Type = null + + def getJavaTypeName = { + if(getType.isArray){ + //TODO implement here + getType.getName() + }else{ + getType.getName() + } + + } + + var normalType : Class[_] = null + + def getOption() = option + def getType() = normalType + def getGenericType() = genericType + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala b/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala new file mode 100644 index 00000000..45b6f5fc --- /dev/null +++ b/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala @@ -0,0 +1,76 @@ +package org.msgpack + +import template._ +import builder.{MessagePackMessageBuilderSelector, BuilderSelectorRegistry} +import template.javassist.BuildContextFactory +import collection.mutable.{MutableList, LinkedList} +import collection.mutable.{Map => MMap,HashMap => MHashMap} +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 1:34 + */ + +object ScalaMessagePack { + + { + // for scala object + BuilderSelectorRegistry.getInstance.insertBefore( + MessagePackMessageBuilderSelector.NAME, + new ScalaTemplateBuilderSelector) + + // register scala's list classes + TemplateRegistry.register(classOf[List[_]],new ImmutableListTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[List[_]],new GenericTemplate1(classOf[ImmutableListTemplate])) + TemplateRegistry.register(classOf[Seq[_]],new ImmutableListTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[Seq[_]],new GenericTemplate1(classOf[ImmutableListTemplate])) + TemplateRegistry.register(classOf[LinkedList[_]],new LinkedListTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[LinkedList[_]],new GenericTemplate1(classOf[LinkedListTemplate])) + TemplateRegistry.register(classOf[MutableList[_]],new MutableListCTemplate(AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[MutableList[_]],new GenericTemplate1(classOf[MutableListCTemplate])) + + // register scala's map classes + TemplateRegistry.register(classOf[Map[_,_]],new ImmutableMapTemplate( + AnyTemplate.getInstance,AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[Map[_,_]],new GenericTemplate2( + classOf[ImmutableMapTemplate])) + TemplateRegistry.register(classOf[MMap[_,_]],new MutableHashMapTemplate( + AnyTemplate.getInstance,AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[MMap[_,_]],new GenericTemplate2( + classOf[MutableHashMapTemplate])) + TemplateRegistry.register(classOf[MHashMap[_,_]],new MutableHashMapTemplate( + AnyTemplate.getInstance,AnyTemplate.getInstance)) + TemplateRegistry.registerGeneric(classOf[MHashMap[_,_]],new GenericTemplate2( + classOf[MutableHashMapTemplate])) + + + + + } + + /** + * dammy method for initialize + */ + def init() = {} + + + def pack( obj : Any) = { + MessagePack.pack(obj.asInstanceOf[AnyRef]) + } + + def unpack[T]( buffer : Array[Byte])(implicit manifest : ClassManifest[T]) : T = { + MessagePack.unpack[T]( buffer, manifest.erasure.asInstanceOf[Class[T]]) + } + + def unpackD(buffer : Array[Byte]) = { + MessagePack.unpack(buffer) + } + + + + + + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala new file mode 100644 index 00000000..f8cc2a7a --- /dev/null +++ b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilder.scala @@ -0,0 +1,16 @@ +package org.msgpack; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 1:52 + */ + +class ScalaTemplateBuilder { + + + def pack(v : Int) = { + + } + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala new file mode 100644 index 00000000..b8b7c122 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala @@ -0,0 +1,48 @@ +package org.msgpack + +import annotation.MessagePackMessage +import template.builder.BuilderSelector +import java.lang.reflect.Type +import template.javassist.BuildContextFactory +import template.JavassistTemplateBuilder +import java.lang.annotation.{Annotation => JAnnotation} +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/14 + * Time: 17:59 + */ + +class ScalaTemplateBuilderSelector extends BuilderSelector +{ + val b = new JavassistTemplateBuilder() + + { + b.setFieldEntryReader(new ScalaFieldEntryReader) + b.setBuildContextFactory(new BuildContextFactory{ + def createBuildContext(builder: JavassistTemplateBuilder) = { + new BuildContextForScala(builder) + } + }) + } + + def getName = "ScalaMessagePackMessageTemplateBuilderSelector"; + + def getTemplateBuilder(targetType: Type) = { + b + } + + def matchType(targetType: Type) = { + val c : Class[_] = targetType.asInstanceOf[Class[Object]] + isAnnotated(c, classOf[MessagePackMessage]) && + classOf[ScalaObject].isAssignableFrom(c)//c.isAssignableFrom(classOf[ScalaObject]) + + } + + private def isAnnotated(targetType : Class[_], annotation : Class[_ <: JAnnotation]) = { + targetType.getAnnotation(annotation) != null + + } + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala b/scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala new file mode 100644 index 00000000..5fab23ba --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/ImmutableListTemplate.scala @@ -0,0 +1,49 @@ +package org.msgpack.template + +import org.msgpack._ + +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:25 + */ + +class ImmutableListTemplate(elementTemplate : Template) extends Template{ + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackArray(); + val array : Array[Object] = new Array(length) + + for(i <- 0 until length){ + array(i) = elementTemplate.unpack(pac,null) + } + + array.toList + + } + + def pack(pk: Packer, target: AnyRef) = { + + val list = try{target.asInstanceOf[List[_]]} + catch{ + case e : ClassCastException => { + throw new MessageTypeException("target is not List type: " + target.getClass()); + } + case e : NullPointerException => { + throw new MessageTypeException(new NullPointerException("target is null.")); + } + } + + pk.packArray(list.size) + for( e <- list){ + elementTemplate.pack(pk,e) + } + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + from.asArray.map(elementTemplate.convert(_,null)).toList + } +} diff --git a/scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala b/scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala new file mode 100644 index 00000000..d4dd01f4 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/ImmutableMapTemplate.scala @@ -0,0 +1,54 @@ +package org.msgpack.template + +import org.msgpack._ + +import scala.collection.JavaConverters._ + +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 11:11 + */ + +class ImmutableMapTemplate(keyTemplate : Template , valueTemplate : Template) extends Template { + + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackMap() + val array : Array[(Object,Object)] = new Array(length) + + for(i <- 0 until length){ + array(i) = (keyTemplate.unpack(pac,null),valueTemplate.unpack(pac,null)) + } + + array.toMap + + } + + def pack(pk: Packer, target: AnyRef) = { + + val map = try{target.asInstanceOf[Map[_,_]]} + catch{ + case e : ClassCastException => { + throw new MessageTypeException("target is not List type: " + target.getClass()); + } + case e : NullPointerException => { + throw new MessageTypeException(new NullPointerException("target is null.")); + } + } + pk.packMap(map.size) + for( e <- map){ + keyTemplate.pack(pk,e._1) + valueTemplate.pack(pk,e._2) + } + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + from.asMap.asScala.map(p => (keyTemplate.convert(p._1,null),valueTemplate.convert(p._2,null))).toMap + } + + + +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala b/scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala new file mode 100644 index 00000000..c1973ae6 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/MutableListTemplate.scala @@ -0,0 +1,56 @@ +package org.msgpack.template + +import org.msgpack.{MessagePackObject, Packer, Unpacker, Template} +import collection.mutable.{MutableList, LinearSeq, LinkedList} +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:37 + */ + +abstract class MutableListTemplate[T <: LinearSeq[_]](elementTemplate : Template) extends Template{ + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackArray(); + + var list : LinearSeq[_] = if(to == null){ + toList(new Array[Object](0)) + }else{ + to.asInstanceOf[T] + } + for(i <- 0 until length){ + list = list :+ elementTemplate.unpack(pac,null) + } + + list + + } + def toList(array : Array[Object]) : T + + def pack(pk: Packer, target: AnyRef) = { + + val list = target.asInstanceOf[LinearSeq[_]] + pk.packArray(list.size) + for( e <- list){ + elementTemplate.pack(pk,e) + } + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + toList(from.asArray.map(elementTemplate.convert(_,null))) + } +} + +class LinkedListTemplate(elementTemplate : Template) extends MutableListTemplate[LinkedList[_]](elementTemplate){ + def toList(array : Array[Object]) = LinkedList(array :_*) +} +class MutableListCTemplate(elementTemplate : Template) extends MutableListTemplate[MutableList[_]](elementTemplate){ + def toList(array : Array[Object]) = { + val list : MutableList[Object] = new MutableList + list ++= array + list + } +} \ No newline at end of file diff --git a/scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala b/scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala new file mode 100644 index 00000000..0503f069 --- /dev/null +++ b/scala/src/main/scala/org/msgpack/template/MutableMapTemplate.scala @@ -0,0 +1,70 @@ +package org.msgpack.template; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 12:06 + */ + +import org.msgpack._ +import collection.mutable.{HashMap,Map => MMap} +import scala.collection.JavaConverters._ + +abstract class MutableMapTemplate[T <: MMap[_,_]](keyTemplate : Template , valueTemplate : Template) extends Template { + + def unpack(pac: Unpacker, to: AnyRef) = { + + val length = pac.unpackMap() + val array : Array[(Object,Object)] = new Array(length) + + for(i <- 0 until length){ + array(i) = (keyTemplate.unpack(pac,null),valueTemplate.unpack(pac,null)) + } + + toMap(array) + + } + + def toMap(array : Array[(Object,Object)]) : T + + + def pack(pk: Packer, target: AnyRef) = { + + val map = try{target.asInstanceOf[MMap[_,_]]} + catch{ + case e : ClassCastException => { + throw new MessageTypeException("target is not List type: " + target.getClass()); + } + case e : NullPointerException => { + throw new MessageTypeException(new NullPointerException("target is null.")); + } + } + pk.packMap(map.size) + for( e <- map){ + keyTemplate.pack(pk,e._1) + valueTemplate.pack(pk,e._2) + } + + + } + + def convert(from: MessagePackObject, to: AnyRef) = { + toMap(from.asMap.asScala.map(p => (keyTemplate.convert(p._1,null),valueTemplate.convert(p._2,null))).toArray) + + } + + + +} + + +class MutableHashMapTemplate(keyTemplate : Template , valueTemplate : Template) + extends MutableMapTemplate[HashMap[_,_]](keyTemplate,valueTemplate ) { + + def toMap(array : Array[(Object,Object)]) = { + HashMap(array :_*) + } + + + +} diff --git a/scala/src/test/scala/org/msgpack/ClassWithList.scala b/scala/src/test/scala/org/msgpack/ClassWithList.scala new file mode 100644 index 00000000..4fc5b4ff --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ClassWithList.scala @@ -0,0 +1,21 @@ +package org.msgpack; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:13 + */ + +import annotation.MessagePackMessage +import collection.mutable.{MutableList, LinkedList} + +@MessagePackMessage +class ClassWithList { + var immutable : List[String] = Nil + + var mutable : LinkedList[String] = LinkedList.empty + + var mutable2 : MutableList[String] = new MutableList + + //var tuple2 : (String,String) = (null,null) +} \ No newline at end of file diff --git a/scala/src/test/scala/org/msgpack/ClassWithMap.scala b/scala/src/test/scala/org/msgpack/ClassWithMap.scala new file mode 100644 index 00000000..6256dd76 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ClassWithMap.scala @@ -0,0 +1,19 @@ +package org.msgpack; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/11 + * Time: 2:22 + */ + +import annotation.MessagePackMessage +import scala.collection.mutable.{Map => MMap} + +@MessagePackMessage +class ClassWithMap { + + var immutable : Map[String,String] = Map.empty + + var mutable : MMap[String,String] = MMap.empty + +} \ No newline at end of file diff --git a/scala/src/test/scala/org/msgpack/CollectionPackSpec.scala b/scala/src/test/scala/org/msgpack/CollectionPackSpec.scala new file mode 100644 index 00000000..ec305507 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/CollectionPackSpec.scala @@ -0,0 +1,71 @@ +package org.msgpack + +import org.junit.runner.RunWith +import org.specs._ +import org.specs.matcher._ +import org.specs.runner.{ JUnitSuiteRunner, JUnit } +import scala.collection.mutable.LinkedList + +//import org.scalacheck.Gen + +/** + * Sample specification. + * + * This specification can be executed with: scala -cp ${package}.SpecsTest + * Or using maven: mvn test + * + * For more information on how to write or run specifications, please visit: http://code.google.com/p/specs. + * + */ +@RunWith(classOf[JUnitSuiteRunner]) +class CollectionPackSpec extends Specification with JUnit { + + "ScalaMessagePack" should { + "pack scala-list" in { + val c = new ClassWithList + + c.immutable = List("a","b","c") + c.mutable = LinkedList("a","b","d") + c.mutable2 ++= List("gh","fjei") + //c.tuple2 = ("hoge","wahoo") + + val b = ScalaMessagePack.pack(c) + val des = ScalaMessagePack.unpack[ClassWithList](b) + + des.immutable must be_==(c.immutable) + des.mutable must be_==(c.mutable) + //des.tuple2 must be_==(c.tuple2) + + val mpo = ScalaMessagePack.unpackD(b) + val des2 = mpo.convert(classOf[ClassWithList]) + + des2.immutable must be_==(c.immutable) + des2.mutable must be_==(c.mutable) + + } + "pack scala-map" in { + val c = new ClassWithMap + c.immutable = Map("a" -> "hoge","b" -> "fuga","c" -> "hehe") + c.mutable = scala.collection.mutable.Map("d" -> "oo" , "e" -> "aa") + + val b = ScalaMessagePack.pack(c) + val des = ScalaMessagePack.unpack[ClassWithMap](b) + + des.immutable must be_==(c.immutable) + des.mutable must be_==(c.mutable) + + val mpo = ScalaMessagePack.unpackD(b) + val des2 = mpo.convert(classOf[ClassWithMap]) + + des2.immutable must be_==(c.immutable) + des2.mutable must be_==(c.mutable) + + } + + } + + + + +} + diff --git a/scala/src/test/scala/org/msgpack/SampleClass.scala b/scala/src/test/scala/org/msgpack/SampleClass.scala new file mode 100644 index 00000000..4979ec61 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/SampleClass.scala @@ -0,0 +1,77 @@ +package org.msgpack + +import annotation.MessagePackMessage +import annotation.{Optional, Index} +import java.util.Date +; +/* + * Created by IntelliJ IDEA. + * User: takeshita + * Date: 11/03/10 + * Time: 1:35 + */ + +@MessagePackMessage +class SampleClass { + var name : String = "hoge" + var number : Int = 2 + +} + +trait SampleTrait { + + var traitName : String = "" + + var traitNum : Int = 12 + +} + +class SampleClass2 extends SampleClass with SampleTrait { + + + @Index(3) + var sampleClass2Name : String = "sampleclass2" + + @Index(0) + def sampleClass2Num : Int = 22 + def sampleClass2Num_=(v : Int) = {} + + val notProperty : String ="This is not prop.Only getter" + + // wrong property + def wrongValue : Int = 53 + def wrongValue_=(v : String) = {} + +} + +object NotDefaultCons{ + + def apply() : NotDefaultCons2 = { + new NotDefaultCons2() + } +} +@MessagePackMessage +class NotDefaultCons(var name : String){ +} + +class NotDefaultCons2 extends NotDefaultCons("hoge") + +@MessagePackMessage +class BasicalTypes{ + + var intVar : Int = 0 + var longVar : Long = 0 + var shortVar : Short = 0 + var byteVar : Byte = 0 + var boolVar : Boolean = false + + var floatVar : Float = 0 + var doubleVar : Double = 0 + + var strVar : String = "" + + var dateVar : Date = null + + + +} \ No newline at end of file diff --git a/scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala b/scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala new file mode 100644 index 00000000..3eeffaad --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ScalaFieldEntryReaderSpec.scala @@ -0,0 +1,120 @@ +package org.msgpack + +import org.junit.runner.RunWith +import org.specs._ +import org.specs.matcher._ +import org.specs.runner.{ JUnitSuiteRunner, JUnit } +//import org.scalacheck.Gen + +/** + * Sample specification. + * + * This specification can be executed with: scala -cp ${package}.SpecsTest + * Or using maven: mvn test + * + * For more information on how to write or run specifications, please visit: http://code.google.com/p/specs. + * + */ +@RunWith(classOf[JUnitSuiteRunner]) +class ScalaFieldEntryReaderSpec extends Specification with JUnit { + + "ScalaFieldEntryReader" should { + "check setter " in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass] + + reader.setter_?(c.getMethod("name")) must be_==(false) + reader.setter_?(c.getMethod("name_$eq",classOf[String])) must be_==(true) + } + "check getter " in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass] + + reader.getter_?(c.getMethod("name")) must be_==(true) + reader.getter_?(c.getMethod("name_$eq",classOf[String])) must be_==(false) + } + + "find props " in { + val reader = new ScalaFieldEntryReader() + + { + val c = classOf[SampleClass] + + val props = reader.findPropertyMethods(c) + + props.size must be_==(2) + props must haveKey("name") + props must haveKey("number") + } + + { + val c = classOf[SampleClass2] + + val props = reader.findPropertyMethods(c) + + println(props.keys) + + props.size must be_==(6) + props must haveKey("name") + props must haveKey("number") + props must haveKey("traitName") + props must haveKey("traitNum") + props must haveKey("sampleClass2Name") + props must haveKey("sampleClass2Num") + } + + } + + "indexing " in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass2] + + def printDecs(c : Class[_]) : Unit = { + println(c.getName + "---") + val ds = c.getDeclaredMethods + ds.foreach(m => {println(m) + println(m.getAnnotations.toList) + }) + if(c.getSuperclass != classOf[Object]){ + printDecs(c.getSuperclass) + } + } + printDecs(c) + + + + val props = reader.findPropertyMethods(c) + + val indexed = reader.indexing(props) + + println(indexed.map(_._1).toList) + + indexed.size must be_==(6) + indexed(0)._1 must be_==("sampleClass2Num") + indexed(3)._1 must be_==("sampleClass2Name") + indexed must notContain(null) + + } + + "read entries" in { + val reader = new ScalaFieldEntryReader() + + val c = classOf[SampleClass2] + import org.msgpack.template.FieldOption + + val e = reader.readFieldEntries(c, FieldOption.NULLABLE) + + e.size must be_==(6) + + } + + } + + + + +} + diff --git a/scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala b/scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala new file mode 100644 index 00000000..8f464000 --- /dev/null +++ b/scala/src/test/scala/org/msgpack/ScalaMessagePackSpec.scala @@ -0,0 +1,90 @@ +package org.msgpack + +import org.junit.runner.RunWith +import org.specs._ +import org.specs.matcher._ +import org.specs.runner.{ JUnitSuiteRunner, JUnit } +import java.util.Date + +//import org.scalacheck.Gen + +/** + * Sample specification. + * + * This specification can be executed with: scala -cp ${package}.SpecsTest + * Or using maven: mvn test + * + * For more information on how to write or run specifications, please visit: http://code.google.com/p/specs. + * + */ +@RunWith(classOf[JUnitSuiteRunner]) +class ScalaMessagePackTest extends Specification with JUnit /*with ScalaCheck*/ { + + "ScalaMessagePackTest" should { + "pack and unpack" in { + + val sc = new SampleClass() + sc.name = "Test object" + sc.number = 123456 + + println("Sampleclass is inherit ScalaObject " + classOf[ScalaObject].isAssignableFrom(classOf[SampleClass])) + new ScalaTemplateBuilderSelector().matchType(classOf[SampleClass]) must be_==(true) + val b = ScalaMessagePack.pack(sc) + + val deser = ScalaMessagePack.unpack[SampleClass](b) + + deser.name must be_==(sc.name) + deser.number must be_==(sc.number) + + val mso = ScalaMessagePack.unpackD(b) + val conv = mso.convert(classOf[SampleClass]) + conv.name must be_==(sc.name) + conv.number must be_==(sc.number) + } + "check basical types" in { + val v = new BasicalTypes + v.intVar = 20 + v.longVar = 11 + v.shortVar = 7 + v.byteVar = 1 + v.floatVar = 1.5f + v.doubleVar = 2.5 + v.strVar = "fugafuga" + v.dateVar = new Date(1233333) + + val b = ScalaMessagePack.pack(v) + val des : BasicalTypes = ScalaMessagePack.unpack[BasicalTypes](b) + + des.intVar must be_==(v.intVar) + des.longVar must be_==(v.longVar) + des.shortVar must be_==(v.shortVar) + des.byteVar must be_==(v.byteVar) + des.floatVar must be_==(v.floatVar) + des.doubleVar must be_==(v.doubleVar) + des.strVar must be_==(v.strVar) + des.dateVar must be_==(v.dateVar) + + + } + + "pack and unpack none-default constructor class" in { + + val sc = new NotDefaultCons("hehehehe") + + val b = ScalaMessagePack.pack(sc) + + val deser = ScalaMessagePack.unpack[NotDefaultCons](b) + + deser.name must be_==(sc.name) + + val mso = ScalaMessagePack.unpackD(b) + val conv = mso.convert(classOf[NotDefaultCons]) + conv.name must be_==(sc.name) + } + + + } + + +} + From 21f0d0bfc47ddc6d9092621705047f3bef385ba5 Mon Sep 17 00:00:00 2001 From: takeshita Date: Mon, 4 Apr 2011 01:46:29 +0900 Subject: [PATCH 32/53] Delete moved class. (TemplateBuilder.java is moved to org.msgpack.template.builder) --- .../org/msgpack/template/TemplateBuilder.java | 381 ------------------ 1 file changed, 381 deletions(-) delete mode 100644 java/src/main/java/org/msgpack/template/TemplateBuilder.java diff --git a/java/src/main/java/org/msgpack/template/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/TemplateBuilder.java deleted file mode 100644 index e3d25b29..00000000 --- a/java/src/main/java/org/msgpack/template/TemplateBuilder.java +++ /dev/null @@ -1,381 +0,0 @@ -// -// 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.lang.reflect.*; -import java.lang.annotation.*; -import java.util.List; -import java.util.ArrayList; -import java.util.EnumSet; -import org.msgpack.*; -import org.msgpack.annotation.*; - -public abstract class TemplateBuilder { - public static class FieldEntry { - private Field field; - private FieldOption option; - - public FieldEntry() { - this.field = null; - this.option = FieldOption.IGNORE; - } - - public FieldEntry(FieldEntry e) { - this.field = e.field; - this.option = e.option; - } - - public FieldEntry(Field field, FieldOption option) { - this.field = field; - this.option = option; - } - - public Field getField() { - return field; - } - - public String getName() { - return field.getName(); - } - - public Class getType() { - return field.getType(); - } - - public String getJavaTypeName() { - Class type = field.getType(); - if(type.isArray()) { - return arrayTypeToString(type); - } else { - return type.getName(); - } - } - - public Type getGenericType() { - return field.getGenericType(); - } - - public FieldOption getOption() { - return option; - } - - public boolean isAvailable() { - return option != FieldOption.IGNORE; - } - - public boolean isRequired() { - return option == FieldOption.REQUIRED; - } - - public boolean isOptional() { - return option == FieldOption.OPTIONAL; - } - - public boolean isNullable() { - return option == FieldOption.NULLABLE; - } - - static String arrayTypeToString(Class type) { - int dim = 1; - Class baseType = type.getComponentType(); - while(baseType.isArray()) { - baseType = baseType.getComponentType(); - dim += 1; - } - StringBuilder sb = new StringBuilder(); - sb.append(baseType.getName()); - for (int i = 0; i < dim; ++i) { - sb.append("[]"); - } - return sb.toString(); - } - } - - // Override this method - public abstract Template buildTemplate(Class targetClass, FieldEntry[] entries); - - // Override this method - public abstract Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries); - - // Override this method - public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim); - - - public Template buildTemplate(Class targetClass, FieldList flist) throws NoSuchFieldException { - checkValidation(targetClass); - return buildTemplate(targetClass, convertFieldEntries(targetClass, flist)); - } - - public Template buildTemplate(Class targetClass, FieldOption implicitOption) { - checkValidation(targetClass); - return buildTemplate(targetClass, readFieldEntries(targetClass, implicitOption)); - } - - public Template buildTemplate(Class targetClass) { - FieldOption implicitOption = readImplicitFieldOption(targetClass); - return buildTemplate(targetClass, implicitOption); - } - - public Template buildOrdinalEnumTemplate(Class targetClass) { - checkOrdinalEnumValidation(targetClass); - Enum[] entries = (Enum[])targetClass.getEnumConstants(); - return buildOrdinalEnumTemplate(targetClass, entries); - } - - public Template buildArrayTemplate(Type arrayType) { - Type baseType; - Class baseClass; - int dim = 1; - if(arrayType instanceof GenericArrayType) { - GenericArrayType type = (GenericArrayType)arrayType; - baseType = type.getGenericComponentType(); - while(baseType instanceof GenericArrayType) { - baseType = ((GenericArrayType)baseType).getGenericComponentType(); - dim += 1; - } - if(baseType instanceof ParameterizedType) { - baseClass = (Class)((ParameterizedType)baseType).getRawType(); - } else { - baseClass = (Class)baseType; - } - } else { - Class type = (Class)arrayType; - baseClass = type.getComponentType(); - while(baseClass.isArray()) { - baseClass = baseClass.getComponentType(); - dim += 1; - } - baseType = baseClass; - } - return buildArrayTemplate(arrayType, baseType, baseClass, dim); - } - - private static Type getComponentType(Type arrayType) { - if(arrayType instanceof GenericArrayType) { - return ((GenericArrayType)arrayType).getGenericComponentType(); - } else { - return ((Class)arrayType).getComponentType(); - } - } - - - private static TemplateBuilder instance; - static { - instance = selectDefaultTemplateBuilder(); - } - - private static TemplateBuilder selectDefaultTemplateBuilder() { - try { - // FIXME JavassistTemplateBuilder doesn't work on DalvikVM - if(System.getProperty("java.vm.name").equals("Dalvik")) { - return ReflectionTemplateBuilder.getInstance(); - } - } catch (Exception e) { - } - return JavassistTemplateBuilder.getInstance(); - } - - synchronized static void setInstance(TemplateBuilder builder) { - instance = builder; - } - - public static Template build(Class targetClass) { - return instance.buildTemplate(targetClass); - } - - public static Template build(Class targetClass, FieldOption implicitOption) { - return instance.buildTemplate(targetClass, implicitOption); - } - - public static Template build(Class targetClass, FieldList flist) throws NoSuchFieldException { - return instance.buildTemplate(targetClass, flist); - } - - public static Template buildOrdinalEnum(Class targetClass) { - return instance.buildOrdinalEnumTemplate(targetClass); - } - - public static Template buildArray(Type arrayType) { - return instance.buildArrayTemplate(arrayType); - } - - - private static void checkValidation(Class targetClass) { - if(targetClass.isInterface()) { - throw new TemplateBuildException("cannot build template of interface"); - } - if(targetClass.isArray()) { - throw new TemplateBuildException("cannot build template of array class"); - } - if(targetClass.isPrimitive()) { - throw new TemplateBuildException("cannot build template of primitive type"); - } - } - - private static void checkOrdinalEnumValidation(Class targetClass) { - if(!targetClass.isEnum()) { - throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); - } - } - - - static FieldEntry[] convertFieldEntries(Class targetClass, FieldList flist) throws NoSuchFieldException { - List src = flist.getList(); - FieldEntry[] result = new FieldEntry[src.size()]; - for(int i=0; i < src.size(); i++) { - FieldList.Entry s = src.get(i); - if(s.isAvailable()) { - result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); - } else { - result[i] = new FieldEntry(); - } - } - return result; - } - - static FieldEntry[] readFieldEntries(Class targetClass, FieldOption implicitOption) { - Field[] allFields = readAllFields(targetClass); - - /* index: - * @Index(0) int field_a; // 0 - * int field_b; // 1 - * @Index(3) int field_c; // 3 - * int field_d; // 4 - * @Index(2) int field_e; // 2 - * int field_f; // 5 - */ - List indexed = new ArrayList(); - int maxIndex = -1; - for(Field f : allFields) { - FieldOption opt = readFieldOption(f, implicitOption); - if(opt == FieldOption.IGNORE) { - // skip - continue; - } - - int index = readFieldIndex(f, maxIndex); - - if(indexed.size() > index && indexed.get(index) != null) { - throw new TemplateBuildException("duplicated index: "+index); - } - if(index < 0) { - throw new TemplateBuildException("invalid index: "+index); - } - - while(indexed.size() <= index) { - indexed.add(null); - } - indexed.set(index, new FieldEntry(f, opt)); - - if(maxIndex < index) { - maxIndex = index; - } - } - - FieldEntry[] result = new FieldEntry[maxIndex+1]; - for(int i=0; i < indexed.size(); i++) { - FieldEntry e = indexed.get(i); - if(e == null) { - result[i] = new FieldEntry(); - } else { - result[i] = e; - } - } - - return result; - } - - private static Field[] readAllFields(Class targetClass) { - // order: [fields of super class, ..., fields of this class] - List succ = new ArrayList(); - int total = 0; - for(Class c = targetClass; c != Object.class; c = c.getSuperclass()) { - Field[] fields = c.getDeclaredFields(); - total += fields.length; - succ.add(fields); - } - Field[] result = new Field[total]; - int off = 0; - for(int i=succ.size()-1; i >= 0; i--) { - Field[] fields = succ.get(i); - System.arraycopy(fields, 0, result, off, fields.length); - off += fields.length; - } - return result; - } - - private static FieldOption readImplicitFieldOption(Class targetClass) { - MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); - if(a == null) { - return FieldOption.DEFAULT; - } - return a.value(); - } - - private static FieldOption readFieldOption(Field field, FieldOption implicitOption) { - int mod = field.getModifiers(); - if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) { - return FieldOption.IGNORE; - } - - if(isAnnotated(field, Ignore.class)) { - return FieldOption.IGNORE; - } else if(isAnnotated(field, Required.class)) { - return FieldOption.REQUIRED; - } else if(isAnnotated(field, Optional.class)) { - return FieldOption.OPTIONAL; - } else if(isAnnotated(field, Nullable.class)) { - if(field.getDeclaringClass().isPrimitive()) { - return FieldOption.REQUIRED; - } else { - return FieldOption.NULLABLE; - } - } - - if(implicitOption != FieldOption.DEFAULT) { - return implicitOption; - } - - // default mode: - // transient : Ignore - // public : Required - // others : Ignore - if(Modifier.isTransient(mod)) { - return FieldOption.IGNORE; - } else if(Modifier.isPublic(mod)) { - return FieldOption.REQUIRED; - } else { - return FieldOption.IGNORE; - } - } - - private static int readFieldIndex(Field field, int maxIndex) { - Index a = field.getAnnotation(Index.class); - if(a == null) { - return maxIndex + 1; - } else { - return a.value(); - } - } - - private static boolean isAnnotated(AccessibleObject ao, Class with) { - return ao.getAnnotation(with) != null; - } -} - From 27b89b237bb8aded199fb89dce40ca89924540e4 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Mon, 4 Apr 2011 01:59:13 +0900 Subject: [PATCH 33/53] java: prototyped TemplateClassWriter, which is program for writing class file of generated tmplate class --- .../main/java/org/msgpack/MessagePack.java | 7 +- .../template/JavassistTemplateBuilder.java | 114 ++++++++++++++++-- .../template/ReflectionTemplateBuilder.java | 31 ++++- .../org/msgpack/template/TemplateBuilder.java | 79 +++++++++++- .../msgpack/template/TemplateClassWriter.java | 28 +++++ .../msgpack/template/TemplateRegistry.java | 8 +- 6 files changed, 249 insertions(+), 18 deletions(-) create mode 100644 java/src/main/java/org/msgpack/template/TemplateClassWriter.java diff --git a/java/src/main/java/org/msgpack/MessagePack.java b/java/src/main/java/org/msgpack/MessagePack.java index f3a73c06..4bb5d2ca 100644 --- a/java/src/main/java/org/msgpack/MessagePack.java +++ b/java/src/main/java/org/msgpack/MessagePack.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,6 +23,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import org.msgpack.template.TemplateRegistry; import org.msgpack.template.TemplateBuilder; +import org.msgpack.template.TemplateClassWriter; import org.msgpack.template.FieldList; public class MessagePack { @@ -146,6 +147,10 @@ public class MessagePack { } } + public static void write(Class target, String directoryName) { + TemplateClassWriter.write(target, directoryName); + } + public static void register(Class target) { TemplateRegistry.register(target); } diff --git a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java index a4d2e4db..a4ef98ff 100644 --- a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -122,9 +122,33 @@ public class JavassistTemplateBuilder extends TemplateBuilder { this.director = director; } + protected void write(final String className, final String directoryName) { + try { + reset(className, false); + buildClass(); + buildConstructor(); + buildMethodInit(); + buildPackMethod(); + buildUnpackMethod(); + buildConvertMethod(); + writeClassFile(directoryName); + } catch (Exception e) { + String code = getBuiltString(); + if(code != null) { + LOG.error("builder: " + code, e); + throw new TemplateBuildException("cannot compile: " + code, e); + } else { + throw new TemplateBuildException(e); + } + } + } + protected void writeClassFile(final String directoryName) throws CannotCompileException, IOException { + tmplCtClass.writeFile(directoryName); + } + protected Template build(final String className) { try { - reset(className); + reset(className, true); buildClass(); buildConstructor(); buildMethodInit(); @@ -143,8 +167,12 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } - protected void reset(String className) { - tmplName = className + "_$$_Template" + director.nextSeqId(); + protected void reset(String className, boolean isBuilt) { + if (isBuilt) { + tmplName = className + "_$$_Template" + director.nextSeqId(); + } else { + tmplName = className + "_$$_Template"; + } tmplCtClass = director.makeCtClass(tmplName); } @@ -254,6 +282,15 @@ public class JavassistTemplateBuilder extends TemplateBuilder { super(director); } + public void writeTemplateClass(Class targetClass, FieldEntry[] entries, + Template[] templates, final String directoryName) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + write(this.origName, directoryName); + } + public Template buildTemplate(Class targetClass, FieldEntry[] entries, Template[] templates) { this.entries = entries; this.templates = templates; @@ -279,6 +316,22 @@ public class JavassistTemplateBuilder extends TemplateBuilder { this.tmplCtClass.addConstructor(newCtCons); } + protected Template buildInstance(Class targetClass, Class tmplClass, Template[] tmpls) { + try { + Constructor cons = tmplClass.getConstructor(new Class[] { + Class.class, + Template[].class + }); + Object tmpl = cons.newInstance(new Object[] { + targetClass, + tmpls + }); + return (Template)tmpl; + } catch (Exception e) { + throw new TemplateBuildException(e); + } + } + protected Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { Constructor cons = c.getConstructor(new Class[] { Class.class, @@ -544,7 +597,39 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } + @Override + public Class loadTemplateClass(Class targetClass) { + String tmplClassName = targetClass.getName() + "_$$_Template"; + ClassLoader cl = this.getClass().getClassLoader();// TODO + try { + return cl.loadClass(tmplClassName); + } catch (ClassNotFoundException e) { + LOG.debug("Tmplate class not found: " + tmplClassName); + return null; + } + } + + @Override + public Template initializeTemplate(Class targetClass, Class tmplClass, FieldEntry[] entries) { + Template[] tmpls = toTemplates(entries); + BuildContext bc = new BuildContext(this); + return bc.buildInstance(targetClass, tmplClass, tmpls); + } + + @Override + public void writeTemplateClass(Class targetClass, FieldEntry[] entries, String directoryName) { + Template[] tmpls = toTemplates(entries); + BuildContext bc = new BuildContext(this); + bc.writeTemplateClass(targetClass, entries, tmpls, directoryName); + } + public Template buildTemplate(Class targetClass, FieldEntry[] entries) { + Template[] tmpls = toTemplates(entries); + BuildContext bc = new BuildContext(this); + return bc.buildTemplate(targetClass, entries, tmpls); + } + + private static Template[] toTemplates(FieldEntry[] from) { // FIXME private / packagefields //for(FieldEntry e : entries) { // Field f = e.getField(); @@ -554,9 +639,9 @@ public class JavassistTemplateBuilder extends TemplateBuilder { // } //} - Template[] tmpls = new Template[entries.length]; - for(int i=0; i < entries.length; i++) { - FieldEntry e = entries[i]; + Template[] tmpls = new Template[from.length]; + for(int i=0; i < from.length; i++) { + FieldEntry e = from[i]; if(!e.isAvailable()) { tmpls[i] = null; } else { @@ -564,9 +649,7 @@ public class JavassistTemplateBuilder extends TemplateBuilder { tmpls[i] = tmpl; } } - - BuildContext bc = new BuildContext(this); - return bc.buildTemplate(targetClass, entries, tmpls); + return tmpls; } static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate { @@ -575,10 +658,21 @@ public class JavassistTemplateBuilder extends TemplateBuilder { } } + @Override + public void writeOrdinalEnumTemplateClass(Class targetClass, Enum[] entires, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");// TODO + } + public Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries) { return new JavassistOrdinalEnumTemplate(entries); } + @Override + public void writeArrayTemplateClass(Type arrayType, Type genericBaseType, + Class baseClass, int dim, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");//TODO + } + public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { if(dim == 1) { if(baseClass == boolean.class) { diff --git a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java index 03ff2067..e48bceac 100644 --- a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -373,6 +373,22 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } + @Override + public Class loadTemplateClass(Class targetClass) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + + @Override + public Template initializeTemplate(Class targetClass, Class tmplClass, FieldEntry[] entries) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + + @Override + public void writeTemplateClass(Class targetClass, FieldEntry[] entries, + String directoryName) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + public Template buildTemplate(Class targetClass, FieldEntry[] entries) { for(FieldEntry e : entries) { Field f = e.getField(); @@ -448,11 +464,16 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } + @Override + public void writeOrdinalEnumTemplateClass(Class targetClass, + Enum[] entires, String directoryName) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + public Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries) { return new ReflectionOrdinalEnumTemplate(entries); } - static class ReflectionObjectArrayTemplate extends AbstractTemplate { private Class componentClass; private Template elementTemplate; @@ -536,6 +557,12 @@ public class ReflectionTemplateBuilder extends TemplateBuilder { } } + @Override + public void writeArrayTemplateClass(Type arrayType, Type genericBaseType, + Class baseClass, int dim, String directoryName) { + throw new UnsupportedOperationException("Not supported by reflection-based template builder"); + } + public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { if(dim == 1) { if(baseClass == boolean.class) { diff --git a/java/src/main/java/org/msgpack/template/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/TemplateBuilder.java index e3d25b29..f0a32089 100644 --- a/java/src/main/java/org/msgpack/template/TemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/TemplateBuilder.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -107,37 +107,81 @@ public abstract class TemplateBuilder { } } + // Override this method + public abstract Class loadTemplateClass(Class targetClass); + + // Override this method + public abstract Template initializeTemplate(Class targetClass, Class tmplClass, FieldEntry[] entries); + + // Override this method + public abstract void writeTemplateClass(Class targetClass, FieldEntry[] entries, String directoryName); + // Override this method public abstract Template buildTemplate(Class targetClass, FieldEntry[] entries); + // Override this method + public abstract void writeOrdinalEnumTemplateClass(Class targetClass, Enum[] entires, String directoryName); + // Override this method public abstract Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries); + // Override this method + public abstract void writeArrayTemplateClass(Type arrayType, Type genericBaseType, + Class baseClass, int dim, String directoryName); + // Override this method public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim); + public Template initializeTemplate(Class targetClass, Class tmplClass) { + return initializeTemplate(targetClass, tmplClass, readFieldEntries(targetClass, readImplicitFieldOption(targetClass))); + } + + public void writeTemplateClass(Class targetClass, FieldList fList, String directoryName) throws NoSuchFieldException { + checkValidation(targetClass); + writeTemplateClass(targetClass, convertFieldEntries(targetClass, fList), directoryName); + } public Template buildTemplate(Class targetClass, FieldList flist) throws NoSuchFieldException { checkValidation(targetClass); return buildTemplate(targetClass, convertFieldEntries(targetClass, flist)); } + public void writeTemplateClass(Class targetClass, FieldOption implicitOption, String directoryName) { + checkValidation(targetClass); + writeTemplateClass(targetClass, readFieldEntries(targetClass, implicitOption), directoryName); + } + public Template buildTemplate(Class targetClass, FieldOption implicitOption) { checkValidation(targetClass); return buildTemplate(targetClass, readFieldEntries(targetClass, implicitOption)); } + public void writeTemplateClass(Class targetClass, final String directoryName) { + FieldOption implicitOption = readImplicitFieldOption(targetClass); + writeTemplateClass(targetClass, implicitOption, directoryName); + } + public Template buildTemplate(Class targetClass) { FieldOption implicitOption = readImplicitFieldOption(targetClass); return buildTemplate(targetClass, implicitOption); } + public void writeOrdinalEnumTemplateClass(Class targetClass, String directoryName) { + checkOrdinalEnumValidation(targetClass); + Enum[] entries = (Enum[])targetClass.getEnumConstants(); + writeOrdinalEnumTemplateClass(targetClass, entries, directoryName); + } + public Template buildOrdinalEnumTemplate(Class targetClass) { checkOrdinalEnumValidation(targetClass); Enum[] entries = (Enum[])targetClass.getEnumConstants(); return buildOrdinalEnumTemplate(targetClass, entries); } + public void writeArrayTemplateClass(Type arrayType, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");// TODO + } + public Template buildArrayTemplate(Type arrayType) { Type baseType; Class baseClass; @@ -195,22 +239,51 @@ public abstract class TemplateBuilder { instance = builder; } + public static Class load(Class targetClass) { + return instance.loadTemplateClass(targetClass); + } + + public static Template initialize(Class targetClass, Class tmplClass) { + return instance.initializeTemplate(targetClass, tmplClass); + } + + public static void writeClass(Class targetClass, String directoryName) { + instance.writeTemplateClass(targetClass, directoryName); + } + public static Template build(Class targetClass) { return instance.buildTemplate(targetClass); } + public static void writeClass(Class targetClass, FieldOption implicitOption, String directoryName) { + instance.writeTemplateClass(targetClass, implicitOption, directoryName); + } + public static Template build(Class targetClass, FieldOption implicitOption) { return instance.buildTemplate(targetClass, implicitOption); } - public static Template build(Class targetClass, FieldList flist) throws NoSuchFieldException { - return instance.buildTemplate(targetClass, flist); + public static void writeClass(Class targetClass, FieldList fList, String directoryName) + throws NoSuchFieldException { + instance.writeTemplateClass(targetClass, fList, directoryName); + } + + public static Template build(Class targetClass, FieldList fList) throws NoSuchFieldException { + return instance.buildTemplate(targetClass, fList); + } + + public static void writeOrdinalEnumClass(Class targetClass, String directoryName) { + instance.writeOrdinalEnumTemplateClass(targetClass, directoryName); } public static Template buildOrdinalEnum(Class targetClass) { return instance.buildOrdinalEnumTemplate(targetClass); } + public static void writeArrayClass(Type arrayType, String directoryName) { + throw new UnsupportedOperationException("not supported yet.");// TODO + } + public static Template buildArray(Type arrayType) { return instance.buildArrayTemplate(arrayType); } diff --git a/java/src/main/java/org/msgpack/template/TemplateClassWriter.java b/java/src/main/java/org/msgpack/template/TemplateClassWriter.java new file mode 100644 index 00000000..2ead9048 --- /dev/null +++ b/java/src/main/java/org/msgpack/template/TemplateClassWriter.java @@ -0,0 +1,28 @@ +// +// MessagePack for Java +// +// Copyright (C) 2009-2011 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; + +public class TemplateClassWriter { + public static void write(Class target, String directoryName) { + if(target.isEnum()) { + throw new UnsupportedOperationException("Not supported yet."); + } else { + TemplateBuilder.writeClass(target, directoryName); + } + } +} diff --git a/java/src/main/java/org/msgpack/template/TemplateRegistry.java b/java/src/main/java/org/msgpack/template/TemplateRegistry.java index 3f98fb46..ef377efa 100644 --- a/java/src/main/java/org/msgpack/template/TemplateRegistry.java +++ b/java/src/main/java/org/msgpack/template/TemplateRegistry.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -27,7 +27,6 @@ import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackDelegate; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.Template; -import org.msgpack.Templates; public class TemplateRegistry { private static Map map; @@ -111,6 +110,11 @@ public class TemplateRegistry { Class target = (Class)targetType; + Class tmplClass = TemplateBuilder.load(target); + if (tmplClass != null) { + return TemplateBuilder.initialize(target, tmplClass); + } + if(target.isArray()) { // FIXME can't distinguish type-erased T<>[]? tmpl = TemplateBuilder.buildArray(target); From 8e3ea8d26cb74d9d5fcd6ff3723eafaeb4efd78a Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Mon, 4 Apr 2011 02:28:24 +0900 Subject: [PATCH 34/53] java: edit TemplateRegistry.java --- java/src/main/java/org/msgpack/template/TemplateRegistry.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/org/msgpack/template/TemplateRegistry.java b/java/src/main/java/org/msgpack/template/TemplateRegistry.java index ef377efa..a3fe1dff 100644 --- a/java/src/main/java/org/msgpack/template/TemplateRegistry.java +++ b/java/src/main/java/org/msgpack/template/TemplateRegistry.java @@ -112,7 +112,9 @@ public class TemplateRegistry { Class tmplClass = TemplateBuilder.load(target); if (tmplClass != null) { - return TemplateBuilder.initialize(target, tmplClass); + tmpl = TemplateBuilder.initialize(target, tmplClass); + register(target, tmpl); + return tmpl; } if(target.isArray()) { From 173302267f8413c46d77036a052c047d70ae64ec Mon Sep 17 00:00:00 2001 From: mzp Date: Mon, 4 Apr 2011 18:28:37 +0900 Subject: [PATCH 35/53] ocaml: upadte build file --- ocaml/README.markdown | 30 +- ocaml/ocaml/.gitignore | 2 - ocaml/ocaml/OMakefile | 4 +- ocaml/ocaml/msgpackCore.ml | 2581 +++++++++++++++++++++++++++++++++++ ocaml/ocaml/msgpackCore.mli | 141 ++ 5 files changed, 2739 insertions(+), 19 deletions(-) create mode 100644 ocaml/ocaml/msgpackCore.ml create mode 100644 ocaml/ocaml/msgpackCore.mli diff --git a/ocaml/README.markdown b/ocaml/README.markdown index 26048134..c62c25e5 100644 --- a/ocaml/README.markdown +++ b/ocaml/README.markdown @@ -1,22 +1,22 @@ MsgPack for OCaml ============================== -OVERVIEW ------------------------------- -MessagePack(http://msgpack.org)のOCaml版ライブラリです。 -シリアライズしたものをデシリアライズすると元にもどることがCoqによって保証されています。 +See http://wiki.msgpack.org/display/MSGPACK/QuickStart+for+OCaml + + + + + + + + + + + + + + -REQUIRE ------------------------------- -* extlib http://code.google.com/p/ocaml-extlib/ -* Coq 8.3 http://coq.inria.fr -BUILD & INSTALL ------------------------------- - $ omake - $ omake install -DOCUMENT ------------------------------- -http://mzp.github.com/msgpack-ocaml/refman \ No newline at end of file diff --git a/ocaml/ocaml/.gitignore b/ocaml/ocaml/.gitignore index 3425f3f1..e60d7ce4 100644 --- a/ocaml/ocaml/.gitignore +++ b/ocaml/ocaml/.gitignore @@ -1,4 +1,2 @@ runner doc -msgpackCore.ml -msgpackCore.mli diff --git a/ocaml/ocaml/OMakefile b/ocaml/ocaml/OMakefile index 47babc35..a438b483 100644 --- a/ocaml/ocaml/OMakefile +++ b/ocaml/ocaml/OMakefile @@ -73,8 +73,8 @@ doc: mkdir -p doc ocamldoc -d doc -html msgpack.mli -install: - ocamlfind install msgpack META msgpack.cmx msgpack.cmo +install: all + ocamlfind install msgpack META *.cmo *.cmx *.cmi clean: rm -rf *.cm[iox] *.o *~ *.omc .omakedb .omakedb.lock *.cmxa *.a *.opt *.run *.annot runner msgpackCore.* diff --git a/ocaml/ocaml/msgpackCore.ml b/ocaml/ocaml/msgpackCore.ml new file mode 100644 index 00000000..4f9303b7 --- /dev/null +++ b/ocaml/ocaml/msgpackCore.ml @@ -0,0 +1,2581 @@ +let __ = let rec f _ = Obj.repr f in Obj.repr f + +(** val fst : ('a1 * 'a2) -> 'a1 **) + +let fst = function + | (x, y) -> x + +(** val snd : ('a1 * 'a2) -> 'a2 **) + +let snd = function + | (x, y) -> y + +(** val length : 'a1 list -> int **) + +let rec length = function + | [] -> 0 + | y::l' -> succ (length l') + +(** val app : 'a1 list -> 'a1 list -> 'a1 list **) + +let rec app l m = + match l with + | [] -> m + | a::l1 -> a::(app l1 m) + +(** val plus : int -> int -> int **) + +let rec plus = (+) + +(** val mult : int -> int -> int **) + +let rec mult = ( * ) + +type positive = + | XI of positive + | XO of positive + | XH + +(** val psucc : positive -> positive **) + +let rec psucc = function + | XI p -> XO (psucc p) + | XO p -> XI p + | XH -> XO XH + +(** val pplus : positive -> positive -> positive **) + +let rec pplus x y = + match x with + | XI p -> + (match y with + | XI q -> XO (pplus_carry p q) + | XO q -> XI (pplus p q) + | XH -> XO (psucc p)) + | XO p -> + (match y with + | XI q -> XI (pplus p q) + | XO q -> XO (pplus p q) + | XH -> XI p) + | XH -> + (match y with + | XI q -> XO (psucc q) + | XO q -> XI q + | XH -> XO XH) + +(** val pplus_carry : positive -> positive -> positive **) + +and pplus_carry x y = + match x with + | XI p -> + (match y with + | XI q -> XI (pplus_carry p q) + | XO q -> XO (pplus_carry p q) + | XH -> XI (psucc p)) + | XO p -> + (match y with + | XI q -> XO (pplus_carry p q) + | XO q -> XI (pplus p q) + | XH -> XO (psucc p)) + | XH -> + (match y with + | XI q -> XI (psucc q) + | XO q -> XO (psucc q) + | XH -> XI XH) + +(** val pmult_nat : positive -> int -> int **) + +let rec pmult_nat x pow2 = + match x with + | XI p -> plus pow2 (pmult_nat p (plus pow2 pow2)) + | XO p -> pmult_nat p (plus pow2 pow2) + | XH -> pow2 + +(** val nat_of_P : positive -> int **) + +let nat_of_P x = + pmult_nat x (succ 0) + +(** val p_of_succ_nat : int -> positive **) + +let rec p_of_succ_nat n0 = + (fun fO fS n -> if n=0 then fO () else fS (n-1)) + (fun _ -> XH) + (fun x -> psucc (p_of_succ_nat x)) + n0 + +(** val pmult : positive -> positive -> positive **) + +let rec pmult x y = + match x with + | XI p -> pplus y (XO (pmult p y)) + | XO p -> XO (pmult p y) + | XH -> y + +type n = + | N0 + | Npos of positive + +(** val nplus : n -> n -> n **) + +let nplus n0 m = + match n0 with + | N0 -> m + | Npos p -> (match m with + | N0 -> n0 + | Npos q -> Npos (pplus p q)) + +(** val nmult : n -> n -> n **) + +let nmult n0 m = + match n0 with + | N0 -> N0 + | Npos p -> (match m with + | N0 -> N0 + | Npos q -> Npos (pmult p q)) + +(** val nat_of_N : n -> int **) + +let nat_of_N = function + | N0 -> 0 + | Npos p -> nat_of_P p + +(** val n_of_nat : int -> n **) + +let n_of_nat n0 = + (fun fO fS n -> if n=0 then fO () else fS (n-1)) + (fun _ -> N0) + (fun n' -> Npos (p_of_succ_nat n')) + n0 + +(** val flat_map : ('a1 -> 'a2 list) -> 'a1 list -> 'a2 list **) + +let rec flat_map f = function + | [] -> [] + | x::t -> app (f x) (flat_map f t) + +(** val eucl_dev : int -> int -> (int * int) **) + +let eucl_dev = fun n m -> (m/n, m mod n) + +type ascii = + | Ascii of bool * bool * bool * bool * bool * bool * bool * bool + +(** val zero : ascii **) + +let zero = + Ascii (false, false, false, false, false, false, false, false) + +(** val one : ascii **) + +let one = + Ascii (true, false, false, false, false, false, false, false) + +(** val shift : bool -> ascii -> ascii **) + +let shift c = function + | Ascii (a1, a2, a3, a4, a5, a6, a7, a8) -> Ascii (c, a1, a2, a3, a4, a5, + a6, a7) + +(** val ascii_of_pos : positive -> ascii **) + +let ascii_of_pos = + let rec loop n0 p = + (fun fO fS n -> if n=0 then fO () else fS (n-1)) + (fun _ -> zero) + (fun n' -> + match p with + | XI p' -> shift true (loop n' p') + | XO p' -> shift false (loop n' p') + | XH -> one) + n0 + in loop (succ (succ (succ (succ (succ (succ (succ (succ 0)))))))) + +(** val ascii_of_N : n -> ascii **) + +let ascii_of_N = function + | N0 -> zero + | Npos p -> ascii_of_pos p + +(** val ascii_of_nat : int -> ascii **) + +let ascii_of_nat a = + ascii_of_N (n_of_nat a) + +(** val n_of_digits : bool list -> n **) + +let rec n_of_digits = function + | [] -> N0 + | b::l' -> + nplus (if b then Npos XH else N0) + (nmult (Npos (XO XH)) (n_of_digits l')) + +(** val n_of_ascii : ascii -> n **) + +let n_of_ascii = function + | Ascii (a0, a1, a2, a3, a4, a5, a6, a7) -> + n_of_digits (a0::(a1::(a2::(a3::(a4::(a5::(a6::(a7::[])))))))) + +(** val nat_of_ascii : ascii -> int **) + +let nat_of_ascii a = + nat_of_N (n_of_ascii a) + +(** val take : int -> 'a1 list -> 'a1 list **) + +let rec take n0 xs = + (fun fO fS n -> if n=0 then fO () else fS (n-1)) + (fun _ -> []) + (fun m -> match xs with + | [] -> [] + | x::xs0 -> x::(take m xs0)) + n0 + +(** val drop : int -> 'a1 list -> 'a1 list **) + +let rec drop n0 xs = + (fun fO fS n -> if n=0 then fO () else fS (n-1)) + (fun _ -> xs) + (fun m -> match xs with + | [] -> [] + | x::xs0 -> drop m xs0) + n0 + +(** val split_at : int -> 'a1 list -> 'a1 list * 'a1 list **) + +let split_at n0 xs = + ((take n0 xs), (drop n0 xs)) + +(** val pair : 'a1 list -> ('a1 * 'a1) list **) + +let rec pair = function + | [] -> [] + | k::l -> (match l with + | [] -> [] + | v::ys -> (k, v)::(pair ys)) + +(** val pow : int -> int **) + +let rec pow n0 = + (fun fO fS n -> if n=0 then fO () else fS (n-1)) + (fun _ -> succ 0) + (fun n' -> mult (succ (succ 0)) (pow n')) + n0 + +(** val divmod : int -> int -> (int * int) **) + +let divmod n0 m = + eucl_dev m n0 + +type ascii8 = ascii + +type ascii16 = ascii8 * ascii8 + +type ascii32 = ascii16 * ascii16 + +type ascii64 = ascii32 * ascii32 + +(** val nat_of_ascii8 : ascii -> int **) + +let nat_of_ascii8 = + nat_of_ascii + +(** val ascii8_of_nat : int -> ascii **) + +let ascii8_of_nat = + ascii_of_nat + +(** val ascii16_of_nat : int -> ascii * ascii **) + +let ascii16_of_nat a = + let (q, r) = + divmod a (pow (succ (succ (succ (succ (succ (succ (succ (succ 0))))))))) + in + ((ascii8_of_nat q), (ascii8_of_nat r)) + +(** val nat_of_ascii16 : ascii16 -> int **) + +let nat_of_ascii16 = function + | (a1, a2) -> + plus + (mult (nat_of_ascii8 a1) + (pow (succ (succ (succ (succ (succ (succ (succ (succ 0)))))))))) + (nat_of_ascii8 a2) + +(** val ascii32_of_nat : int -> (ascii * ascii) * (ascii * ascii) **) + +let ascii32_of_nat a = + let (q, r) = + divmod a + (pow (succ (succ (succ (succ (succ (succ (succ (succ (succ (succ (succ + (succ (succ (succ (succ (succ 0))))))))))))))))) + in + ((ascii16_of_nat q), (ascii16_of_nat r)) + +(** val nat_of_ascii32 : ascii32 -> int **) + +let nat_of_ascii32 = function + | (a1, a2) -> + plus + (mult (nat_of_ascii16 a1) + (pow (succ (succ (succ (succ (succ (succ (succ (succ (succ (succ + (succ (succ (succ (succ (succ (succ 0)))))))))))))))))) + (nat_of_ascii16 a2) + +(** val list_of_ascii8 : ascii8 -> ascii8 list **) + +let list_of_ascii8 x = + x::[] + +(** val list_of_ascii16 : ascii16 -> ascii8 list **) + +let list_of_ascii16 = function + | (x1, x2) -> app (list_of_ascii8 x1) (list_of_ascii8 x2) + +(** val list_of_ascii32 : ascii32 -> ascii8 list **) + +let list_of_ascii32 = function + | (x1, x2) -> app (list_of_ascii16 x1) (list_of_ascii16 x2) + +(** val list_of_ascii64 : ascii64 -> ascii8 list **) + +let list_of_ascii64 = function + | (x1, x2) -> app (list_of_ascii32 x1) (list_of_ascii32 x2) + +type object0 = + | Bool of bool + | Nil + | PFixnum of ascii8 + | NFixnum of ascii8 + | Uint8 of ascii8 + | Uint16 of ascii16 + | Uint32 of ascii32 + | Uint64 of ascii64 + | Int8 of ascii8 + | Int16 of ascii16 + | Int32 of ascii32 + | Int64 of ascii64 + | Float of ascii32 + | Double of ascii64 + | FixRaw of ascii8 list + | Raw16 of ascii8 list + | Raw32 of ascii8 list + | FixArray of object0 list + | Array16 of object0 list + | Array32 of object0 list + | FixMap of (object0 * object0) list + | Map16 of (object0 * object0) list + | Map32 of (object0 * object0) list + +(** val atat : ('a1 -> 'a2) -> 'a1 -> 'a2 **) + +let atat f x = + f x + +(** val serialize : object0 -> ascii8 list **) + +let rec serialize = function + | Bool b -> + if b + then (Ascii (true, true, false, false, false, false, true, true))::[] + else (Ascii (false, true, false, false, false, false, true, true))::[] + | Nil -> (Ascii (false, false, false, false, false, false, true, true))::[] + | PFixnum a -> + let Ascii (b1, b2, b3, b4, b5, b6, b7, b) = a in + (Ascii (b1, b2, b3, b4, b5, b6, b7, false))::[] + | NFixnum a -> + let Ascii (b1, b2, b3, b4, b5, b, b0, b6) = a in + (Ascii (b1, b2, b3, b4, b5, true, true, true))::[] + | Uint8 c -> (Ascii (false, false, true, true, false, false, true, + true))::(list_of_ascii8 c) + | Uint16 c -> (Ascii (true, false, true, true, false, false, true, + true))::(list_of_ascii16 c) + | Uint32 c -> (Ascii (false, true, true, true, false, false, true, + true))::(list_of_ascii32 c) + | Uint64 c -> (Ascii (true, true, true, true, false, false, true, + true))::(list_of_ascii64 c) + | Int8 c -> (Ascii (false, false, false, false, true, false, true, + true))::(list_of_ascii8 c) + | Int16 c -> (Ascii (true, false, false, false, true, false, true, + true))::(list_of_ascii16 c) + | Int32 c -> (Ascii (false, true, false, false, true, false, true, + true))::(list_of_ascii32 c) + | Int64 c -> (Ascii (true, true, false, false, true, false, true, + true))::(list_of_ascii64 c) + | Float c -> (Ascii (false, true, false, true, false, false, true, + true))::(list_of_ascii32 c) + | Double c -> (Ascii (true, true, false, true, false, false, true, + true))::(list_of_ascii64 c) + | FixRaw xs -> + let Ascii (b1, b2, b3, b4, b5, b, b0, b6) = + atat ascii8_of_nat (length xs) + in + (Ascii (b1, b2, b3, b4, b5, true, false, true))::xs + | Raw16 xs -> + let (s1, s2) = atat ascii16_of_nat (length xs) in + (Ascii (false, true, false, true, true, false, true, + true))::(s1::(s2::xs)) + | Raw32 xs -> + let (p, p0) = atat ascii32_of_nat (length xs) in + let (s1, s2) = p in + let (s3, s4) = p0 in + (Ascii (true, true, false, true, true, false, true, + true))::(s1::(s2::(s3::(s4::xs)))) + | FixArray xs -> + let ys = flat_map serialize xs in + let Ascii (b1, b2, b3, b4, b, b0, b5, b6) = + atat ascii8_of_nat (length xs) + in + (Ascii (b1, b2, b3, b4, true, false, false, true))::ys + | Array16 xs -> + let ys = flat_map serialize xs in + let (s1, s2) = ascii16_of_nat (length xs) in + (Ascii (false, false, true, true, true, false, true, + true))::(s1::(s2::ys)) + | Array32 xs -> + let ys = flat_map serialize xs in + let (p, p0) = atat ascii32_of_nat (length xs) in + let (s1, s2) = p in + let (s3, s4) = p0 in + (Ascii (true, false, true, true, true, false, true, + true))::(s1::(s2::(s3::(s4::ys)))) + | FixMap xs -> + let ys = + flat_map (fun p -> app (serialize (fst p)) (serialize (snd p))) xs + in + let Ascii (b1, b2, b3, b4, b, b0, b5, b6) = + atat ascii8_of_nat (length xs) + in + (Ascii (b1, b2, b3, b4, false, false, false, true))::ys + | Map16 xs -> + let ys = + flat_map (fun p -> app (serialize (fst p)) (serialize (snd p))) xs + in + let (s1, s2) = ascii16_of_nat (length xs) in + (Ascii (false, true, true, true, true, false, true, + true))::(s1::(s2::ys)) + | Map32 xs -> + let ys = + flat_map (fun p -> app (serialize (fst p)) (serialize (snd p))) xs + in + let (p, p0) = atat ascii32_of_nat (length xs) in + let (s1, s2) = p in + let (s3, s4) = p0 in + (Ascii (true, true, true, true, true, false, true, + true))::(s1::(s2::(s3::(s4::ys)))) + +(** val compact : object0 list -> ascii8 list **) + +let compact xs = + flat_map (fun x -> match x with + | FixRaw xs0 -> xs0 + | _ -> []) xs + +(** val deserialize : int -> ascii8 list -> object0 list **) + +let rec deserialize n0 xs = + (fun fO fS n -> if n=0 then fO () else fS (n-1)) + (fun _ -> + match xs with + | [] -> [] + | a::ys -> + let Ascii (b1, b2, b3, b4, b5, b6, b7, b) = a in + if b1 + then if b2 + then if b3 + then if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + s1::l -> + (match l with + | + [] -> [] + | + s2::l0 -> + (match l0 with + | + [] -> [] + | + s3::l1 -> + (match l1 with + | + [] -> [] + | + s4::ys0 -> + let n1 = + nat_of_ascii32 ((s1, s2), + (s3, s4)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys0) + in + (Map32 (pair zs))::ws)))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::l0 -> + (match l0 with + | + [] -> [] + | + c3::l1 -> + (match l1 with + | + [] -> [] + | + c4::l2 -> + (match l2 with + | + [] -> [] + | + c5::l3 -> + (match l3 with + | + [] -> [] + | + c6::l4 -> + (match l4 with + | + [] -> [] + | + c7::l5 -> + (match l5 with + | + [] -> [] + | + c8::ys0 -> (Uint64 (((c1, + c2), (c3, c4)), ((c5, c6), + (c7, + c8)))):: + (deserialize 0 ys0))))))))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + s1::l -> + (match l with + | + [] -> [] + | + s2::l0 -> + (match l0 with + | + [] -> [] + | + s3::l1 -> + (match l1 with + | + [] -> [] + | + s4::ys0 -> + let n1 = + nat_of_ascii32 ((s1, s2), + (s3, s4)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys0) + in + (Raw32 (compact zs))::ws)))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::l0 -> + (match l0 with + | + [] -> [] + | + c3::l1 -> + (match l1 with + | + [] -> [] + | + c4::l2 -> + (match l2 with + | + [] -> [] + | + c5::l3 -> + (match l3 with + | + [] -> [] + | + c6::l4 -> + (match l4 with + | + [] -> [] + | + c7::l5 -> + (match l5 with + | + [] -> [] + | + c8::ys0 -> (Double (((c1, + c2), (c3, c4)), ((c5, c6), + (c7, + c8)))):: + (deserialize 0 ys0))))))))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::l0 -> + (match l0 with + | + [] -> [] + | + c3::l1 -> + (match l1 with + | + [] -> [] + | + c4::l2 -> + (match l2 with + | + [] -> [] + | + c5::l3 -> + (match l3 with + | + [] -> [] + | + c6::l4 -> + (match l4 with + | + [] -> [] + | + c7::l5 -> + (match l5 with + | + [] -> [] + | + c8::ys0 -> (Int64 (((c1, + c2), (c3, c4)), ((c5, c6), + (c7, + c8)))):: + (deserialize 0 ys0))))))))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (Bool + true):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b3 + then if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + s1::l -> + (match l with + | + [] -> [] + | + s2::l0 -> + (match l0 with + | + [] -> [] + | + s3::l1 -> + (match l1 with + | + [] -> [] + | + s4::ys0 -> + let n1 = + nat_of_ascii32 ((s1, s2), + (s3, s4)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys0) + in + (Array32 zs)::ws)))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::ys0 -> (Uint16 (c1, + c2)):: + (deserialize 0 ys0))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::ys0 -> (Int16 (c1, + c2)):: + (deserialize 0 ys0))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b2 + then if b3 + then if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + s1::l -> + (match l with + | + [] -> [] + | + s2::ys0 -> + let n1 = + nat_of_ascii16 (s1, s2) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys0) + in + (Map16 (pair zs))::ws)) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::l0 -> + (match l0 with + | + [] -> [] + | + c3::l1 -> + (match l1 with + | + [] -> [] + | + c4::ys0 -> (Uint32 ((c1, + c2), (c3, + c4))):: + (deserialize 0 ys0))))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + s1::l -> + (match l with + | + [] -> [] + | + s2::ys0 -> + let n1 = + nat_of_ascii16 (s1, s2) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys0) + in + (Raw16 (compact zs))::ws)) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::l0 -> + (match l0 with + | + [] -> [] + | + c3::l1 -> + (match l1 with + | + [] -> [] + | + c4::ys0 -> (Float ((c1, + c2), (c3, + c4))):: + (deserialize 0 ys0))))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::l -> + (match l with + | + [] -> [] + | + c2::l0 -> + (match l0 with + | + [] -> [] + | + c3::l1 -> + (match l1 with + | + [] -> [] + | + c4::ys0 -> (Int32 ((c1, + c2), (c3, + c4))):: + (deserialize 0 ys0))))) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (Bool + false):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b3 + then if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + s1::l -> + (match l with + | + [] -> [] + | + s2::ys0 -> + let n1 = + nat_of_ascii16 (s1, s2) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys0) + in + (Array16 zs)::ws)) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::ys0 -> (Uint8 + c1):: + (deserialize 0 ys0)) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b4 + then if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then [] + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b5 + then if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then (match ys with + | + [] -> [] + | + c1::ys0 -> (Int8 + c1):: + (deserialize 0 ys0)) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize 0 ys) + in + (FixArray zs)::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b6 + then if b7 + then if b + then (NFixnum (Ascii (b1, b2, + b3, b4, b5, true, true, + true))):: + (deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, b5, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at n1) + (deserialize n1 ys) + in + (FixRaw (compact zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b7 + then if b + then Nil::(deserialize 0 ys) + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys) + else if b + then let n1 = + nat_of_ascii8 (Ascii (b1, + b2, b3, b4, false, false, + false, false)) + in + let ( + zs, ws) = + atat + (split_at + (mult (succ (succ 0)) n1)) + (deserialize 0 ys) + in + (FixMap (pair zs))::ws + else (PFixnum (Ascii (b1, b2, + b3, b4, b5, b6, b7, + false))):: + (deserialize 0 ys)) + (fun m -> + match xs with + | [] -> [] + | y::ys -> (FixRaw (y::[]))::(deserialize m ys)) + n0 + diff --git a/ocaml/ocaml/msgpackCore.mli b/ocaml/ocaml/msgpackCore.mli new file mode 100644 index 00000000..914b4d64 --- /dev/null +++ b/ocaml/ocaml/msgpackCore.mli @@ -0,0 +1,141 @@ +val fst : ('a1 * 'a2) -> 'a1 + +val snd : ('a1 * 'a2) -> 'a2 + +val length : 'a1 list -> int + +val app : 'a1 list -> 'a1 list -> 'a1 list + +val plus : int -> int -> int + +val mult : int -> int -> int + +type positive = + | XI of positive + | XO of positive + | XH + +val psucc : positive -> positive + +val pplus : positive -> positive -> positive + +val pplus_carry : positive -> positive -> positive + +val pmult_nat : positive -> int -> int + +val nat_of_P : positive -> int + +val p_of_succ_nat : int -> positive + +val pmult : positive -> positive -> positive + +type n = + | N0 + | Npos of positive + +val nplus : n -> n -> n + +val nmult : n -> n -> n + +val nat_of_N : n -> int + +val n_of_nat : int -> n + +val flat_map : ('a1 -> 'a2 list) -> 'a1 list -> 'a2 list + +val eucl_dev : int -> int -> (int * int) + +type ascii = + | Ascii of bool * bool * bool * bool * bool * bool * bool * bool + +val zero : ascii + +val one : ascii + +val shift : bool -> ascii -> ascii + +val ascii_of_pos : positive -> ascii + +val ascii_of_N : n -> ascii + +val ascii_of_nat : int -> ascii + +val n_of_digits : bool list -> n + +val n_of_ascii : ascii -> n + +val nat_of_ascii : ascii -> int + +val take : int -> 'a1 list -> 'a1 list + +val drop : int -> 'a1 list -> 'a1 list + +val split_at : int -> 'a1 list -> 'a1 list * 'a1 list + +val pair : 'a1 list -> ('a1 * 'a1) list + +val pow : int -> int + +val divmod : int -> int -> (int * int) + +type ascii8 = ascii + +type ascii16 = ascii8 * ascii8 + +type ascii32 = ascii16 * ascii16 + +type ascii64 = ascii32 * ascii32 + +val nat_of_ascii8 : ascii -> int + +val ascii8_of_nat : int -> ascii + +val ascii16_of_nat : int -> ascii * ascii + +val nat_of_ascii16 : ascii16 -> int + +val ascii32_of_nat : int -> (ascii * ascii) * (ascii * ascii) + +val nat_of_ascii32 : ascii32 -> int + +val list_of_ascii8 : ascii8 -> ascii8 list + +val list_of_ascii16 : ascii16 -> ascii8 list + +val list_of_ascii32 : ascii32 -> ascii8 list + +val list_of_ascii64 : ascii64 -> ascii8 list + +type object0 = + | Bool of bool + | Nil + | PFixnum of ascii8 + | NFixnum of ascii8 + | Uint8 of ascii8 + | Uint16 of ascii16 + | Uint32 of ascii32 + | Uint64 of ascii64 + | Int8 of ascii8 + | Int16 of ascii16 + | Int32 of ascii32 + | Int64 of ascii64 + | Float of ascii32 + | Double of ascii64 + | FixRaw of ascii8 list + | Raw16 of ascii8 list + | Raw32 of ascii8 list + | FixArray of object0 list + | Array16 of object0 list + | Array32 of object0 list + | FixMap of (object0 * object0) list + | Map16 of (object0 * object0) list + | Map32 of (object0 * object0) list + +val atat : ('a1 -> 'a2) -> 'a1 -> 'a2 + +val serialize : object0 -> ascii8 list + +val compact : object0 list -> ascii8 list + +val deserialize : int -> ascii8 list -> object0 list + From 86d30fe5718e8809f6eb736d9e995cf881599e61 Mon Sep 17 00:00:00 2001 From: Hideyuki Tanaka Date: Mon, 4 Apr 2011 23:33:02 +0900 Subject: [PATCH 36/53] haskell: reduce dependency of template-haskell --- haskell/msgpack.cabal | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/haskell/msgpack.cabal b/haskell/msgpack.cabal index aef55f94..02f1ec16 100644 --- a/haskell/msgpack.cabal +++ b/haskell/msgpack.cabal @@ -1,5 +1,5 @@ Name: msgpack -Version: 0.6.1 +Version: 0.6.1.1 Synopsis: A Haskell implementation of MessagePack Description: A Haskell implementation of MessagePack @@ -29,7 +29,7 @@ Library binary >= 0.5.0 && < 0.5.1, data-binary-ieee754 >= 0.4 && < 0.5, deepseq >= 1.1 && <1.2, - template-haskell >= 2.5 && < 2.6 + template-haskell >= 2.4 && < 2.6 Ghc-options: -Wall Hs-source-dirs: src From 85e90aa81e48ea5056c0f0292041ec11417336f2 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Tue, 5 Apr 2011 00:51:53 +0900 Subject: [PATCH 37/53] java: Improved DefaultTemplate.java. It allows displaying details of exception messages --- .../java/org/msgpack/template/DefaultTemplate.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/src/main/java/org/msgpack/template/DefaultTemplate.java b/java/src/main/java/org/msgpack/template/DefaultTemplate.java index 7784eb27..45d84f3f 100644 --- a/java/src/main/java/org/msgpack/template/DefaultTemplate.java +++ b/java/src/main/java/org/msgpack/template/DefaultTemplate.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 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,14 +43,14 @@ public class DefaultTemplate implements Template { public void pack(Packer pk, Object target) throws IOException { if(messagePackable) { if(target == null) { - throw new MessageTypeException("target is null."); + throw new MessageTypeException("target is null: " + target.getClass().getName()); } ((MessagePackable)target).messagePack(pk); return; } Template tmpl = TemplateRegistry.tryLookup(lookupType); if(tmpl == this || tmpl == null) { - throw new MessageTypeException(); + throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName()); } tmpl.pack(pk, target); } @@ -69,7 +69,7 @@ public class DefaultTemplate implements Template { } Template tmpl = TemplateRegistry.tryLookup(lookupType); if(tmpl == this || tmpl == null) { - throw new MessageTypeException(); + throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName()); } return tmpl.unpack(pac, to); } @@ -88,7 +88,7 @@ public class DefaultTemplate implements Template { } Template tmpl = TemplateRegistry.tryLookup(lookupType); if(tmpl == this || tmpl == null) { - throw new MessageTypeException(); + throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName()); } return tmpl.convert(from, to); } From 337cc9fa7871f52315aaffdbd3b52786400b098b Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Tue, 5 Apr 2011 01:27:51 +0900 Subject: [PATCH 38/53] java: Fixed a bug that NullPointerException occurs within DefaultTemplate.java --- java/src/main/java/org/msgpack/template/DefaultTemplate.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/src/main/java/org/msgpack/template/DefaultTemplate.java b/java/src/main/java/org/msgpack/template/DefaultTemplate.java index 45d84f3f..f94e2f13 100644 --- a/java/src/main/java/org/msgpack/template/DefaultTemplate.java +++ b/java/src/main/java/org/msgpack/template/DefaultTemplate.java @@ -43,7 +43,7 @@ public class DefaultTemplate implements Template { public void pack(Packer pk, Object target) throws IOException { if(messagePackable) { if(target == null) { - throw new MessageTypeException("target is null: " + target.getClass().getName()); + throw new MessageTypeException("target is null."); } ((MessagePackable)target).messagePack(pk); return; From 9c4812f4d400be129f0dc653301ab407b673e089 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Tue, 5 Apr 2011 03:30:43 +0900 Subject: [PATCH 39/53] java: Fixed RawType's bug that hash values of same byte arrays (raw data) are different --- java/src/main/java/org/msgpack/object/RawType.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/src/main/java/org/msgpack/object/RawType.java b/java/src/main/java/org/msgpack/object/RawType.java index 26f6e0d9..f6866c46 100644 --- a/java/src/main/java/org/msgpack/object/RawType.java +++ b/java/src/main/java/org/msgpack/object/RawType.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -79,7 +79,7 @@ public class RawType extends MessagePackObject { @Override public int hashCode() { - return bytes.hashCode(); + return Arrays.hashCode(bytes); } @Override From 233ad3aaffad720ff2e8e4d320c8f79586edfe7f Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Tue, 5 Apr 2011 03:34:11 +0900 Subject: [PATCH 40/53] java: Updated several property files in .settings --- java/.settings/org.eclipse.jdt.core.prefs | 11 ++++++----- java/.settings/org.maven.ide.eclipse.prefs | 9 +++++++++ 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 java/.settings/org.maven.ide.eclipse.prefs diff --git a/java/.settings/org.eclipse.jdt.core.prefs b/java/.settings/org.eclipse.jdt.core.prefs index c75ad473..c2f9169f 100755 --- a/java/.settings/org.eclipse.jdt.core.prefs +++ b/java/.settings/org.eclipse.jdt.core.prefs @@ -1,5 +1,6 @@ -#Mon Apr 19 22:18:48 JST 2010 -org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 -eclipse.preferences.version=1 -org.eclipse.jdt.core.compiler.source=1.6 -org.eclipse.jdt.core.compiler.compliance=1.6 +#Mon Sep 27 07:43:48 JST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/java/.settings/org.maven.ide.eclipse.prefs b/java/.settings/org.maven.ide.eclipse.prefs new file mode 100644 index 00000000..6d8de378 --- /dev/null +++ b/java/.settings/org.maven.ide.eclipse.prefs @@ -0,0 +1,9 @@ +#Mon Sep 27 07:43:27 JST 2010 +activeProfiles= +eclipse.preferences.version=1 +fullBuildGoals=process-test-resources +includeModules=false +resolveWorkspaceProjects=true +resourceFilterGoals=process-resources resources\:testResources +skipCompilerPlugin=true +version=1 From 03aa736199f33fe88c6c64b288fa7fe713916f8e Mon Sep 17 00:00:00 2001 From: Watabiki Naoya Date: Tue, 5 Apr 2011 23:26:53 +0900 Subject: [PATCH 41/53] java: update BigDecimalTemplate, TestPackConvert and TestPackUnpack --- .../msgpack/template/BigDecimalTemplate.java | 6 +- .../org/msgpack/template/TestPackConvert.java | 85 ++++++++++++++++++ .../org/msgpack/template/TestPackUnpack.java | 87 +++++++++++++++++++ 3 files changed, 177 insertions(+), 1 deletion(-) diff --git a/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java b/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java index e8265a5d..7958f825 100644 --- a/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java +++ b/java/src/main/java/org/msgpack/template/BigDecimalTemplate.java @@ -30,7 +30,11 @@ public class BigDecimalTemplate implements Template { @Override public void pack(Packer pk, Object target) throws IOException { BigDecimal temp = (BigDecimal) target; - pk.packString(temp.toString()); + try { + pk.packString(temp.toString()); + } catch (NullPointerException e) { + throw new MessageTypeException("target is null.", e); + } } @Override diff --git a/java/src/test/java/org/msgpack/template/TestPackConvert.java b/java/src/test/java/org/msgpack/template/TestPackConvert.java index 9524b289..f69b0ce2 100644 --- a/java/src/test/java/org/msgpack/template/TestPackConvert.java +++ b/java/src/test/java/org/msgpack/template/TestPackConvert.java @@ -1,6 +1,7 @@ package org.msgpack.template; import java.io.ByteArrayOutputStream; +import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -741,4 +742,88 @@ public class TestPackConvert extends TestCase { Collection dst = (Collection) tmpl.convert(obj, null); assertEquals(src, dst); } + + @Test + public void testBigDecimal() throws Exception { + // String + _testBigDecimal(new BigDecimal("0")); + _testBigDecimal(new BigDecimal("-0")); + _testBigDecimal(new BigDecimal("1")); + _testBigDecimal(new BigDecimal("-1")); + _testBigDecimal(new BigDecimal("123.456")); + _testBigDecimal(new BigDecimal("-123.456")); + _testBigDecimal(new BigDecimal("0.123456789")); + _testBigDecimal(new BigDecimal("-0.123456789")); + + // char array + char[] zero = {'0'}; + _testBigDecimal(new BigDecimal(zero)); + char[] one = {'1'}; + _testBigDecimal(new BigDecimal(one)); + char[] minusOne = {'-', '1'}; + _testBigDecimal(new BigDecimal(minusOne)); + char[] decimal = {'1', '2', '3', '.', '4', '5', '6'}; + _testBigDecimal(new BigDecimal(decimal)); + char[] minusDecimal = {'-', '1', '2', '3', '.', '4', '5', '6'}; + _testBigDecimal(new BigDecimal(minusDecimal)); + char[] oneOrLessDecimal = {'0', '.', '1', '2', '3'}; + _testBigDecimal(new BigDecimal(oneOrLessDecimal)); + char[] minusOneOrLessDecimal = {'-', '0', '.', '1', '2', '3'}; + _testBigDecimal(new BigDecimal(minusOneOrLessDecimal)); + + // int + _testBigDecimal(new BigDecimal(0)); + _testBigDecimal(new BigDecimal(-0)); + _testBigDecimal(new BigDecimal(1)); + _testBigDecimal(new BigDecimal(-1)); + _testBigDecimal(new BigDecimal(Integer.MAX_VALUE)); + _testBigDecimal(new BigDecimal(Integer.MIN_VALUE)); + + // double + _testBigDecimal(new BigDecimal((double) 0.0)); + _testBigDecimal(new BigDecimal((double) -0.0)); + _testBigDecimal(new BigDecimal((double) 1.0)); + _testBigDecimal(new BigDecimal((double) -1.0)); + _testBigDecimal(new BigDecimal((double) 123.456)); + _testBigDecimal(new BigDecimal((double) -123.456)); + _testBigDecimal(new BigDecimal((double) 0.123456789)); + _testBigDecimal(new BigDecimal((double) -0.123456789)); + _testBigDecimal(new BigDecimal(Double.MAX_VALUE)); + _testBigDecimal(new BigDecimal(Double.MIN_VALUE)); + } + + static void _testBigDecimal(BigDecimal src) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Template tmpl = BigDecimalTemplate.getInstance(); + tmpl.pack(new Packer(out), src); + MessagePackObject obj = Util.unpackOne(out.toByteArray()); + BigDecimal dst = (BigDecimal) tmpl.convert(obj, null); + assertEquals(src, dst); + } + + @Test + public void testNullBigDecimal() throws Exception { + BigDecimal src = null; + Template tmpl = BigDecimalTemplate.getInstance(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Packer packer = new Packer(out); + try { + tmpl.pack(packer, src); + fail(); + } catch (Exception e) { + assertTrue(e instanceof MessageTypeException); + } + packer.pack(src); + MessagePackObject obj = Util.unpackOne(out.toByteArray()); + try { + tmpl.convert(obj, null); + fail(); + } catch (Exception e) { + assertTrue(e instanceof MessageTypeException); + } + obj = Util.unpackOne(out.toByteArray()); + tmpl = new NullableTemplate(BigDecimalTemplate.getInstance()); + BigDecimal dst = (BigDecimal) tmpl.convert(obj, null); + assertEquals(src, dst); + } } diff --git a/java/src/test/java/org/msgpack/template/TestPackUnpack.java b/java/src/test/java/org/msgpack/template/TestPackUnpack.java index 1fe92b09..0855d986 100644 --- a/java/src/test/java/org/msgpack/template/TestPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestPackUnpack.java @@ -2,6 +2,7 @@ package org.msgpack.template; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; +import java.math.BigDecimal; import java.math.BigInteger; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -768,4 +769,90 @@ public class TestPackUnpack extends TestCase { Collection dst = (Collection) tmpl.unpack(unpacker, null); assertEquals(src, dst); } + + @Test + public void testBigDecimal() throws Exception { + // String + _testBigDecimal(new BigDecimal("0")); + _testBigDecimal(new BigDecimal("-0")); + _testBigDecimal(new BigDecimal("1")); + _testBigDecimal(new BigDecimal("-1")); + _testBigDecimal(new BigDecimal("123.456")); + _testBigDecimal(new BigDecimal("-123.456")); + _testBigDecimal(new BigDecimal("0.123456789")); + _testBigDecimal(new BigDecimal("-0.123456789")); + + // char array + char[] zero = {'0'}; + _testBigDecimal(new BigDecimal(zero)); + char[] one = {'1'}; + _testBigDecimal(new BigDecimal(one)); + char[] minusOne = {'-', '1'}; + _testBigDecimal(new BigDecimal(minusOne)); + char[] decimal = {'1', '2', '3', '.', '4', '5', '6'}; + _testBigDecimal(new BigDecimal(decimal)); + char[] minusDecimal = {'-', '1', '2', '3', '.', '4', '5', '6'}; + _testBigDecimal(new BigDecimal(minusDecimal)); + char[] oneOrLessDecimal = {'0', '.', '1', '2', '3'}; + _testBigDecimal(new BigDecimal(oneOrLessDecimal)); + char[] minusOneOrLessDecimal = {'-', '0', '.', '1', '2', '3'}; + _testBigDecimal(new BigDecimal(minusOneOrLessDecimal)); + + // int + _testBigDecimal(new BigDecimal(0)); + _testBigDecimal(new BigDecimal(-0)); + _testBigDecimal(new BigDecimal(1)); + _testBigDecimal(new BigDecimal(-1)); + _testBigDecimal(new BigDecimal(Integer.MAX_VALUE)); + _testBigDecimal(new BigDecimal(Integer.MIN_VALUE)); + + // double + _testBigDecimal(new BigDecimal((double) 0.0)); + _testBigDecimal(new BigDecimal((double) -0.0)); + _testBigDecimal(new BigDecimal((double) 1.0)); + _testBigDecimal(new BigDecimal((double) -1.0)); + _testBigDecimal(new BigDecimal((double) 123.456)); + _testBigDecimal(new BigDecimal((double) -123.456)); + _testBigDecimal(new BigDecimal((double) 0.123456789)); + _testBigDecimal(new BigDecimal((double) -0.123456789)); + _testBigDecimal(new BigDecimal(Double.MAX_VALUE)); + _testBigDecimal(new BigDecimal(Double.MIN_VALUE)); + } + + static void _testBigDecimal(BigDecimal src) throws Exception { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Template tmpl = BigDecimalTemplate.getInstance(); + tmpl.pack(new Packer(out), src); + ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray()); + BigDecimal dst = (BigDecimal) tmpl.unpack(new Unpacker(in), null); + assertEquals(src, dst); + } + + @Test + public void testNullBigDecimal() throws Exception { + BigDecimal src = null; + Template tmpl = BigDecimalTemplate.getInstance(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + Packer packer = new Packer(out); + try { + tmpl.pack(packer, src); + fail(); + } catch (Exception e) { + assertTrue(e instanceof MessageTypeException); + } + packer.pack(src); + byte[] bytes = out.toByteArray(); + Unpacker unpacker = new Unpacker(); + try { + unpacker.wrap(bytes); + tmpl.unpack(unpacker, null); + fail(); + } catch (Exception e) { + assertTrue(e instanceof MessageTypeException); + } + unpacker.wrap(bytes); + tmpl = new NullableTemplate(BigDecimalTemplate.getInstance()); + BigDecimal dst = (BigDecimal) tmpl.unpack(unpacker, null); + assertEquals(src, dst); + } } From c1c25c455cdf771b2451c8fa7f7ead057393f5ac Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Wed, 6 Apr 2011 08:52:14 +0900 Subject: [PATCH 42/53] scala: Modified pom.xml. I changed version of 'MessagePack for Java' from 0.5.1-devel to 0.5.2-SNAPSHOT --- scala/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scala/pom.xml b/scala/pom.xml index b6a14f2c..7ec8f3e9 100644 --- a/scala/pom.xml +++ b/scala/pom.xml @@ -68,7 +68,7 @@ org.msgpack msgpack - 0.5.2-SNAPSHOT + 0.5.1-devel From dfaa28147693126422e41752c756f411cde0449d Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Thu, 7 Apr 2011 00:38:21 +0900 Subject: [PATCH 43/53] java: Fixed TemplateClassWriter.java but, it doesn't work. --- .../msgpack/template/TemplateClassWriter.java | 47 ++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/java/src/main/java/org/msgpack/template/TemplateClassWriter.java b/java/src/main/java/org/msgpack/template/TemplateClassWriter.java index 2ead9048..157c242b 100644 --- a/java/src/main/java/org/msgpack/template/TemplateClassWriter.java +++ b/java/src/main/java/org/msgpack/template/TemplateClassWriter.java @@ -17,12 +17,55 @@ // package org.msgpack.template; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class TemplateClassWriter { + private static final Logger LOG = LoggerFactory.getLogger(TemplateClassWriter.class); + public static void write(Class target, String directoryName) { - if(target.isEnum()) { + if (target.isEnum()) { throw new UnsupportedOperationException("Not supported yet."); } else { - TemplateBuilder.writeClass(target, directoryName); + //TemplateBuilder.writeClass(target, directoryName); + } + LOG.info("finished writing .class file of template class for " + target.getName()); + } + + private String directoryName; + + private String[] classNames; + + private TemplateClassWriter() { + } + + private void parseOpts(final String[] args) {// TODO + if (args.length == 0) { + usage(); } } + + private void usage() {// TODO + System.err.println("java org.msgpack.template.TemplateClassWriter "); + System.err.println(""); + } + + private void writeTemplateClasses() { + ClassLoader cl = this.getClass().getClassLoader();// TODO + for (String className : classNames) { + Class origClass = null; + try { + origClass = cl.loadClass(className); + } catch (ClassNotFoundException e) { + throw new TemplateBuildException(e); + } + write(origClass, directoryName); + } + } + + public static void main(final String[] args) throws Exception { + TemplateClassWriter writer = new TemplateClassWriter(); + writer.parseOpts(args); + writer.writeTemplateClasses(); + } } From 9d4db8498776d574616c45556d247dc29c2adfc7 Mon Sep 17 00:00:00 2001 From: FURUHASHI Sadayuki Date: Thu, 7 Apr 2011 22:32:59 +0900 Subject: [PATCH 44/53] MSGPACK-4 BufferedUnpackerImpl.unpackLong: more(4)+advance(4) -> more(5)+advance(5) --- java/src/main/java/org/msgpack/BufferedUnpackerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java b/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java index 406fff73..36b6a59c 100644 --- a/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java +++ b/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java @@ -215,10 +215,10 @@ abstract class BufferedUnpackerImpl extends UnpackerImpl { advance(3); return (long)castBuffer.getShort(0); case 0xd2: // signed int 32 - more(4); + more(5); castBuffer.rewind(); castBuffer.put(buffer, offset+1, 4); - advance(4); + advance(5); return (long)castBuffer.getInt(0); case 0xd3: // signed int 64 more(9); From 983ae0c5a2a5c67b5a7e20d9489bad0bc8ab2be0 Mon Sep 17 00:00:00 2001 From: FURUHASHI Sadayuki Date: Thu, 7 Apr 2011 23:21:30 +0900 Subject: [PATCH 45/53] MSGPACK-4 BufferedUnapckerImpl.unpackInt: more(4)+advance(4) -> more(5)+advance(5) --- java/src/main/java/org/msgpack/BufferedUnpackerImpl.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java b/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java index 36b6a59c..30637a1a 100644 --- a/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java +++ b/java/src/main/java/org/msgpack/BufferedUnpackerImpl.java @@ -146,10 +146,10 @@ abstract class BufferedUnpackerImpl extends UnpackerImpl { advance(3); return (int)castBuffer.getShort(0); case 0xd2: // signed int 32 - more(4); + more(5); castBuffer.rewind(); castBuffer.put(buffer, offset+1, 4); - advance(4); + advance(5); return (int)castBuffer.getInt(0); case 0xd3: // signed int 64 more(9); From b50ff920f08bc3f21d72994ab55ecac6266bdf5b Mon Sep 17 00:00:00 2001 From: FURUHASHI Sadayuki Date: Thu, 7 Apr 2011 23:21:56 +0900 Subject: [PATCH 46/53] MSGPACK-5 added test cases for Unpacker.unpackXxx() methods --- java/src/test/java/org/msgpack/TestCases.java | 174 +++++++++++++++++- 1 file changed, 172 insertions(+), 2 deletions(-) diff --git a/java/src/test/java/org/msgpack/TestCases.java b/java/src/test/java/org/msgpack/TestCases.java index c368972f..38c1d1c2 100644 --- a/java/src/test/java/org/msgpack/TestCases.java +++ b/java/src/test/java/org/msgpack/TestCases.java @@ -2,6 +2,7 @@ package org.msgpack; import java.io.*; import java.util.*; +import java.math.BigInteger; import org.junit.Test; import static org.junit.Assert.*; @@ -20,7 +21,7 @@ public class TestCases { } @Test - public void testCases() throws Exception { + public void testDynamicType() throws Exception { Unpacker pac = new Unpacker(); Unpacker pac_compact = new Unpacker(); @@ -28,13 +29,182 @@ public class TestCases { feedFile(pac_compact, "src/test/resources/cases_compact.mpac"); UnpackResult result = new UnpackResult(); + UnpackResult result_compact = new UnpackResult(); while(pac.next(result)) { - UnpackResult result_compact = new UnpackResult(); assertTrue( pac_compact.next(result_compact) ); assertTrue( result.getData().equals(result_compact.getData()) ); } assertFalse( pac_compact.next(result) ); } + + @Test + public void testDirectConversion() throws Exception { + Unpacker pac = new Unpacker(); + Unpacker pac_compact = new Unpacker(); + + feedFile(pac, "src/test/resources/cases.mpac"); + feedFile(pac_compact, "src/test/resources/cases_compact.mpac"); + + UnpackResult result_compact = new UnpackResult(); + while(pac_compact.next(result_compact)) { + MessagePackObject obj = result_compact.getData(); + testDirectConversionRecursive(pac, obj); + } + + assertFalse( pac_compact.next(result_compact) ); + } + + private void testDirectConversionRecursive(Unpacker pac, MessagePackObject obj) throws Exception { + if(obj.isBooleanType()) { + boolean expect = obj.asBoolean(); + boolean actual = pac.unpackBoolean(); + assertEquals(expect, actual); + + } else if(obj.isIntegerType()) { + BigInteger expect = obj.asBigInteger(); + if(BigInteger.valueOf((long)Byte.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf((long)Byte.MAX_VALUE)) <= 0) { + byte actual = pac.unpackByte(); + assertEquals(expect.byteValue(), actual); + } else if(BigInteger.valueOf((long)Short.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf((long)Short.MAX_VALUE)) <= 0) { + short actual = pac.unpackShort(); + assertEquals(expect.shortValue(), actual); + } else if(BigInteger.valueOf((long)Integer.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf((long)Integer.MAX_VALUE)) <= 0) { + int actual = pac.unpackInt(); + assertEquals(expect.intValue(), actual); + } else if(BigInteger.valueOf(Long.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) { + long actual = pac.unpackLong(); + assertEquals(expect.longValue(), actual); + } else { + BigInteger actual = pac.unpackBigInteger(); + assertEquals(expect, actual); + } + + } else if(obj.isFloatType()) { + double expect = obj.asFloat(); + double actual = pac.unpackDouble(); + assertEquals(expect, actual, 0.01); + + } else if(obj.isArrayType()) { + MessagePackObject[] expect = obj.asArray(); + int length = pac.unpackArray(); + assertEquals(expect.length, length); + for(int i=0; i < length; i++) { + testDirectConversionRecursive(pac, expect[i]); + } + + } else if(obj.isMapType()) { + Map expect = obj.asMap(); + int size = pac.unpackMap(); + assertEquals(expect.size(), size); + for(int i=0; i < size; i++) { + MessagePackObject key = pac.unpackObject(); + MessagePackObject value = expect.get(key); + assertNotNull(value); + testDirectConversionRecursive(pac, value); + } + + } else if(obj.isRawType()) { + byte[] expect = obj.asByteArray(); + int length = pac.unpackRaw(); + assertEquals(expect.length, length); + byte[] actual = pac.unpackRawBody(length); + assertTrue(Arrays.equals(expect, actual)); + + } else if(obj.isNil()) { + pac.unpackNull(); + + } else { + fail("unexpected object: "+obj); + } + } + + @Test + public void testIndirectConversion() throws Exception { + Unpacker pac = new Unpacker(); + Unpacker pac_compact = new Unpacker(); + + feedFile(pac, "src/test/resources/cases.mpac"); + feedFile(pac_compact, "src/test/resources/cases_compact.mpac"); + + UnpackResult result = new UnpackResult(); + UnpackResult result_compact = new UnpackResult(); + while(pac.next(result)) { + assertTrue( pac_compact.next(result_compact) ); + testIndirectConversionRecursive(result.getData(), result_compact.getData()); + } + + assertFalse( pac_compact.next(result) ); + } + + private void testIndirectConversionRecursive(MessagePackObject target, MessagePackObject obj) { + if(obj.isBooleanType()) { + boolean expect = obj.asBoolean(); + boolean actual = target.asBoolean(); + assertEquals(expect, actual); + + } else if(obj.isIntegerType()) { + BigInteger expect = obj.asBigInteger(); + if(BigInteger.valueOf((long)Byte.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf((long)Byte.MAX_VALUE)) <= 0) { + byte actual = target.asByte(); + assertEquals(expect.byteValue(), actual); + } else if(BigInteger.valueOf((long)Short.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf((long)Short.MAX_VALUE)) <= 0) { + short actual = target.asShort(); + assertEquals(expect.shortValue(), actual); + } else if(BigInteger.valueOf((long)Integer.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf((long)Integer.MAX_VALUE)) <= 0) { + int actual = target.asInt(); + assertEquals(expect.intValue(), actual); + } else if(BigInteger.valueOf(Long.MIN_VALUE).compareTo(expect) <= 0 && + expect.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) { + long actual = target.asLong(); + assertEquals(expect.longValue(), actual); + } else { + BigInteger actual = target.asBigInteger(); + assertEquals(expect, actual); + } + + } else if(obj.isFloatType()) { + double expect = obj.asFloat(); + double actual = target.asDouble(); + assertEquals(expect, actual, 0.01); + + } else if(obj.isArrayType()) { + MessagePackObject[] expect = obj.asArray(); + MessagePackObject[] actual = target.asArray(); + assertEquals(expect.length, actual.length); + for(int i=0; i < expect.length; i++) { + testIndirectConversionRecursive(actual[i], expect[i]); + } + + } else if(obj.isMapType()) { + Map expect = obj.asMap(); + Map actual = target.asMap(); + assertEquals(expect.size(), actual.size()); + for(Map.Entry pair : expect.entrySet()) { + MessagePackObject value = actual.get(pair.getKey()); + assertNotNull(value); + testIndirectConversionRecursive(value, pair.getValue()); + } + + } else if(obj.isRawType()) { + byte[] expect = obj.asByteArray(); + byte[] actual = obj.asByteArray(); + assertEquals(expect.length, actual.length); + assertTrue(Arrays.equals(expect, actual)); + + } else if(obj.isNil()) { + assertTrue(target.isNil()); + + } else { + fail("unexpected object: "+obj); + } + } }; From 4f3d9a1dedf3497133ec5dc7cdc7d2b2eae4bb59 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Fri, 8 Apr 2011 16:13:29 +0900 Subject: [PATCH 47/53] Refactored programs related to TemplateBuilder.java --- .../main/java/org/msgpack/MessagePack.java | 5 - .../msgpack/MessagePackTemplateProvider.java | 3 +- .../template/TemplateBuildException.java | 2 +- ...=> AnnotationTemplateBuilderSelector.java} | 29 +- .../builder/ArrayTemplateBuilder.java | 10 +- .../builder/ArrayTemplateBuilderSelector.java | 7 +- .../BeansBuildContext.java | 16 +- .../BeansTemplateBuilder.java} | 22 +- ...java => BeansTemplateBuilderSelector.java} | 30 +- .../{javassist => builder}/BuildContext.java | 16 +- .../BuildContextBase.java | 17 +- .../BuildContextFactory.java | 3 +- .../template/builder/BuilderSelector.java | 19 +- .../builder/BuilderSelectorRegistry.java | 27 +- .../builder/CustomTemplateBuilder.java | 5 +- ....java => EnumTemplateBuilderSelector.java} | 13 +- .../JavassistTemplate.java | 27 +- .../JavassistTemplateBuilder.java | 8 +- .../builder/OrdinalEnumTemplateBuilder.java | 3 +- ...> OrdinalEnumTemplateBuilderSelector.java} | 24 +- .../ReflectionTemplateBuilder.java | 8 +- .../template/builder/TemplateBuilder.java | 389 +----------------- .../TemplatePrecompiler.java} | 11 +- ...ionTemplateBuilderJavaBeansPackUnpack.java | 12 +- ...tReflectionTemplateBuilderPackConvert.java | 12 +- ...stReflectionTemplateBuilderPackUnpack.java | 12 +- .../JavassistTypeScalaTemplateBuilder.scala | 2 +- .../scala/org/msgpack/ScalaMessagePack.scala | 7 +- .../ScalaTemplateBuilderSelector.scala | 3 +- 29 files changed, 126 insertions(+), 616 deletions(-) rename java/src/main/java/org/msgpack/template/builder/{MessagePackMessageBuilderSelector.java => AnnotationTemplateBuilderSelector.java} (68%) rename java/src/main/java/org/msgpack/template/{javassist => builder}/BeansBuildContext.java (95%) rename java/src/main/java/org/msgpack/template/{BeansReflectionTemplateBuilder.java => builder/BeansTemplateBuilder.java} (90%) rename java/src/main/java/org/msgpack/template/builder/{MessagePackBeansBuilderSelector.java => BeansTemplateBuilderSelector.java} (66%) rename java/src/main/java/org/msgpack/template/{javassist => builder}/BuildContext.java (95%) rename java/src/main/java/org/msgpack/template/{javassist => builder}/BuildContextBase.java (95%) rename java/src/main/java/org/msgpack/template/{javassist => builder}/BuildContextFactory.java (89%) rename java/src/main/java/org/msgpack/template/builder/{EnumBuilderSelector.java => EnumTemplateBuilderSelector.java} (93%) rename java/src/main/java/org/msgpack/template/{javassist => builder}/JavassistTemplate.java (57%) rename java/src/main/java/org/msgpack/template/{ => builder}/JavassistTemplateBuilder.java (96%) rename java/src/main/java/org/msgpack/template/builder/{MessagePackOrdinalEnumBuilderSelector.java => OrdinalEnumTemplateBuilderSelector.java} (71%) rename java/src/main/java/org/msgpack/template/{ => builder}/ReflectionTemplateBuilder.java (97%) rename java/src/main/java/org/msgpack/{template/TemplateClassWriter.java => util/TemplatePrecompiler.java} (89%) diff --git a/java/src/main/java/org/msgpack/MessagePack.java b/java/src/main/java/org/msgpack/MessagePack.java index a650b797..27cfc506 100644 --- a/java/src/main/java/org/msgpack/MessagePack.java +++ b/java/src/main/java/org/msgpack/MessagePack.java @@ -22,7 +22,6 @@ import java.io.InputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import org.msgpack.template.TemplateRegistry; -import org.msgpack.template.TemplateClassWriter; import org.msgpack.template.FieldList; public class MessagePack { @@ -146,10 +145,6 @@ public class MessagePack { } } - public static void write(Class target, String directoryName) { - TemplateClassWriter.write(target, directoryName); - } - public static void register(Class target) { TemplateRegistry.register(target); } diff --git a/java/src/main/java/org/msgpack/MessagePackTemplateProvider.java b/java/src/main/java/org/msgpack/MessagePackTemplateProvider.java index 511625b7..8f7515b6 100644 --- a/java/src/main/java/org/msgpack/MessagePackTemplateProvider.java +++ b/java/src/main/java/org/msgpack/MessagePackTemplateProvider.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,6 +18,5 @@ package org.msgpack; public interface MessagePackTemplateProvider { - Template getTemplate(); } diff --git a/java/src/main/java/org/msgpack/template/TemplateBuildException.java b/java/src/main/java/org/msgpack/template/TemplateBuildException.java index c4c99566..f8560d1f 100644 --- a/java/src/main/java/org/msgpack/template/TemplateBuildException.java +++ b/java/src/main/java/org/msgpack/template/TemplateBuildException.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/AnnotationTemplateBuilderSelector.java similarity index 68% rename from java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java rename to java/src/main/java/org/msgpack/template/builder/AnnotationTemplateBuilderSelector.java index a4b3fe0c..10bf5e62 100644 --- a/java/src/main/java/org/msgpack/template/builder/MessagePackMessageBuilderSelector.java +++ b/java/src/main/java/org/msgpack/template/builder/AnnotationTemplateBuilderSelector.java @@ -22,34 +22,33 @@ import java.lang.reflect.Type; import org.msgpack.annotation.MessagePackMessage; -public class MessagePackMessageBuilderSelector implements BuilderSelector{ - - public static final String NAME = "MessagePackMessageTemplateBuilder"; - - +public class AnnotationTemplateBuilderSelector implements BuilderSelector{ + + public static final String NAME = "AnnotationTemplateBuilder"; + TemplateBuilder builder; - public MessagePackMessageBuilderSelector(TemplateBuilder builder){ + + public AnnotationTemplateBuilderSelector(TemplateBuilder builder){ this.builder = builder; } - - public String getName(){ + + @Override + public String getName(){ return NAME; } - + @Override public boolean matchType(Type targetType) { - Class target = (Class)targetType; - return isAnnotated(target, MessagePackMessage.class); + Class targetClass = (Class)targetType; + return isAnnotated(targetClass, MessagePackMessage.class); } @Override public TemplateBuilder getTemplateBuilder(Type targetType) { return builder; } - - private boolean isAnnotated(Class ao, Class with) { - return ao.getAnnotation(with) != null; + public static boolean isAnnotated(Class targetClass, Class with) { + return targetClass.getAnnotation(with) != null; } - } diff --git a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java index 07e49dee..819a6e49 100644 --- a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java @@ -22,8 +22,6 @@ import java.lang.reflect.Array; import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.util.HashMap; -import java.util.Map; import org.msgpack.AbstractTemplate; import org.msgpack.MessagePackObject; @@ -34,17 +32,12 @@ import org.msgpack.Unpacker; import org.msgpack.template.BooleanArrayTemplate; import org.msgpack.template.DoubleArrayTemplate; import org.msgpack.template.FloatArrayTemplate; -import org.msgpack.template.IFieldEntry; -import org.msgpack.template.IFieldEntryReader; import org.msgpack.template.IntArrayTemplate; import org.msgpack.template.LongArrayTemplate; import org.msgpack.template.ShortArrayTemplate; import org.msgpack.template.TemplateRegistry; -public class ArrayTemplateBuilder extends TemplateBuilder { - - - +public class ArrayTemplateBuilder implements TemplateBuilder { static class ReflectionObjectArrayTemplate extends AbstractTemplate { private Class componentClass; @@ -128,6 +121,7 @@ public class ArrayTemplateBuilder extends TemplateBuilder { return array; } } + @Override public Template buildTemplate(Type arrayType) { Type baseType; diff --git a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java index 66428bef..eeefd7ec 100644 --- a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java +++ b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilderSelector.java @@ -20,18 +20,17 @@ package org.msgpack.template.builder; import java.lang.reflect.GenericArrayType; import java.lang.reflect.Type; -import org.msgpack.Template; - public class ArrayTemplateBuilderSelector implements BuilderSelector { public static final String NAME = "ArrayTemplateBuilder"; + ArrayTemplateBuilder templateBuilder = new ArrayTemplateBuilder(); + @Override public String getName(){ return NAME; } - @Override public boolean matchType(Type targetType) { if(targetType instanceof GenericArrayType){ @@ -41,8 +40,6 @@ public class ArrayTemplateBuilderSelector implements BuilderSelector { return targetClass.isArray(); } - ArrayTemplateBuilder templateBuilder = new ArrayTemplateBuilder(); - @Override public TemplateBuilder getTemplateBuilder(Type target) { return templateBuilder; diff --git a/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java b/java/src/main/java/org/msgpack/template/builder/BeansBuildContext.java similarity index 95% rename from java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java rename to java/src/main/java/org/msgpack/template/builder/BeansBuildContext.java index 6b4fa265..574ce76e 100644 --- a/java/src/main/java/org/msgpack/template/javassist/BeansBuildContext.java +++ b/java/src/main/java/org/msgpack/template/builder/BeansBuildContext.java @@ -15,33 +15,19 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template.javassist; +package org.msgpack.template.builder; -import java.io.IOException; -import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Type; -import java.lang.Thread; import org.msgpack.*; import org.msgpack.template.*; import javassist.CannotCompileException; -import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; -import javassist.CtMethod; import javassist.CtNewConstructor; -import javassist.CtNewMethod; -import javassist.LoaderClassPath; import javassist.NotFoundException; -import javassist.ClassClassPath; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - public class BeansBuildContext extends BuildContextBase { protected BeansFieldEntry[] entries; diff --git a/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilder.java similarity index 90% rename from java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java rename to java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilder.java index e97531f7..e5946dd7 100644 --- a/java/src/main/java/org/msgpack/template/BeansReflectionTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilder.java @@ -15,10 +15,9 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template; +package org.msgpack.template.builder; import java.io.IOException; -import java.lang.reflect.Field; import org.msgpack.AbstractTemplate; import org.msgpack.MessagePackObject; @@ -26,27 +25,22 @@ import org.msgpack.MessageTypeException; import org.msgpack.Packer; import org.msgpack.Template; import org.msgpack.Unpacker; -import org.msgpack.template.ReflectionTemplateBuilder.BooleanFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.ByteFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.DoubleFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.FloatFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.IntFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.LongFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.NullFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.ObjectFieldEntry; -import org.msgpack.template.ReflectionTemplateBuilder.ShortFieldEntry; -import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.BeansFieldEntry; +import org.msgpack.template.BeansFieldEntryReader; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.TemplateRegistry; /** * Class for building java reflection template builder for java beans class. * @author takeshita * */ -public class BeansReflectionTemplateBuilder extends CustomTemplateBuilder{ +public class BeansTemplateBuilder extends CustomTemplateBuilder{ IFieldEntryReader reader = new BeansFieldEntryReader(); - public BeansReflectionTemplateBuilder(){} + public BeansTemplateBuilder(){} @Override public IFieldEntryReader getFieldEntryReader(){ diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilderSelector.java similarity index 66% rename from java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java rename to java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilderSelector.java index bec4a4f5..b875c2f7 100644 --- a/java/src/main/java/org/msgpack/template/builder/MessagePackBeansBuilderSelector.java +++ b/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilderSelector.java @@ -17,41 +17,33 @@ // package org.msgpack.template.builder; -import java.lang.annotation.Annotation; import java.lang.reflect.Type; import org.msgpack.annotation.MessagePackBeans; -import org.msgpack.annotation.MessagePackMessage; -public class MessagePackBeansBuilderSelector implements BuilderSelector{ - - public static final String NAME = "MessagePackBeansTemplateBuilder"; - - +public class BeansTemplateBuilderSelector implements BuilderSelector{ + + public static final String NAME = "BeansTemplateBuilder"; + TemplateBuilder builder; - public MessagePackBeansBuilderSelector(TemplateBuilder builder){ + + public BeansTemplateBuilderSelector(TemplateBuilder builder){ this.builder = builder; } - - + + @Override public String getName(){ return NAME; } - + @Override public boolean matchType(Type targetType) { - Class target = (Class)targetType; - return isAnnotated(target, MessagePackBeans.class); + Class targetClass = (Class)targetType; + return AnnotationTemplateBuilderSelector.isAnnotated(targetClass, MessagePackBeans.class); } @Override public TemplateBuilder getTemplateBuilder(Type targetType) { return builder; } - - - private boolean isAnnotated(Class ao, Class with) { - return ao.getAnnotation(with) != null; - } - } diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContext.java b/java/src/main/java/org/msgpack/template/builder/BuildContext.java similarity index 95% rename from java/src/main/java/org/msgpack/template/javassist/BuildContext.java rename to java/src/main/java/org/msgpack/template/builder/BuildContext.java index a3ab97d9..ccb05f52 100644 --- a/java/src/main/java/org/msgpack/template/javassist/BuildContext.java +++ b/java/src/main/java/org/msgpack/template/builder/BuildContext.java @@ -15,33 +15,19 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template.javassist; +package org.msgpack.template.builder; -import java.io.IOException; -import java.lang.reflect.Array; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Type; -import java.lang.Thread; import org.msgpack.*; import org.msgpack.template.*; import javassist.CannotCompileException; -import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; -import javassist.CtMethod; import javassist.CtNewConstructor; -import javassist.CtNewMethod; -import javassist.LoaderClassPath; import javassist.NotFoundException; -import javassist.ClassClassPath; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - - public class BuildContext extends BuildContextBase { protected IFieldEntry[] entries; diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java b/java/src/main/java/org/msgpack/template/builder/BuildContextBase.java similarity index 95% rename from java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java rename to java/src/main/java/org/msgpack/template/builder/BuildContextBase.java index 1b2db02b..7253bfd4 100644 --- a/java/src/main/java/org/msgpack/template/javassist/BuildContextBase.java +++ b/java/src/main/java/org/msgpack/template/builder/BuildContextBase.java @@ -15,37 +15,26 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template.javassist; +package org.msgpack.template.builder; import java.io.IOException; -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Type; -import java.lang.Thread; import org.msgpack.*; import org.msgpack.template.*; import javassist.CannotCompileException; -import javassist.ClassPool; import javassist.CtClass; -import javassist.CtConstructor; import javassist.CtMethod; -import javassist.CtNewConstructor; import javassist.CtNewMethod; -import javassist.LoaderClassPath; import javassist.NotFoundException; -import javassist.ClassClassPath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - public abstract class BuildContextBase { private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class); - protected JavassistTemplateBuilder director; @@ -70,10 +59,8 @@ public abstract class BuildContextBase { public BuildContextBase(JavassistTemplateBuilder director) { this.director = director; } - - - public abstract Template buildTemplate(Class targetClass, T[] entries, Template[] templates); + public abstract Template buildTemplate(Class targetClass, T[] entries, Template[] templates); protected Template build(final String className) { try { diff --git a/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java b/java/src/main/java/org/msgpack/template/builder/BuildContextFactory.java similarity index 89% rename from java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java rename to java/src/main/java/org/msgpack/template/builder/BuildContextFactory.java index 1099482b..5974ef7f 100644 --- a/java/src/main/java/org/msgpack/template/javassist/BuildContextFactory.java +++ b/java/src/main/java/org/msgpack/template/builder/BuildContextFactory.java @@ -15,9 +15,8 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template.javassist; +package org.msgpack.template.builder; -import org.msgpack.template.JavassistTemplateBuilder; public interface BuildContextFactory { diff --git a/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java index 0691612e..8ca94b44 100644 --- a/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java +++ b/java/src/main/java/org/msgpack/template/builder/BuilderSelector.java @@ -25,20 +25,9 @@ import java.lang.reflect.Type; * */ public interface BuilderSelector { - - - /** - * Name of this. - * @return - */ - public String getName(); - - - public abstract boolean matchType(Type targetType); - - - public abstract TemplateBuilder getTemplateBuilder(Type targetType); - - + String getName(); + boolean matchType(Type targetType); + + TemplateBuilder getTemplateBuilder(Type targetType); } diff --git a/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java b/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java index 02d365b8..f5d5a5be 100644 --- a/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java +++ b/java/src/main/java/org/msgpack/template/builder/BuilderSelectorRegistry.java @@ -22,13 +22,6 @@ import java.util.LinkedList; import java.util.List; import org.msgpack.template.BeansFieldEntryReader; -import org.msgpack.template.BeansReflectionTemplateBuilder; -import org.msgpack.template.JavassistTemplateBuilder; -import org.msgpack.template.ReflectionTemplateBuilder; -import org.msgpack.template.javassist.BeansBuildContext; -import org.msgpack.template.javassist.BuildContext; -import org.msgpack.template.javassist.BuildContextBase; -import org.msgpack.template.javassist.BuildContextFactory; /** * Registry for BuilderSelectors. @@ -38,8 +31,9 @@ import org.msgpack.template.javassist.BuildContextFactory; * */ public class BuilderSelectorRegistry { - + private static BuilderSelectorRegistry instance = new BuilderSelectorRegistry(); + static{ initForJava(); } @@ -50,26 +44,25 @@ public class BuilderSelectorRegistry { TemplateBuilder forceBuilder; - List builderSelectors = new LinkedList(); private BuilderSelectorRegistry(){ } + /** * initialize BuilderSelectors for basic java enviroment. */ private static void initForJava(){ - instance.append(new ArrayTemplateBuilderSelector()); if(isSupportJavassist()){ instance.append( - new MessagePackMessageBuilderSelector( + new AnnotationTemplateBuilderSelector( new JavassistTemplateBuilder())); instance.forceBuilder = new JavassistTemplateBuilder(); //Java beans - instance.append(new MessagePackBeansBuilderSelector( + instance.append(new BeansTemplateBuilderSelector( new JavassistTemplateBuilder( new BeansFieldEntryReader(), new BuildContextFactory() { @@ -81,17 +74,17 @@ public class BuilderSelectorRegistry { ))); }else{ instance.append( - new MessagePackMessageBuilderSelector( + new AnnotationTemplateBuilderSelector( new ReflectionTemplateBuilder())); instance.forceBuilder = new ReflectionTemplateBuilder(); //Java beans - instance.append(new MessagePackBeansBuilderSelector( - new BeansReflectionTemplateBuilder())); + instance.append(new BeansTemplateBuilderSelector( + new BeansTemplateBuilder())); } - instance.append(new MessagePackOrdinalEnumBuilderSelector()); - instance.append(new EnumBuilderSelector()); + instance.append(new OrdinalEnumTemplateBuilderSelector()); + instance.append(new EnumTemplateBuilderSelector()); } public static boolean isSupportJavassist(){ try { diff --git a/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java index a3875388..439371d7 100644 --- a/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java @@ -25,14 +25,11 @@ import org.msgpack.template.FieldOption; import org.msgpack.template.IFieldEntry; import org.msgpack.template.IFieldEntryReader; import org.msgpack.template.TemplateBuildException; -import org.msgpack.template.javassist.BuildContextFactory; - -public abstract class CustomTemplateBuilder extends TemplateBuilder { +public abstract class CustomTemplateBuilder implements TemplateBuilder { public abstract IFieldEntryReader getFieldEntryReader(); - public abstract Template buildTemplate(Class targetClass , IFieldEntry[] entries); public Template buildTemplate(Class targetClass ,FieldOption implicitOption ){ diff --git a/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/EnumTemplateBuilderSelector.java similarity index 93% rename from java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java rename to java/src/main/java/org/msgpack/template/builder/EnumTemplateBuilderSelector.java index 959aa9ec..816a2faf 100644 --- a/java/src/main/java/org/msgpack/template/builder/EnumBuilderSelector.java +++ b/java/src/main/java/org/msgpack/template/builder/EnumTemplateBuilderSelector.java @@ -19,25 +19,24 @@ package org.msgpack.template.builder; import java.lang.reflect.Type; -public class EnumBuilderSelector implements BuilderSelector { +public class EnumTemplateBuilderSelector implements BuilderSelector { public static final String NAME = "EnumTemplateBuilder"; - + + OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); + + @Override public String getName(){ return NAME; } - + @Override public boolean matchType(Type targetType) { return ((Class)targetType).isEnum(); } - - OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); - @Override public TemplateBuilder getTemplateBuilder(Type targetType) { return builder; } - } diff --git a/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java b/java/src/main/java/org/msgpack/template/builder/JavassistTemplate.java similarity index 57% rename from java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java rename to java/src/main/java/org/msgpack/template/builder/JavassistTemplate.java index c3feabe2..84b8cc1b 100644 --- a/java/src/main/java/org/msgpack/template/javassist/JavassistTemplate.java +++ b/java/src/main/java/org/msgpack/template/builder/JavassistTemplate.java @@ -15,31 +15,10 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template.javassist; +package org.msgpack.template.builder; -import java.io.IOException; -import java.lang.reflect.Array; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Type; -import java.lang.Thread; - -import org.msgpack.*; -import org.msgpack.template.*; - -import javassist.CannotCompileException; -import javassist.ClassPool; -import javassist.CtClass; -import javassist.CtConstructor; -import javassist.CtMethod; -import javassist.CtNewConstructor; -import javassist.CtNewMethod; -import javassist.LoaderClassPath; -import javassist.NotFoundException; -import javassist.ClassClassPath; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.msgpack.AbstractTemplate; +import org.msgpack.Template; public abstract class JavassistTemplate extends AbstractTemplate { public Class targetClass; diff --git a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/JavassistTemplateBuilder.java similarity index 96% rename from java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java rename to java/src/main/java/org/msgpack/template/builder/JavassistTemplateBuilder.java index 7366c653..a001bf45 100644 --- a/java/src/main/java/org/msgpack/template/JavassistTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/JavassistTemplateBuilder.java @@ -15,7 +15,7 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template; +package org.msgpack.template.builder; import java.lang.Thread; @@ -28,8 +28,10 @@ import javassist.NotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.msgpack.template.builder.CustomTemplateBuilder; -import org.msgpack.template.javassist.*; +import org.msgpack.template.FieldEntryReader; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.TemplateRegistry; public class JavassistTemplateBuilder extends CustomTemplateBuilder { private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class); diff --git a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java index d368984e..471defd4 100644 --- a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java @@ -30,7 +30,7 @@ import org.msgpack.Template; import org.msgpack.Unpacker; import org.msgpack.template.TemplateBuildException; -public class OrdinalEnumTemplateBuilder extends TemplateBuilder{ +public class OrdinalEnumTemplateBuilder implements TemplateBuilder{ static class ReflectionOrdinalEnumTemplate extends AbstractTemplate { protected Enum[] entries; @@ -68,6 +68,7 @@ public class OrdinalEnumTemplateBuilder extends TemplateBuilder{ return entries[ord]; } } + @Override public Template buildTemplate(Type targetType) { Class targetClass = (Class)targetType; diff --git a/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilderSelector.java similarity index 71% rename from java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java rename to java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilderSelector.java index 93f0f71d..6e612097 100644 --- a/java/src/main/java/org/msgpack/template/builder/MessagePackOrdinalEnumBuilderSelector.java +++ b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilderSelector.java @@ -17,35 +17,29 @@ // package org.msgpack.template.builder; -import java.lang.annotation.Annotation; import java.lang.reflect.Type; import org.msgpack.annotation.MessagePackOrdinalEnum; -public class MessagePackOrdinalEnumBuilderSelector implements BuilderSelector { +public class OrdinalEnumTemplateBuilderSelector implements BuilderSelector { - public static final String NAME = "MessagePackOrdinalEnumBuilderTemplate"; - + public static final String NAME = "OrdinalEnumBuilder"; + + OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); + + @Override public String getName(){ return NAME; } - + @Override public boolean matchType(Type targetType) { - Class target = (Class)targetType; - return isAnnotated(target, MessagePackOrdinalEnum.class); + Class targetClass = (Class)targetType; + return AnnotationTemplateBuilderSelector.isAnnotated(targetClass, MessagePackOrdinalEnum.class); } - - OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); @Override public TemplateBuilder getTemplateBuilder(Type targetType) { return builder; } - - - private boolean isAnnotated(Class ao, Class with) { - return ao.getAnnotation(with) != null; - } - } diff --git a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/ReflectionTemplateBuilder.java similarity index 97% rename from java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java rename to java/src/main/java/org/msgpack/template/builder/ReflectionTemplateBuilder.java index 057d500c..30bdda38 100644 --- a/java/src/main/java/org/msgpack/template/ReflectionTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/ReflectionTemplateBuilder.java @@ -15,14 +15,18 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template; +package org.msgpack.template.builder; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import org.msgpack.*; -import org.msgpack.template.builder.CustomTemplateBuilder; +import org.msgpack.template.FieldEntry; +import org.msgpack.template.FieldEntryReader; +import org.msgpack.template.IFieldEntry; +import org.msgpack.template.IFieldEntryReader; +import org.msgpack.template.TemplateRegistry; public class ReflectionTemplateBuilder extends CustomTemplateBuilder { IFieldEntryReader reader = new FieldEntryReader(); diff --git a/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java index 3e04a1fa..7c2533a1 100644 --- a/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java @@ -17,392 +17,11 @@ // package org.msgpack.template.builder; -import java.io.IOException; -import java.lang.reflect.*; -import java.lang.annotation.*; -import java.util.List; -import java.util.ArrayList; -import java.util.EnumSet; -import org.msgpack.*; -import org.msgpack.annotation.*; -import org.msgpack.template.FieldList; -import org.msgpack.template.FieldOption; -import org.msgpack.template.IFieldEntry; -import org.msgpack.template.IFieldEntryReader; -import org.msgpack.template.JavassistTemplateBuilder; -import org.msgpack.template.ReflectionTemplateBuilder; +import java.lang.reflect.Type; -public abstract class TemplateBuilder { +import org.msgpack.Template; - public abstract Template buildTemplate(Type targetType); - /* - // Override this method -<<<<<<< HEAD:java/src/main/java/org/msgpack/template/TemplateBuilder.java - public abstract Class loadTemplateClass(Class targetClass); - - // Override this method - public abstract Template initializeTemplate(Class targetClass, Class tmplClass, FieldEntry[] entries); - - // Override this method - public abstract void writeTemplateClass(Class targetClass, FieldEntry[] entries, String directoryName); - - // Override this method - public abstract Template buildTemplate(Class targetClass, FieldEntry[] entries); -======= - public abstract Template buildTemplate(Class targetClass, IFieldEntry[] entries); ->>>>>>> 21f0d0bfc47ddc6d9092621705047f3bef385ba5:java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java - - // Override this method - public abstract void writeOrdinalEnumTemplateClass(Class targetClass, Enum[] entires, String directoryName); - - // Override this method - public abstract Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries); - - // Override this method - public abstract void writeArrayTemplateClass(Type arrayType, Type genericBaseType, - Class baseClass, int dim, String directoryName); - - // Override this method - public abstract Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim); -<<<<<<< HEAD:java/src/main/java/org/msgpack/template/TemplateBuilder.java - - public Template initializeTemplate(Class targetClass, Class tmplClass) { - return initializeTemplate(targetClass, tmplClass, readFieldEntries(targetClass, readImplicitFieldOption(targetClass))); - } - - public void writeTemplateClass(Class targetClass, FieldList fList, String directoryName) throws NoSuchFieldException { - checkValidation(targetClass); - writeTemplateClass(targetClass, convertFieldEntries(targetClass, fList), directoryName); - } -======= - - public abstract IFieldEntryReader getFieldEntryReader(); ->>>>>>> 21f0d0bfc47ddc6d9092621705047f3bef385ba5:java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java - - public Template buildTemplate(Class targetClass, FieldList flist) throws NoSuchFieldException { - checkValidation(targetClass); - return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist)); - } - - public void writeTemplateClass(Class targetClass, FieldOption implicitOption, String directoryName) { - checkValidation(targetClass); - writeTemplateClass(targetClass, readFieldEntries(targetClass, implicitOption), directoryName); - } - - public Template buildTemplate(Class targetClass, FieldOption implicitOption) { - checkValidation(targetClass); - return buildTemplate(targetClass, getFieldEntryReader().readFieldEntries(targetClass, implicitOption)); - } - - public void writeTemplateClass(Class targetClass, final String directoryName) { - FieldOption implicitOption = readImplicitFieldOption(targetClass); - writeTemplateClass(targetClass, implicitOption, directoryName); - } - - public Template buildTemplate(Class targetClass) { - FieldOption implicitOption = getFieldEntryReader().readImplicitFieldOption(targetClass); - return buildTemplate(targetClass, implicitOption); - } - - public void writeOrdinalEnumTemplateClass(Class targetClass, String directoryName) { - checkOrdinalEnumValidation(targetClass); - Enum[] entries = (Enum[])targetClass.getEnumConstants(); - writeOrdinalEnumTemplateClass(targetClass, entries, directoryName); - } - - public Template buildOrdinalEnumTemplate(Class targetClass) { - checkOrdinalEnumValidation(targetClass); - Enum[] entries = (Enum[])targetClass.getEnumConstants(); - return buildOrdinalEnumTemplate(targetClass, entries); - } - - public void writeArrayTemplateClass(Type arrayType, String directoryName) { - throw new UnsupportedOperationException("not supported yet.");// TODO - } - - public Template buildArrayTemplate(Type arrayType) { - Type baseType; - Class baseClass; - int dim = 1; - if(arrayType instanceof GenericArrayType) { - GenericArrayType type = (GenericArrayType)arrayType; - baseType = type.getGenericComponentType(); - while(baseType instanceof GenericArrayType) { - baseType = ((GenericArrayType)baseType).getGenericComponentType(); - dim += 1; - } - if(baseType instanceof ParameterizedType) { - baseClass = (Class)((ParameterizedType)baseType).getRawType(); - } else { - baseClass = (Class)baseType; - } - } else { - Class type = (Class)arrayType; - baseClass = type.getComponentType(); - while(baseClass.isArray()) { - baseClass = baseClass.getComponentType(); - dim += 1; - } - baseType = baseClass; - } - return buildArrayTemplate(arrayType, baseType, baseClass, dim); - } - - private static Type getComponentType(Type arrayType) { - if(arrayType instanceof GenericArrayType) { - return ((GenericArrayType)arrayType).getGenericComponentType(); - } else { - return ((Class)arrayType).getComponentType(); - } - } - private void checkValidation(Class targetClass) { - if(targetClass.isInterface()) { - throw new TemplateBuildException("cannot build template of interface"); - } - if(targetClass.isArray()) { - throw new TemplateBuildException("cannot build template of array class"); - } - if(targetClass.isPrimitive()) { - throw new TemplateBuildException("cannot build template of primitive type"); - } - } - private void checkOrdinalEnumValidation(Class targetClass) { - if(!targetClass.isEnum()) { - throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); - } - } - - - private static TemplateBuilder instance; - static { - instance = selectDefaultTemplateBuilder(); - } - - private static TemplateBuilder selectDefaultTemplateBuilder() { - try { - // FIXME JavassistTemplateBuilder doesn't work on DalvikVM - if(System.getProperty("java.vm.name").equals("Dalvik")) { - return ReflectionTemplateBuilder.getInstance(); - } - } catch (Exception e) { - } - return JavassistTemplateBuilder.getInstance(); - } - - public synchronized static void setInstance(TemplateBuilder builder) { - instance = builder; - } - - public static Class load(Class targetClass) { - return instance.loadTemplateClass(targetClass); - } - - public static Template initialize(Class targetClass, Class tmplClass) { - return instance.initializeTemplate(targetClass, tmplClass); - } - - public static void writeClass(Class targetClass, String directoryName) { - instance.writeTemplateClass(targetClass, directoryName); - } - - public static Template build(Class targetClass) { - return instance.buildTemplate(targetClass); - } - - public static void writeClass(Class targetClass, FieldOption implicitOption, String directoryName) { - instance.writeTemplateClass(targetClass, implicitOption, directoryName); - } - - public static Template build(Class targetClass, FieldOption implicitOption) { - return instance.buildTemplate(targetClass, implicitOption); - } - - public static void writeClass(Class targetClass, FieldList fList, String directoryName) - throws NoSuchFieldException { - instance.writeTemplateClass(targetClass, fList, directoryName); - } - - public static Template build(Class targetClass, FieldList fList) throws NoSuchFieldException { - return instance.buildTemplate(targetClass, fList); - } - - public static void writeOrdinalEnumClass(Class targetClass, String directoryName) { - instance.writeOrdinalEnumTemplateClass(targetClass, directoryName); - } - - public static Template buildOrdinalEnum(Class targetClass) { - return instance.buildOrdinalEnumTemplate(targetClass); - } - - public static void writeArrayClass(Type arrayType, String directoryName) { - throw new UnsupportedOperationException("not supported yet.");// TODO - } - - public static Template buildArray(Type arrayType) { - return instance.buildArrayTemplate(arrayType); - }*/ - - /* - private static void checkValidation(Class targetClass) { - if(targetClass.isInterface()) { - throw new TemplateBuildException("cannot build template of interface"); - } - if(targetClass.isArray()) { - throw new TemplateBuildException("cannot build template of array class"); - } - if(targetClass.isPrimitive()) { - throw new TemplateBuildException("cannot build template of primitive type"); - } - } - - private static void checkOrdinalEnumValidation(Class targetClass) { - if(!targetClass.isEnum()) { - throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); - } - }*/ - - /* - static IFieldEntry[] convertFieldEntries(Class targetClass, FieldList flist) throws NoSuchFieldException { - List src = flist.getList(); - FieldEntry[] result = new FieldEntry[src.size()]; - for(int i=0; i < src.size(); i++) { - FieldList.Entry s = src.get(i); - if(s.isAvailable()) { - result[i] = new FieldEntry(targetClass.getDeclaredField(s.getName()), s.getOption()); - } else { - result[i] = new FieldEntry(); - } - } - return result; - }*/ - - /*static IFieldEntry[] readFieldEntries(Class targetClass, FieldOption implicitOption) { - Field[] allFields = readAllFields(targetClass); - - /* index: - * @Index(0) int field_a; // 0 - * int field_b; // 1 - * @Index(3) int field_c; // 3 - * int field_d; // 4 - * @Index(2) int field_e; // 2 - * int field_f; // 5 - *//* - List indexed = new ArrayList(); - int maxIndex = -1; - for(Field f : allFields) { - FieldOption opt = readFieldOption(f, implicitOption); - if(opt == FieldOption.IGNORE) { - // skip - continue; - } - - int index = readFieldIndex(f, maxIndex); - - if(indexed.size() > index && indexed.get(index) != null) { - throw new TemplateBuildException("duplicated index: "+index); - } - if(index < 0) { - throw new TemplateBuildException("invalid index: "+index); - } - - while(indexed.size() <= index) { - indexed.add(null); - } - indexed.set(index, new FieldEntry(f, opt)); - - if(maxIndex < index) { - maxIndex = index; - } - } - - FieldEntry[] result = new FieldEntry[maxIndex+1]; - for(int i=0; i < indexed.size(); i++) { - FieldEntry e = indexed.get(i); - if(e == null) { - result[i] = new FieldEntry(); - } else { - result[i] = e; - } - } - - return result; - }*/ - /* - private static Field[] readAllFields(Class targetClass) { - // order: [fields of super class, ..., fields of this class] - List succ = new ArrayList(); - int total = 0; - for(Class c = targetClass; c != Object.class; c = c.getSuperclass()) { - Field[] fields = c.getDeclaredFields(); - total += fields.length; - succ.add(fields); - } - Field[] result = new Field[total]; - int off = 0; - for(int i=succ.size()-1; i >= 0; i--) { - Field[] fields = succ.get(i); - System.arraycopy(fields, 0, result, off, fields.length); - off += fields.length; - } - return result; - } - - private static FieldOption readImplicitFieldOption(Class targetClass) { - MessagePackMessage a = targetClass.getAnnotation(MessagePackMessage.class); - if(a == null) { - return FieldOption.DEFAULT; - } - return a.value(); - } - - private static FieldOption readFieldOption(Field field, FieldOption implicitOption) { - int mod = field.getModifiers(); - if(Modifier.isStatic(mod) || Modifier.isFinal(mod)) { - return FieldOption.IGNORE; - } - - if(isAnnotated(field, Ignore.class)) { - return FieldOption.IGNORE; - } else if(isAnnotated(field, Required.class)) { - return FieldOption.REQUIRED; - } else if(isAnnotated(field, Optional.class)) { - return FieldOption.OPTIONAL; - } else if(isAnnotated(field, Nullable.class)) { - if(field.getDeclaringClass().isPrimitive()) { - return FieldOption.REQUIRED; - } else { - return FieldOption.NULLABLE; - } - } - - if(implicitOption != FieldOption.DEFAULT) { - return implicitOption; - } - - // default mode: - // transient : Ignore - // public : Required - // others : Ignore - if(Modifier.isTransient(mod)) { - return FieldOption.IGNORE; - } else if(Modifier.isPublic(mod)) { - return FieldOption.REQUIRED; - } else { - return FieldOption.IGNORE; - } - } - - private static int readFieldIndex(Field field, int maxIndex) { - Index a = field.getAnnotation(Index.class); - if(a == null) { - return maxIndex + 1; - } else { - return a.value(); - } - } - - private static boolean isAnnotated(AccessibleObject ao, Class with) { - return ao.getAnnotation(with) != null; - }*/ +public interface TemplateBuilder { + Template buildTemplate(Type targetType); } diff --git a/java/src/main/java/org/msgpack/template/TemplateClassWriter.java b/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java similarity index 89% rename from java/src/main/java/org/msgpack/template/TemplateClassWriter.java rename to java/src/main/java/org/msgpack/util/TemplatePrecompiler.java index 157c242b..8ca113b4 100644 --- a/java/src/main/java/org/msgpack/template/TemplateClassWriter.java +++ b/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java @@ -15,13 +15,14 @@ // See the License for the specific language governing permissions and // limitations under the License. // -package org.msgpack.template; +package org.msgpack.util; +import org.msgpack.template.TemplateBuildException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class TemplateClassWriter { - private static final Logger LOG = LoggerFactory.getLogger(TemplateClassWriter.class); +public class TemplatePrecompiler { + private static final Logger LOG = LoggerFactory.getLogger(TemplatePrecompiler.class); public static void write(Class target, String directoryName) { if (target.isEnum()) { @@ -36,7 +37,7 @@ public class TemplateClassWriter { private String[] classNames; - private TemplateClassWriter() { + private TemplatePrecompiler() { } private void parseOpts(final String[] args) {// TODO @@ -64,7 +65,7 @@ public class TemplateClassWriter { } public static void main(final String[] args) throws Exception { - TemplateClassWriter writer = new TemplateClassWriter(); + TemplatePrecompiler writer = new TemplatePrecompiler(); writer.parseOpts(args); writer.writeTemplateClasses(); } diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java index 951b401c..0bd6f71a 100644 --- a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java @@ -30,9 +30,11 @@ import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BeansTemplateBuilder; import org.msgpack.template.builder.BuilderSelectorRegistry; -import org.msgpack.template.builder.MessagePackBeansBuilderSelector; -import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.BeansTemplateBuilderSelector; +import org.msgpack.template.builder.AnnotationTemplateBuilderSelector; +import org.msgpack.template.builder.ReflectionTemplateBuilder; import org.msgpack.template.builder.TemplateBuilder; import org.junit.Assert; @@ -46,11 +48,11 @@ public class TestReflectionTemplateBuilderJavaBeansPackUnpack extends TestCase { BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); instance.replace( - new MessagePackMessageBuilderSelector( + new AnnotationTemplateBuilderSelector( new ReflectionTemplateBuilder())); instance.setForceBuilder( new ReflectionTemplateBuilder()); - instance.replace(new MessagePackBeansBuilderSelector( - new BeansReflectionTemplateBuilder())); + instance.replace(new BeansTemplateBuilderSelector( + new BeansTemplateBuilder())); MessagePack.register(PrimitiveTypeFieldsClass.class); MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java index dcb039f7..93523228 100644 --- a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java @@ -24,9 +24,11 @@ import org.msgpack.Unpacker; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; +import org.msgpack.template.builder.BeansTemplateBuilder; import org.msgpack.template.builder.BuilderSelectorRegistry; -import org.msgpack.template.builder.MessagePackBeansBuilderSelector; -import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.BeansTemplateBuilderSelector; +import org.msgpack.template.builder.AnnotationTemplateBuilderSelector; +import org.msgpack.template.builder.ReflectionTemplateBuilder; import org.msgpack.template.builder.TemplateBuilder; import junit.framework.Assert; @@ -38,11 +40,11 @@ public class TestReflectionTemplateBuilderPackConvert extends TestCase { BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); instance.replace( - new MessagePackMessageBuilderSelector( + new AnnotationTemplateBuilderSelector( new ReflectionTemplateBuilder())); instance.setForceBuilder( new ReflectionTemplateBuilder()); - instance.replace(new MessagePackBeansBuilderSelector( - new BeansReflectionTemplateBuilder())); + instance.replace(new BeansTemplateBuilderSelector( + new BeansTemplateBuilder())); MessagePack.register(PrimitiveTypeFieldsClass.class); MessagePack.register(OptionalPrimitiveTypeFieldsClass.class); diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java index 6080df6e..64fc9785 100644 --- a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java @@ -25,9 +25,11 @@ import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; +import org.msgpack.template.builder.BeansTemplateBuilder; import org.msgpack.template.builder.BuilderSelectorRegistry; -import org.msgpack.template.builder.MessagePackBeansBuilderSelector; -import org.msgpack.template.builder.MessagePackMessageBuilderSelector; +import org.msgpack.template.builder.BeansTemplateBuilderSelector; +import org.msgpack.template.builder.AnnotationTemplateBuilderSelector; +import org.msgpack.template.builder.ReflectionTemplateBuilder; import org.msgpack.template.builder.TemplateBuilder; import junit.framework.Assert; @@ -41,11 +43,11 @@ public class TestReflectionTemplateBuilderPackUnpack extends TestCase { BuilderSelectorRegistry instance = BuilderSelectorRegistry.getInstance(); instance.replace( - new MessagePackMessageBuilderSelector( + new AnnotationTemplateBuilderSelector( new ReflectionTemplateBuilder())); instance.setForceBuilder( new ReflectionTemplateBuilder()); - instance.replace(new MessagePackBeansBuilderSelector( - new BeansReflectionTemplateBuilder())); + instance.replace(new BeansTemplateBuilderSelector( + new BeansTemplateBuilder())); MessagePack.register(PrimitiveTypeFieldsClass.class); diff --git a/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala index 879bddea..784c9e93 100644 --- a/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala +++ b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala @@ -7,7 +7,7 @@ import java.lang.Class import collection.immutable.{ListMap, TreeMap} import java.lang.reflect.{Type, Modifier, Method, Field} import java.lang.annotation.{Annotation => JavaAnnotation} -import javassist.{JavassistTemplate, BuildContextBase, BuildContext} +import builder.{JavassistTemplateBuilder, JavassistTemplate, BuildContextBase, BuildContext} import scala.collection.JavaConverters._ ; /* diff --git a/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala b/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala index 45b6f5fc..89fb43c6 100644 --- a/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala +++ b/scala/src/main/scala/org/msgpack/ScalaMessagePack.scala @@ -1,10 +1,9 @@ package org.msgpack import template._ -import builder.{MessagePackMessageBuilderSelector, BuilderSelectorRegistry} -import template.javassist.BuildContextFactory +import builder.{AnnotationTemplateBuilderSelector, BuilderSelectorRegistry, BuildContextFactory} import collection.mutable.{MutableList, LinkedList} -import collection.mutable.{Map => MMap,HashMap => MHashMap} +import collection.mutable.{Map => MMap, HashMap => MHashMap} ; /* * Created by IntelliJ IDEA. @@ -18,7 +17,7 @@ object ScalaMessagePack { { // for scala object BuilderSelectorRegistry.getInstance.insertBefore( - MessagePackMessageBuilderSelector.NAME, + AnnotationTemplateBuilderSelector.NAME, new ScalaTemplateBuilderSelector) // register scala's list classes diff --git a/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala index b8b7c122..ac236a56 100644 --- a/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala +++ b/scala/src/main/scala/org/msgpack/ScalaTemplateBuilderSelector.scala @@ -3,8 +3,7 @@ package org.msgpack import annotation.MessagePackMessage import template.builder.BuilderSelector import java.lang.reflect.Type -import template.javassist.BuildContextFactory -import template.JavassistTemplateBuilder +import template.builder.{JavassistTemplateBuilder, BuildContextFactory} import java.lang.annotation.{Annotation => JAnnotation} ; /* From 43fc0a52a64c4678a2497c5e90d0872aa8c28782 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Fri, 8 Apr 2011 16:17:25 +0900 Subject: [PATCH 48/53] scala: added a new AUTHORS file and edited pom.xml --- scala/AUTHORS | 1 + scala/pom.xml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 scala/AUTHORS diff --git a/scala/AUTHORS b/scala/AUTHORS new file mode 100644 index 00000000..ababacb0 --- /dev/null +++ b/scala/AUTHORS @@ -0,0 +1 @@ +FURUHASHI Sadayuki diff --git a/scala/pom.xml b/scala/pom.xml index 7ec8f3e9..c15f9480 100644 --- a/scala/pom.xml +++ b/scala/pom.xml @@ -2,7 +2,7 @@ 4.0.0 org.msgpack scala-msgpack - 0.0.1-SNAPSHOT + 0.0.1-devel ${project.artifactId} My wonderfull scala app 2010 From b96b62f2ac7edc98be9ab78085be9ee4ed8536ea Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Fri, 8 Apr 2011 16:20:28 +0900 Subject: [PATCH 49/53] scala: deleted the AUTHORS file --- scala/AUTHORS | 1 - 1 file changed, 1 deletion(-) delete mode 100644 scala/AUTHORS diff --git a/scala/AUTHORS b/scala/AUTHORS deleted file mode 100644 index ababacb0..00000000 --- a/scala/AUTHORS +++ /dev/null @@ -1 +0,0 @@ -FURUHASHI Sadayuki From 58c0fe0f91c32db2d6f89b1a40d7d022da5e0b54 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Sat, 9 Apr 2011 21:10:15 +0900 Subject: [PATCH 50/53] java: Refactored template builders again --- .../java/org/msgpack/AbstractTemplate.java | 5 +- java/src/main/java/org/msgpack/Template.java | 5 +- .../msgpack/template/TemplateRegistry.java | 72 +++-------- .../builder/ArrayTemplateBuilder.java | 10 ++ .../template/builder/BeansBuildContext.java | 12 +- .../builder/BeansTemplateBuilder.java | 6 +- .../template/builder/BuildContext.java | 20 ++- .../template/builder/BuildContextBase.java | 70 +++++++++-- .../builder/CustomTemplateBuilder.java | 28 +++-- .../template/builder/JavassistTemplate.java | 31 ----- .../builder/JavassistTemplateBuilder.java | 115 ++++++++---------- .../builder/OrdinalEnumTemplateBuilder.java | 10 ++ .../OrdinalEnumTemplateBuilderSelector.java | 2 +- .../builder/ReflectionTemplateBuilder.java | 8 +- .../template/builder/TemplateBuilder.java | 4 + .../org/msgpack/util/TemplatePrecompiler.java | 64 +++++----- .../JavassistTypeScalaTemplateBuilder.scala | 20 ++- 17 files changed, 264 insertions(+), 218 deletions(-) delete mode 100644 java/src/main/java/org/msgpack/template/builder/JavassistTemplate.java diff --git a/java/src/main/java/org/msgpack/AbstractTemplate.java b/java/src/main/java/org/msgpack/AbstractTemplate.java index 7f8cb49f..429a4705 100644 --- a/java/src/main/java/org/msgpack/AbstractTemplate.java +++ b/java/src/main/java/org/msgpack/AbstractTemplate.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -23,5 +23,4 @@ public abstract class AbstractTemplate implements Template { public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException { return convert(pac.unpackObject(), to); } -} - +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/Template.java b/java/src/main/java/org/msgpack/Template.java index 19808afb..8cce999f 100644 --- a/java/src/main/java/org/msgpack/Template.java +++ b/java/src/main/java/org/msgpack/Template.java @@ -1,7 +1,7 @@ // // MessagePack for Java // -// Copyright (C) 2009-2010 FURUHASHI Sadayuki +// Copyright (C) 2009-2011 FURUHASHI Sadayuki // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -18,5 +18,4 @@ package org.msgpack; public interface Template extends MessagePacker, MessageUnpacker, MessageConverter { -} - +} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/TemplateRegistry.java b/java/src/main/java/org/msgpack/template/TemplateRegistry.java index ef4d51f2..4c4f87b6 100644 --- a/java/src/main/java/org/msgpack/template/TemplateRegistry.java +++ b/java/src/main/java/org/msgpack/template/TemplateRegistry.java @@ -20,12 +20,7 @@ package org.msgpack.template; import java.util.Map; import java.util.HashMap; import java.lang.reflect.Type; -import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; -import java.lang.annotation.Annotation; -import org.msgpack.annotation.MessagePackMessage; -import org.msgpack.annotation.MessagePackDelegate; -import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.template.builder.BuilderSelectorRegistry; import org.msgpack.template.builder.CustomTemplateBuilder; import org.msgpack.template.builder.TemplateBuilder; @@ -44,18 +39,13 @@ public class TemplateRegistry { builderSelectorRegistry = BuilderSelectorRegistry.getInstance(); } - public static void register(Class target) { // auto-detect + public static void register(Class target) { TemplateBuilder builder = builderSelectorRegistry.select(target); if(builder != null){ register(target,builder.buildTemplate(target)); }else{ register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target)); } - /*if(target.isEnum()) { - register(target, TemplateBuilder.buildOrdinalEnum(target)); - } else { - register(target, TemplateBuilder.build(target)); - }*/ } public static void register(Class target, FieldOption implicitOption) { @@ -63,7 +53,7 @@ public class TemplateRegistry { if(builder != null && builder instanceof CustomTemplateBuilder){ register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, implicitOption)); }else{ - throw new TemplateBuildException("cannot build template with filed option"); + throw new TemplateBuildException("Cannot build template with filed option"); } } @@ -72,7 +62,7 @@ public class TemplateRegistry { if(builder != null && builder instanceof CustomTemplateBuilder){ register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, flist)); }else{ - throw new TemplateBuildException("cannot build template with filed list"); + throw new TemplateBuildException("Cannot build template with filed list"); } } @@ -123,50 +113,21 @@ public class TemplateRegistry { return tmpl; } - /*if(targetType instanceof GenericArrayType) { - // GenericArrayType is not a Class - tmpl = TemplateBuilder.buildArray(targetType); - register(targetType, tmpl); - return tmpl; - } - - Class target = (Class)targetType; - - Class tmplClass = TemplateBuilder.load(target); - if (tmplClass != null) { - tmpl = TemplateBuilder.initialize(target, tmplClass); - register(target, tmpl); - return tmpl; - } - - if(target.isArray()) { - // FIXME can't distinguish type-erased T<>[]? - tmpl = TemplateBuilder.buildArray(target); - register(target, tmpl); - return tmpl; - } - - if(isAnnotated(target, MessagePackMessage.class)) { - tmpl = TemplateBuilder.build(target); - register(target, tmpl); - return tmpl; - } else if(isAnnotated(target, MessagePackDelegate.class)) { - // TODO DelegateTemplate - throw new UnsupportedOperationException("not supported yet. : " + target.getName()); - } else if(isAnnotated(target, MessagePackOrdinalEnum.class)) { - tmpl = TemplateBuilder.buildOrdinalEnum(target); - register(target, tmpl); - return tmpl; - }*/ // find match TemplateBuilder TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetType); if(builder != null){ + tmpl = builder.loadTemplate(targetType); + if (tmpl != null) { + return tmpl; + } + tmpl = builder.buildTemplate(targetType); - register(targetType,tmpl); - return tmpl; + if (tmpl != null) { + register(targetType, tmpl); + return tmpl; + } } - - + Class target = (Class)targetType; for(Class i : target.getInterfaces()) { @@ -212,7 +173,7 @@ public class TemplateRegistry { } return new DefaultTemplate((Class)parameterizedType.getRawType(), parameterizedType); } else { - throw new IllegalArgumentException("actual types of the generic type are erased: "+targetType); + throw new IllegalArgumentException("Actual types of the generic type are erased: "+targetType); } } @@ -231,10 +192,5 @@ public class TemplateRegistry { return gtmpl.build(tmpls); } - - private static boolean isAnnotated(Class ao, Class with) { - return ao.getAnnotation(with) != null; - } - } diff --git a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java index 819a6e49..24e277ac 100644 --- a/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/ArrayTemplateBuilder.java @@ -151,6 +151,7 @@ public class ArrayTemplateBuilder implements TemplateBuilder { return toTemplate(arrayType, baseType, baseClass, dim); } + private Template toTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { if(dim == 1) { if(baseClass == boolean.class) { @@ -181,4 +182,13 @@ public class ArrayTemplateBuilder implements TemplateBuilder { } } + @Override + public void writeTemplate(Type targetType, String directoryName) { + throw new UnsupportedOperationException(targetType.toString()); + } + + @Override + public Template loadTemplate(Type targetType) { + return null; + } } diff --git a/java/src/main/java/org/msgpack/template/builder/BeansBuildContext.java b/java/src/main/java/org/msgpack/template/builder/BeansBuildContext.java index 574ce76e..af88d3ff 100644 --- a/java/src/main/java/org/msgpack/template/builder/BeansBuildContext.java +++ b/java/src/main/java/org/msgpack/template/builder/BeansBuildContext.java @@ -50,7 +50,7 @@ public class BeansBuildContext extends BuildContextBase { protected void setSuperClass() throws CannotCompileException, NotFoundException { this.tmplCtClass.setSuperclass( - director.getCtClass(JavassistTemplate.class.getName())); + director.getCtClass(JavassistTemplateBuilder.JavassistTemplate.class.getName())); } protected void buildConstructor() throws CannotCompileException, NotFoundException { @@ -272,4 +272,14 @@ public class BeansBuildContext extends BuildContextBase { return getBuiltString(); } + @Override + public void writeTemplate(Class targetClass, BeansFieldEntry[] entries, + Template[] templates, String directoryName) { + throw new UnsupportedOperationException(targetClass.getName()); + } + + @Override + public Template loadTemplate(Class targetClass, BeansFieldEntry[] entries, Template[] templates) { + throw new UnsupportedOperationException(targetClass.getName()); + } } \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilder.java index e5946dd7..57634660 100644 --- a/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/BeansTemplateBuilder.java @@ -18,6 +18,7 @@ package org.msgpack.template.builder; import java.io.IOException; +import java.lang.reflect.Type; import org.msgpack.AbstractTemplate; import org.msgpack.MessagePackObject; @@ -299,7 +300,6 @@ public class BeansTemplateBuilder extends CustomTemplateBuilder{ @Override public Template buildTemplate(Class targetClass, IFieldEntry[] entries) { - ReflectionEntry[] refEntries = new ReflectionEntry[entries.length]; for(int i = 0;i < entries.length;i++){ BeansFieldEntry e = (BeansFieldEntry)entries[i]; @@ -323,10 +323,6 @@ public class BeansTemplateBuilder extends CustomTemplateBuilder{ refEntries[i] = new ObjectFieldEntry(e, tmpl); } } - - return new BeansReflectionTemplate(targetClass,refEntries); } - - } diff --git a/java/src/main/java/org/msgpack/template/builder/BuildContext.java b/java/src/main/java/org/msgpack/template/builder/BuildContext.java index ccb05f52..ef843a96 100644 --- a/java/src/main/java/org/msgpack/template/builder/BuildContext.java +++ b/java/src/main/java/org/msgpack/template/builder/BuildContext.java @@ -50,7 +50,7 @@ public class BuildContext extends BuildContextBase { protected void setSuperClass() throws CannotCompileException, NotFoundException { this.tmplCtClass.setSuperclass( - director.getCtClass(JavassistTemplate.class.getName())); + director.getCtClass(JavassistTemplateBuilder.JavassistTemplate.class.getName())); } protected void buildConstructor() throws CannotCompileException, NotFoundException { @@ -272,4 +272,22 @@ public class BuildContext extends BuildContextBase { return getBuiltString(); } + @Override + public void writeTemplate(Class targetClass, FieldEntry[] entries, + Template[] templates, String directoryName) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + write(this.origName, directoryName); + } + + @Override + public Template loadTemplate(Class targetClass, FieldEntry[] entries, Template[] templates) { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + return load(this.origName); + } } \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/builder/BuildContextBase.java b/java/src/main/java/org/msgpack/template/builder/BuildContextBase.java index 7253bfd4..229f1c8c 100644 --- a/java/src/main/java/org/msgpack/template/builder/BuildContextBase.java +++ b/java/src/main/java/org/msgpack/template/builder/BuildContextBase.java @@ -42,6 +42,8 @@ public abstract class BuildContextBase { protected CtClass tmplCtClass; + protected abstract Template buildTemplate(Class targetClass, T[] entries, Template[] templates); + protected abstract void setSuperClass() throws CannotCompileException, NotFoundException; protected abstract void buildConstructor() throws CannotCompileException, NotFoundException; @@ -54,17 +56,21 @@ public abstract class BuildContextBase { protected abstract String buildConvertMethodBody(); - protected abstract Template buildInstance(Class c) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException; + protected abstract Template buildInstance(Class c) + throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException; + + protected abstract void writeTemplate(Class targetClass, T[] entries, + Template[] templates, String directoryName); + + protected abstract Template loadTemplate(Class targetClass, T[] entries, Template[] templates); public BuildContextBase(JavassistTemplateBuilder director) { this.director = director; } - public abstract Template buildTemplate(Class targetClass, T[] entries, Template[] templates); - protected Template build(final String className) { try { - reset(className); + reset(className, false); buildClass(); buildConstructor(); buildMethodInit(); @@ -76,15 +82,20 @@ public abstract class BuildContextBase { String code = getBuiltString(); if(code != null) { LOG.error("builder: " + code, e); - throw new TemplateBuildException("cannot compile: " + code, e); + throw new TemplateBuildException("Cannot compile: " + code, e); } else { throw new TemplateBuildException(e); } } } - protected void reset(String className) { - tmplName = className + "_$$_Template" + director.nextSeqId(); + protected void reset(String className, boolean isWritten) { + String tmplName = null; + if (!isWritten) { + tmplName = className + "_$$_Template" + director.nextSeqId(); + } else { + tmplName = className + "_$$_Template"; + } tmplCtClass = director.makeCtClass(tmplName); } @@ -151,6 +162,10 @@ public abstract class BuildContextBase { return (Class) tmplCtClass.toClass(null, null); } + protected void saveClass(final String directoryName) throws CannotCompileException, IOException { + tmplCtClass.writeFile(directoryName); + } + protected StringBuilder stringBuilder = null; protected void resetStringBuilder() { @@ -171,7 +186,7 @@ public abstract class BuildContextBase { } return stringBuilder.toString(); } - + protected String primitivePackName(Class type) { if(type == boolean.class) { return "packBoolean"; @@ -228,4 +243,43 @@ public abstract class BuildContextBase { } return null; } + + protected void write(final String className, final String directoryName) { + try { + reset(className, true); + buildClass(); + buildConstructor(); + buildMethodInit(); + buildPackMethod(); + buildUnpackMethod(); + buildConvertMethod(); + saveClass(directoryName); + } catch (Exception e) { + String code = getBuiltString(); + if(code != null) { + LOG.error("builder: " + code, e); + throw new TemplateBuildException("Cannot compile: " + code, e); + } else { + throw new TemplateBuildException(e); + } + } + } + + protected Template load(final String className) { + String tmplName = className + "_$$_Template"; + try { + Class tmplClass = getClass().getClassLoader().loadClass(tmplName); + return buildInstance(tmplClass); + } catch (ClassNotFoundException e) { + return null; + } catch (Exception e) { + String code = getBuiltString(); + if(code != null) { + LOG.error("builder: " + code, e); + throw new TemplateBuildException("Cannot compile: " + code, e); + } else { + throw new TemplateBuildException(e); + } + } + } } \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java index 439371d7..8d97689f 100644 --- a/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/CustomTemplateBuilder.java @@ -31,12 +31,13 @@ public abstract class CustomTemplateBuilder implements TemplateBuilder { public abstract IFieldEntryReader getFieldEntryReader(); public abstract Template buildTemplate(Class targetClass , IFieldEntry[] entries); - - public Template buildTemplate(Class targetClass ,FieldOption implicitOption ){ + + public Template buildTemplate(Class targetClass, FieldOption implicitOption ){ checkValidation(targetClass); return buildTemplate(targetClass, getFieldEntryReader().readFieldEntries(targetClass, implicitOption)); } + public Template buildTemplate(Class targetClass, FieldList flist) throws NoSuchFieldException { checkValidation(targetClass); return buildTemplate(targetClass, getFieldEntryReader().convertFieldEntries(targetClass, flist)); @@ -48,20 +49,29 @@ public abstract class CustomTemplateBuilder implements TemplateBuilder { IFieldEntryReader reader = getFieldEntryReader(); FieldOption implicitOption = reader.readImplicitFieldOption(targetClass); checkValidation(targetClass); - IFieldEntry[] entries = reader.readFieldEntries(targetClass, implicitOption); - - return buildTemplate(targetClass,entries); + return buildTemplate(targetClass, entries); } - private void checkValidation(Class targetClass) { + + protected void checkValidation(Class targetClass) { if(targetClass.isInterface()) { - throw new TemplateBuildException("cannot build template of interface"); + throw new TemplateBuildException("Cannot build template of interface"); } if(targetClass.isArray()) { - throw new TemplateBuildException("cannot build template of array class"); + throw new TemplateBuildException("Cannot build template of array class"); } if(targetClass.isPrimitive()) { - throw new TemplateBuildException("cannot build template of primitive type"); + throw new TemplateBuildException("Cannot build template of primitive type"); } } + + @Override + public void writeTemplate(Type targetType, String directoryName) { + throw new UnsupportedOperationException(targetType.toString()); + } + + @Override + public Template loadTemplate(Type targetType) { + return null; + } } \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/builder/JavassistTemplate.java b/java/src/main/java/org/msgpack/template/builder/JavassistTemplate.java deleted file mode 100644 index 84b8cc1b..00000000 --- a/java/src/main/java/org/msgpack/template/builder/JavassistTemplate.java +++ /dev/null @@ -1,31 +0,0 @@ -// -// MessagePack for Java -// -// Copyright (C) 2009-2011 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.builder; - -import org.msgpack.AbstractTemplate; -import org.msgpack.Template; - -public abstract class JavassistTemplate extends AbstractTemplate { - public Class targetClass; - public Template[] templates; - - public JavassistTemplate(Class targetClass, Template[] templates) { - this.targetClass = targetClass; - this.templates = templates; - } -} \ No newline at end of file diff --git a/java/src/main/java/org/msgpack/template/builder/JavassistTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/JavassistTemplateBuilder.java index a001bf45..f174f03d 100644 --- a/java/src/main/java/org/msgpack/template/builder/JavassistTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/JavassistTemplateBuilder.java @@ -18,6 +18,7 @@ package org.msgpack.template.builder; import java.lang.Thread; +import java.lang.reflect.Type; import org.msgpack.*; @@ -29,11 +30,22 @@ import javassist.NotFoundException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.msgpack.template.FieldEntryReader; +import org.msgpack.template.FieldOption; import org.msgpack.template.IFieldEntry; import org.msgpack.template.IFieldEntryReader; import org.msgpack.template.TemplateRegistry; public class JavassistTemplateBuilder extends CustomTemplateBuilder { + public static abstract class JavassistTemplate extends AbstractTemplate { + public Class targetClass; + public Template[] templates; + + public JavassistTemplate(Class targetClass, Template[] templates) { + this.targetClass = targetClass; + this.templates = templates; + } + } + private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class); private static JavassistTemplateBuilder instance; @@ -49,27 +61,24 @@ public class JavassistTemplateBuilder extends CustomTemplateBuilder { getInstance().pool.appendClassPath(new LoaderClassPath(cl)); } - IFieldEntryReader reader = new FieldEntryReader(); - + public void setFieldEntryReader(IFieldEntryReader reader){ this.reader = reader; } - + BuildContextFactory buildContextFactory = new BuildContextFactory() { - @Override public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) { return new BuildContext(builder); } }; + public void setBuildContextFactory(BuildContextFactory factory){ this.buildContextFactory = factory; } - - - + public JavassistTemplateBuilder() { pool = new ClassPool(); boolean appended = false; @@ -96,6 +105,7 @@ public class JavassistTemplateBuilder extends CustomTemplateBuilder { pool.appendSystemPath(); } } + /** * Replace FieldEntryReader and BuilderContextFactory. * you can replace field entry rules and generated codes easily. @@ -108,7 +118,6 @@ public class JavassistTemplateBuilder extends CustomTemplateBuilder { this.buildContextFactory = buildContextFactory; } - protected ClassPool pool; private int seqId = 0; @@ -125,7 +134,6 @@ public class JavassistTemplateBuilder extends CustomTemplateBuilder { return seqId++; } - @Override public Template buildTemplate(Class targetClass, IFieldEntry[] entries) { // FIXME private / packagefields @@ -136,10 +144,15 @@ public class JavassistTemplateBuilder extends CustomTemplateBuilder { // f.setAccessible(true); // } //} + Template[] tmpls = toTemplate(entries); + BuildContextBase bc = getBuildContextFacotry().createBuildContext(this); + return bc.buildTemplate(targetClass, entries, tmpls); + } - Template[] tmpls = new Template[entries.length]; - for(int i=0; i < entries.length; i++) { - IFieldEntry e = entries[i]; + private static Template[] toTemplate(IFieldEntry[] from) { + Template[] tmpls = new Template[from.length]; + for(int i=0; i < from.length; i++) { + IFieldEntry e = from[i]; if(!e.isAvailable()) { tmpls[i] = null; } else { @@ -147,9 +160,7 @@ public class JavassistTemplateBuilder extends CustomTemplateBuilder { tmpls[i] = tmpl; } } - - BuildContextBase bc = getBuildContextFacotry().createBuildContext(this); - return bc.buildTemplate(targetClass, entries, tmpls); + return tmpls; } @Override @@ -161,60 +172,36 @@ public class JavassistTemplateBuilder extends CustomTemplateBuilder { return buildContextFactory; } - - /* - static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate { - JavassistOrdinalEnumTemplate(Enum[] entries) { - super(entries); - } + @Override + public void writeTemplate(Type targetType, String directoryName) { + Class targetClass = (Class)targetType; + IFieldEntryReader reader = getFieldEntryReader(); + FieldOption implicitOption = reader.readImplicitFieldOption(targetClass); + checkValidation(targetClass); + IFieldEntry[] entries = reader.readFieldEntries(targetClass, implicitOption); + writeTemplate(targetClass, entries, directoryName); + } + + private void writeTemplate(Class targetClass, IFieldEntry[] entries, String directoryName) { + Template[] tmpls = toTemplate(entries); + BuildContextBase bc = getBuildContextFacotry().createBuildContext(this); + bc.writeTemplate(targetClass, entries, tmpls, directoryName); } @Override - public void writeOrdinalEnumTemplateClass(Class targetClass, Enum[] entires, String directoryName) { - throw new UnsupportedOperationException("not supported yet.");// TODO + public Template loadTemplate(Type targetType) { + Class targetClass = (Class)targetType; + IFieldEntryReader reader = getFieldEntryReader(); + FieldOption implicitOption = reader.readImplicitFieldOption(targetClass); + checkValidation(targetClass); + IFieldEntry[] entries = reader.readFieldEntries(targetClass, implicitOption); + return loadTemplate(targetClass, entries); } - public Template buildOrdinalEnumTemplate(Class targetClass, Enum[] entries) { - return new JavassistOrdinalEnumTemplate(entries); + private Template loadTemplate(Class targetClass, IFieldEntry[] entries) { + Template[] tmpls = toTemplate(entries); + BuildContextBase bc = getBuildContextFacotry().createBuildContext(this); + return bc.loadTemplate(targetClass, entries, tmpls); } - - @Override - public void writeArrayTemplateClass(Type arrayType, Type genericBaseType, - Class baseClass, int dim, String directoryName) { - throw new UnsupportedOperationException("not supported yet.");//TODO - } - - public Template buildArrayTemplate(Type arrayType, Type genericBaseType, Class baseClass, int dim) { - if(dim == 1) { - if(baseClass == boolean.class) { - return BooleanArrayTemplate.getInstance(); - } else if(baseClass == short.class) { - return ShortArrayTemplate.getInstance(); - } else if(baseClass == int.class) { - return IntArrayTemplate.getInstance(); - } else if(baseClass == long.class) { - return LongArrayTemplate.getInstance(); - } else if(baseClass == float.class) { - return FloatArrayTemplate.getInstance(); - } else if(baseClass == double.class) { - return DoubleArrayTemplate.getInstance(); - } else { - // FIXME - Template baseTemplate = TemplateRegistry.lookup(genericBaseType); - return new ReflectionTemplateBuilder.ReflectionObjectArrayTemplate(baseClass, baseTemplate); - } - } else if(dim == 2) { - // FIXME - Class componentClass = Array.newInstance(baseClass, 0).getClass(); - Template componentTemplate = buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1); - return new ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); - } else { - // FIXME - ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate componentTemplate = (ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate) - buildArrayTemplate(arrayType, genericBaseType, baseClass, dim-1); - Class componentClass = Array.newInstance(componentTemplate.getComponentClass(), 0).getClass(); - return new ReflectionTemplateBuilder.ReflectionMultidimentionalArrayTemplate(componentClass, componentTemplate); - } - }*/ } diff --git a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java index 471defd4..61f29838 100644 --- a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilder.java @@ -77,10 +77,20 @@ public class OrdinalEnumTemplateBuilder implements TemplateBuilder{ return new ReflectionOrdinalEnumTemplate(entries); } + private void checkOrdinalEnumValidation(Class targetClass) { if(!targetClass.isEnum()) { throw new TemplateBuildException("tried to build ordinal enum template of non-enum class"); } } + @Override + public void writeTemplate(Type targetType, String directoryName) { + throw new UnsupportedOperationException(targetType.toString()); + } + + @Override + public Template loadTemplate(Type targetType) { + return null; + } } diff --git a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilderSelector.java b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilderSelector.java index 6e612097..38ff7c4f 100644 --- a/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilderSelector.java +++ b/java/src/main/java/org/msgpack/template/builder/OrdinalEnumTemplateBuilderSelector.java @@ -23,7 +23,7 @@ import org.msgpack.annotation.MessagePackOrdinalEnum; public class OrdinalEnumTemplateBuilderSelector implements BuilderSelector { - public static final String NAME = "OrdinalEnumBuilder"; + public static final String NAME = "OrdinalEnumTemplateBuilder"; OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder(); diff --git a/java/src/main/java/org/msgpack/template/builder/ReflectionTemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/ReflectionTemplateBuilder.java index 30bdda38..6d875015 100644 --- a/java/src/main/java/org/msgpack/template/builder/ReflectionTemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/ReflectionTemplateBuilder.java @@ -21,7 +21,12 @@ import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Modifier; -import org.msgpack.*; +import org.msgpack.AbstractTemplate; +import org.msgpack.MessagePackObject; +import org.msgpack.MessageTypeException; +import org.msgpack.Packer; +import org.msgpack.Template; +import org.msgpack.Unpacker; import org.msgpack.template.FieldEntry; import org.msgpack.template.FieldEntryReader; import org.msgpack.template.IFieldEntry; @@ -412,7 +417,6 @@ public class ReflectionTemplateBuilder extends CustomTemplateBuilder { res[i] = new ObjectFieldEntry(e, tmpl); } } - return new ReflectionTemplate(targetClass, res); } } diff --git a/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java index 7c2533a1..0846ac41 100644 --- a/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java +++ b/java/src/main/java/org/msgpack/template/builder/TemplateBuilder.java @@ -23,5 +23,9 @@ import org.msgpack.Template; public interface TemplateBuilder { Template buildTemplate(Type targetType); + + void writeTemplate(Type targetType, String directoryName); + + Template loadTemplate(Type targetType); } diff --git a/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java b/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java index 8ca113b4..af99e06c 100644 --- a/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java +++ b/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java @@ -17,56 +17,58 @@ // package org.msgpack.util; -import org.msgpack.template.TemplateBuildException; +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.TemplateBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TemplatePrecompiler { private static final Logger LOG = LoggerFactory.getLogger(TemplatePrecompiler.class); - public static void write(Class target, String directoryName) { - if (target.isEnum()) { - throw new UnsupportedOperationException("Not supported yet."); - } else { - //TemplateBuilder.writeClass(target, directoryName); - } - LOG.info("finished writing .class file of template class for " + target.getName()); - } + //private static final String SRC = "msgpack.template.srcdir"; - private String directoryName; + private static final String DIST = "msgpack.template.distdir"; - private String[] classNames; + //private static final String DEFAULT_SRC = "."; + + private static final String DEFAULT_DIST = "."; private TemplatePrecompiler() { } - private void parseOpts(final String[] args) {// TODO - if (args.length == 0) { - usage(); - } + public void saveTemplates(final String[] classFileNames) throws IOException { + throw new UnsupportedOperationException("Not supported yet.");// TODO } - private void usage() {// TODO - System.err.println("java org.msgpack.template.TemplateClassWriter "); - System.err.println(""); + public void saveTemplateClass(Class targetClass) throws IOException { + LOG.info("Saving template of " + targetClass.getName() + "..."); + Properties props = System.getProperties(); + String distDirName = getDirName(props, DIST, DEFAULT_DIST); + if (targetClass.isEnum()) { + throw new UnsupportedOperationException("Enum not supported yet: " + targetClass.getName()); + } else { + TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetClass); + builder.writeTemplate(targetClass, distDirName); + } + LOG.info("Saved .class file of template class of " + targetClass.getName()); } - private void writeTemplateClasses() { - ClassLoader cl = this.getClass().getClassLoader();// TODO - for (String className : classNames) { - Class origClass = null; - try { - origClass = cl.loadClass(className); - } catch (ClassNotFoundException e) { - throw new TemplateBuildException(e); - } - write(origClass, directoryName); + private String getDirName(Properties props, String dirName, String defaultDirName) + throws IOException { + String dName = props.getProperty(dirName, defaultDirName); + File d = new File(dName); + if (!d.isDirectory() && !d.exists()) { + throw new IOException("Directory not exists: " + dName); } + return d.getAbsolutePath(); } public static void main(final String[] args) throws Exception { - TemplatePrecompiler writer = new TemplatePrecompiler(); - writer.parseOpts(args); - writer.writeTemplateClasses(); + TemplatePrecompiler compiler = new TemplatePrecompiler();// TODO + compiler.saveTemplates(args); } } diff --git a/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala index 784c9e93..7e39baa0 100644 --- a/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala +++ b/scala/src/main/scala/org/msgpack/JavassistTypeScalaTemplateBuilder.scala @@ -7,7 +7,8 @@ import java.lang.Class import collection.immutable.{ListMap, TreeMap} import java.lang.reflect.{Type, Modifier, Method, Field} import java.lang.annotation.{Annotation => JavaAnnotation} -import builder.{JavassistTemplateBuilder, JavassistTemplate, BuildContextBase, BuildContext} +import builder.{JavassistTemplateBuilder, BuildContextBase, BuildContext} +import builder.JavassistTemplateBuilder.JavassistTemplate import scala.collection.JavaConverters._ ; /* @@ -26,6 +27,23 @@ import scala.collection.JavaConverters._ var templates : Array[Template] = null var minimumArrayLength : Int = 0 + def writeTemplate(targetClass : Class[_] , entries : Array[IFieldEntry], + templates : Array[Template], directoryName : String) = { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + write(this.origName, directoryName); + } + + def loadTemplate(targetClass : Class[_] , entries : Array[IFieldEntry], templates : Array[Template]) = { + this.entries = entries; + this.templates = templates; + this.origClass = targetClass; + this.origName = this.origClass.getName(); + load(this.origName); + } + def buildTemplate(targetClass : Class[_] , entries : Array[IFieldEntry], templates : Array[Template]) = { this.entries = entries; this.templates = templates; From 65ddd1a455eb975e6a88f87b4e89759e57289f10 Mon Sep 17 00:00:00 2001 From: Muga Nishizawa Date: Sun, 10 Apr 2011 02:33:46 +0900 Subject: [PATCH 51/53] java: add test program for TemplatePrecompiler --- .../msgpack/template/TemplateRegistry.java | 46 +++++--- .../org/msgpack/util/TemplatePrecompiler.java | 26 +++-- .../TestTemplateBuilderPackUnpack.java | 5 - .../msgpack/util/TestTemplatePrecompiler.java | 110 ++++++++++++++++++ 4 files changed, 154 insertions(+), 33 deletions(-) create mode 100644 java/src/test/java/org/msgpack/util/TestTemplatePrecompiler.java diff --git a/java/src/main/java/org/msgpack/template/TemplateRegistry.java b/java/src/main/java/org/msgpack/template/TemplateRegistry.java index 4c4f87b6..5d869a06 100644 --- a/java/src/main/java/org/msgpack/template/TemplateRegistry.java +++ b/java/src/main/java/org/msgpack/template/TemplateRegistry.java @@ -29,7 +29,6 @@ import org.msgpack.Template; public class TemplateRegistry { private static Map map; private static Map genericMap; - private static BuilderSelectorRegistry builderSelectorRegistry; static { @@ -41,38 +40,43 @@ public class TemplateRegistry { public static void register(Class target) { TemplateBuilder builder = builderSelectorRegistry.select(target); - if(builder != null){ + if (builder != null) { register(target,builder.buildTemplate(target)); - }else{ + } else { register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target)); } } public static void register(Class target, FieldOption implicitOption) { TemplateBuilder builder = builderSelectorRegistry.select(target); - if(builder != null && builder instanceof CustomTemplateBuilder){ + if (builder != null && builder instanceof CustomTemplateBuilder) { register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, implicitOption)); - }else{ + } else { throw new TemplateBuildException("Cannot build template with filed option"); } } public static void register(Class target, FieldList flist) throws NoSuchFieldException { TemplateBuilder builder = builderSelectorRegistry.select(target); - if(builder != null && builder instanceof CustomTemplateBuilder){ + if (builder != null && builder instanceof CustomTemplateBuilder) { register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, flist)); - }else{ + } else { throw new TemplateBuildException("Cannot build template with filed list"); } } public static synchronized void register(Type rawType, Template tmpl) { - if(rawType instanceof ParameterizedType) { + if (rawType instanceof ParameterizedType) { rawType = ((ParameterizedType)rawType).getRawType(); } map.put(rawType, tmpl); } + public static boolean unregister(Class target) { + Template tmpl = map.remove(target); + return tmpl != null; + } + public static synchronized void registerGeneric(Type rawType, GenericTemplate gtmpl) { if(rawType instanceof ParameterizedType) { rawType = ((ParameterizedType)rawType).getRawType(); @@ -81,22 +85,27 @@ public class TemplateRegistry { } public static synchronized Template lookup(Type targetType) { - return lookupImpl(targetType, false, true); + return lookupImpl(targetType, true, false, true); } public static synchronized Template lookup(Type targetType, boolean forceBuild) { - return lookupImpl(targetType, forceBuild, true); + return lookupImpl(targetType, true, forceBuild, true); + } + + public static synchronized Template lookup(Type targetType, boolean forceLoad, boolean forceBuild) { + return lookupImpl(targetType, forceLoad, forceBuild, true); } public static synchronized Template tryLookup(Type targetType) { - return lookupImpl(targetType, false, false); + return lookupImpl(targetType, true, false, false); } public static synchronized Template tryLookup(Type targetType, boolean forceBuild) { - return lookupImpl(targetType, forceBuild, false); + return lookupImpl(targetType, true, forceBuild, false); } - private static synchronized Template lookupImpl(Type targetType, boolean forceBuild, boolean fallbackDefault) { + private static synchronized Template lookupImpl(Type targetType, + boolean forceLoad, boolean forceBuild, boolean fallbackDefault) { Template tmpl; if(targetType instanceof ParameterizedType) { @@ -115,10 +124,13 @@ public class TemplateRegistry { // find match TemplateBuilder TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetType); - if(builder != null){ - tmpl = builder.loadTemplate(targetType); - if (tmpl != null) { - return tmpl; + if (builder != null) { + if (forceLoad) { + tmpl = builder.loadTemplate(targetType); + if (tmpl != null) { + register(targetType, tmpl); + return tmpl; + } } tmpl = builder.buildTemplate(targetType); diff --git a/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java b/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java index af99e06c..d1d23f6c 100644 --- a/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java +++ b/java/src/main/java/org/msgpack/util/TemplatePrecompiler.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.util.Properties; import org.msgpack.template.builder.BuilderSelectorRegistry; +import org.msgpack.template.builder.JavassistTemplateBuilder; import org.msgpack.template.builder.TemplateBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,35 +30,39 @@ import org.slf4j.LoggerFactory; public class TemplatePrecompiler { private static final Logger LOG = LoggerFactory.getLogger(TemplatePrecompiler.class); - //private static final String SRC = "msgpack.template.srcdir"; + //public static final String SRC = "msgpack.template.srcdir"; - private static final String DIST = "msgpack.template.distdir"; + public static final String DIST = "msgpack.template.distdir"; - //private static final String DEFAULT_SRC = "."; + //public static final String DEFAULT_SRC = "."; - private static final String DEFAULT_DIST = "."; + public static final String DEFAULT_DIST = "."; + + private static TemplatePrecompiler INSTANCE = null; private TemplatePrecompiler() { } - public void saveTemplates(final String[] classFileNames) throws IOException { + public static void saveTemplates(final String[] classFileNames) throws IOException { throw new UnsupportedOperationException("Not supported yet.");// TODO } - public void saveTemplateClass(Class targetClass) throws IOException { + public static void saveTemplateClass(Class targetClass) throws IOException { + if (INSTANCE != null) { + INSTANCE = new TemplatePrecompiler(); + } LOG.info("Saving template of " + targetClass.getName() + "..."); Properties props = System.getProperties(); String distDirName = getDirName(props, DIST, DEFAULT_DIST); if (targetClass.isEnum()) { throw new UnsupportedOperationException("Enum not supported yet: " + targetClass.getName()); } else { - TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetClass); - builder.writeTemplate(targetClass, distDirName); + new JavassistTemplateBuilder().writeTemplate(targetClass, distDirName); } LOG.info("Saved .class file of template class of " + targetClass.getName()); } - private String getDirName(Properties props, String dirName, String defaultDirName) + private static String getDirName(Properties props, String dirName, String defaultDirName) throws IOException { String dName = props.getProperty(dirName, defaultDirName); File d = new File(dName); @@ -68,7 +73,6 @@ public class TemplatePrecompiler { } public static void main(final String[] args) throws Exception { - TemplatePrecompiler compiler = new TemplatePrecompiler();// TODO - compiler.saveTemplates(args); + TemplatePrecompiler.saveTemplates(args); } } diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java index 9ac94ef7..b938ab20 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java @@ -1,7 +1,5 @@ package org.msgpack.template; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.nio.ByteBuffer; @@ -15,16 +13,13 @@ import org.junit.Test; import org.msgpack.MessagePack; import org.msgpack.MessagePackable; -import org.msgpack.MessagePacker; import org.msgpack.MessageTypeException; import org.msgpack.MessageUnpackable; import org.msgpack.Packer; -import org.msgpack.Template; import org.msgpack.Unpacker; import org.msgpack.annotation.MessagePackMessage; import org.msgpack.annotation.MessagePackOrdinalEnum; import org.msgpack.annotation.Optional; -import org.msgpack.template.TestTemplateBuilderPackConvert.SampleInterface; import org.msgpack.template.builder.BuilderSelectorRegistry; import org.msgpack.template.builder.TemplateBuilder; diff --git a/java/src/test/java/org/msgpack/util/TestTemplatePrecompiler.java b/java/src/test/java/org/msgpack/util/TestTemplatePrecompiler.java new file mode 100644 index 00000000..e99c5da1 --- /dev/null +++ b/java/src/test/java/org/msgpack/util/TestTemplatePrecompiler.java @@ -0,0 +1,110 @@ +package org.msgpack.util; + +import org.junit.Test; +import static org.junit.Assert.*; +import org.msgpack.MessagePack; +import org.msgpack.MessageTypeException; +import org.msgpack.template.TemplateRegistry; + +public class TestTemplatePrecompiler { + + @Test + public void testPrimitiveTypeFields00() throws Exception { + System.getProperties().setProperty(TemplatePrecompiler.DIST, "./target/test-classes"); + Class c = PrimitiveTypeFieldsClass.class; + TemplatePrecompiler.saveTemplateClass(PrimitiveTypeFieldsClass.class); + + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + src.f0 = (byte) 0; + src.f1 = 1; + src.f2 = 2; + src.f3 = 3; + src.f4 = 4; + src.f5 = 5; + src.f6 = false; + + try { + MessagePack.pack(src); + fail(); + } catch (Exception e) { + assertTrue(e instanceof MessageTypeException); + assertTrue(TemplateRegistry.unregister(c)); + } + try { + TemplateRegistry.lookup(c, true, true); + byte[] raw = MessagePack.pack(src); + PrimitiveTypeFieldsClass dst = MessagePack.unpack(raw, 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); + } finally { + TemplateRegistry.unregister(c); + } + } + + @Test + public void testPrimitiveTypeFields01() throws Exception { + System.getProperties().setProperty(TemplatePrecompiler.DIST, "./target/test-classes"); + Class c = PrimitiveTypeFieldsClass.class; + TemplatePrecompiler.saveTemplateClass(PrimitiveTypeFieldsClass.class); + + PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass(); + + try { + MessagePack.pack(src); + fail(); + } catch (Exception e) { + assertTrue(e instanceof MessageTypeException); + assertTrue(TemplateRegistry.unregister(c)); + } + try { + TemplateRegistry.lookup(c, true, true); + byte[] raw = MessagePack.pack(src); + PrimitiveTypeFieldsClass dst = MessagePack.unpack(raw, 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); + } finally { + TemplateRegistry.unregister(c); + } + } + + @Test + public void testPrimitiveTypeFields02() throws Exception { + System.getProperties().setProperty(TemplatePrecompiler.DIST, "./target/test-classes"); + Class c = PrimitiveTypeFieldsClass.class; + TemplatePrecompiler.saveTemplateClass(PrimitiveTypeFieldsClass.class); + + PrimitiveTypeFieldsClass src = null; + MessagePack.pack(src); + try { + TemplateRegistry.lookup(c, true, true); + byte[] raw = MessagePack.pack(src); + PrimitiveTypeFieldsClass dst = MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class); + assertEquals(src, dst); + } finally { + TemplateRegistry.unregister(c); + } + } + + public static class PrimitiveTypeFieldsClass { + public byte f0; + public short f1; + public int f2; + public long f3; + public float f4; + public double f5; + public boolean f6; + + public PrimitiveTypeFieldsClass() { + } + } +} From c6d9bbd7b0e206b2cc69417bb3ed2a8cfa5899a5 Mon Sep 17 00:00:00 2001 From: FURUHASHI Sadayuki Date: Tue, 12 Apr 2011 18:39:54 +0900 Subject: [PATCH 52/53] MSGPACK-7 fixed test cases; iteration order of HashMap is not defined by JDK 5/6 specification --- ...ionTemplateBuilderJavaBeansPackUnpack.java | 23 ++++++------------ ...tReflectionTemplateBuilderPackConvert.java | 24 ++++++------------- ...stReflectionTemplateBuilderPackUnpack.java | 24 ++++++------------- ...estTemplateBuilderJavaBeansPackUnpack.java | 22 ++++++----------- .../TestTemplateBuilderPackConvert.java | 24 ++++++------------- .../TestTemplateBuilderPackUnpack.java | 24 ++++++------------- 6 files changed, 42 insertions(+), 99 deletions(-) diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java index 0bd6f71a..e894ad65 100644 --- a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderJavaBeansPackUnpack.java @@ -826,7 +826,7 @@ public class TestReflectionTemplateBuilderJavaBeansPackUnpack extends TestCase { SampleOptionalListTypes dst = MessagePack.unpack(raw, SampleOptionalListTypes.class); - assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(0, 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)); @@ -1013,22 +1013,18 @@ public class TestReflectionTemplateBuilderJavaBeansPackUnpack extends TestCase { SampleMapTypes dst = MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } @@ -1097,21 +1093,16 @@ public class TestReflectionTemplateBuilderJavaBeansPackUnpack extends TestCase { assertEquals(src.f0.size(), dst.f0.size()); assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java index 93523228..a514216d 100644 --- a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackConvert.java @@ -612,22 +612,18 @@ public class TestReflectionTemplateBuilderPackConvert extends TestCase { SampleMapTypes dst = MessagePack.unpack(raw).convert(SampleMapTypes.class); + assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } @@ -668,24 +664,18 @@ public class TestReflectionTemplateBuilderPackConvert extends TestCase { SampleOptionalMapTypes dst = MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); - assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(0, dst.f0.size()); assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } diff --git a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java index 64fc9785..53e48913 100644 --- a/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestReflectionTemplateBuilderPackUnpack.java @@ -617,22 +617,18 @@ public class TestReflectionTemplateBuilderPackUnpack extends TestCase { SampleMapTypes dst = MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(0, dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } @@ -673,24 +669,18 @@ public class TestReflectionTemplateBuilderPackUnpack extends TestCase { SampleOptionalMapTypes dst = MessagePack.unpack(raw, SampleOptionalMapTypes.class); - assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(0, dst.f0.size()); assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java index 1310cddb..b5262ac3 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderJavaBeansPackUnpack.java @@ -1038,22 +1038,18 @@ public class TestTemplateBuilderJavaBeansPackUnpack extends TestCase { SampleMapTypes dst = MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(0, dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } @@ -1119,24 +1115,20 @@ public class TestTemplateBuilderJavaBeansPackUnpack extends TestCase { SampleOptionalMapTypes dst = MessagePack.unpack(raw, SampleOptionalMapTypes.class); - assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(0, dst.f0.size()); assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java index f316e64a..d741c9bf 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackConvert.java @@ -598,22 +598,18 @@ public class TestTemplateBuilderPackConvert extends TestCase { SampleMapTypes dst = MessagePack.unpack(raw).convert(SampleMapTypes.class); + assertEquals(0, dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } @@ -654,24 +650,18 @@ public class TestTemplateBuilderPackConvert extends TestCase { SampleOptionalMapTypes dst = MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class); - assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(0, dst.f0.size()); assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } diff --git a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java index b938ab20..7fcf0d7c 100644 --- a/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java +++ b/java/src/test/java/org/msgpack/template/TestTemplateBuilderPackUnpack.java @@ -594,22 +594,18 @@ public class TestTemplateBuilderPackUnpack extends TestCase { SampleMapTypes dst = MessagePack.unpack(raw, SampleMapTypes.class); + assertEquals(0, dst.f0.size()); + assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } @@ -650,24 +646,18 @@ public class TestTemplateBuilderPackUnpack extends TestCase { SampleOptionalMapTypes dst = MessagePack.unpack(raw, SampleOptionalMapTypes.class); - assertEquals(src.f0.size(), dst.f0.size()); + assertEquals(0, dst.f0.size()); assertEquals(src.f1.size(), dst.f1.size()); Iterator srcf1 = src.f1.keySet().iterator(); - Iterator 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.f1.get(s1), dst.f1.get(s1)); } assertEquals(src.f2.size(), dst.f2.size()); Iterator srcf2 = src.f2.keySet().iterator(); - Iterator 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)); + assertEquals(src.f2.get(s2), dst.f2.get(s2)); } } From c58ce1a975ffcda089bbc835e035b0f670294a98 Mon Sep 17 00:00:00 2001 From: FURUHASHI Sadayuki Date: Tue, 12 Apr 2011 18:41:08 +0900 Subject: [PATCH 53/53] MSGPACK-7 added -source 1.5 -target 1.5 options to javac --- java/pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/pom.xml b/java/pom.xml index 39149d20..b9abaa41 100755 --- a/java/pom.xml +++ b/java/pom.xml @@ -63,8 +63,8 @@ maven-compiler-plugin - 1.6 - 1.6 + 1.5 + 1.5