mirror of
https://github.com/msgpack/msgpack-c
synced 2026-06-08 16:11:40 +00:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 076bd07f39 | |||
| 00e897503b | |||
| 2f3c47f385 | |||
| 2b28211701 | |||
| 46c794fc2e | |||
| 0408738b48 | |||
| eb8a338a0e | |||
| 23480bfe8a | |||
| 3384dbc92d | |||
| 8446549ed8 | |||
| 6a9f3ae71d | |||
| c58ce1a975 | |||
| c6d9bbd7b0 | |||
| 65ddd1a455 | |||
| 58c0fe0f91 | |||
| b96b62f2ac | |||
| 43fc0a52a6 | |||
| 4f3d9a1ded | |||
| b50ff920f0 | |||
| 983ae0c5a2 | |||
| 9d4db84987 | |||
| dfaa281476 | |||
| c1c25c455c | |||
| e65197f386 | |||
| ecbb8f8711 | |||
| 03aa736199 | |||
| 821b1f0384 | |||
| 233ad3aaff | |||
| 9c4812f4d4 | |||
| 337cc9fa78 | |||
| dfe29a0329 | |||
| 85e90aa81e | |||
| 86d30fe571 | |||
| 173302267f | |||
| 8e3ea8d26c | |||
| cb065563c2 | |||
| 27b89b237b | |||
| 21f0d0bfc4 | |||
| d5e583b09e | |||
| 15fb9bbcb2 | |||
| a03418ab12 | |||
| 035513844d | |||
| 193906b8ce | |||
| d354f2e8c2 | |||
| 24a8ee436f | |||
| 6e5f9404b7 | |||
| 64fe90aabb | |||
| 7e31d487e0 | |||
| ee16e2eb30 | |||
| 003fb3392f | |||
| 0e82278cd5 | |||
| 5b544248bc | |||
| d4d7495c0a | |||
| 8325cce44c | |||
| ee0debc5b3 | |||
| 8f1bd12a17 | |||
| fccf1016e4 | |||
| 1b010a082b | |||
| 324f215316 | |||
| ace4f1e7f0 | |||
| 5c5f16f148 | |||
| f50855d5c0 | |||
| 86917b0ba7 | |||
| 7201fcbe0f | |||
| 83f1735fbb | |||
| 80fd8e70f0 | |||
| 698c1c2b7a | |||
| 5d3287f5aa | |||
| 6990fe6f51 | |||
| 0b81068368 | |||
| d439b1495b |
@@ -1,3 +1,8 @@
|
|||||||
*.o
|
*.o
|
||||||
*.so
|
*.so
|
||||||
ruby/Makefile
|
ruby/Makefile
|
||||||
|
*.5
|
||||||
|
*.8
|
||||||
|
*.6
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
|
|
||||||
|
2011-04-24 version 0.5.6:
|
||||||
|
|
||||||
|
* #42 fixes double-free problem on msgpack_unpacker_release_zone
|
||||||
|
|
||||||
2011-02-24 version 0.5.5:
|
2011-02-24 version 0.5.5:
|
||||||
|
|
||||||
* eliminates dependency of winsock2.h header
|
* eliminates dependency of winsock2.h header
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
AC_INIT(src/object.cpp)
|
AC_INIT(src/object.cpp)
|
||||||
AC_CONFIG_AUX_DIR(ac)
|
AC_CONFIG_AUX_DIR(ac)
|
||||||
AM_INIT_AUTOMAKE(msgpack, 0.5.5)
|
AM_INIT_AUTOMAKE(msgpack, 0.5.6)
|
||||||
AC_CONFIG_HEADER(config.h)
|
AC_CONFIG_HEADER(config.h)
|
||||||
|
|
||||||
AC_SUBST(CFLAGS)
|
AC_SUBST(CFLAGS)
|
||||||
|
|||||||
+1
-1
@@ -12,7 +12,7 @@ preprocess() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
if [ "$1" == "clean" ];then
|
if [ "$1" = "clean" ];then
|
||||||
rm -f src/msgpack/type/tuple.hpp
|
rm -f src/msgpack/type/tuple.hpp
|
||||||
rm -f src/msgpack/type/define.hpp
|
rm -f src/msgpack/type/define.hpp
|
||||||
rm -f src/msgpack/zone.hpp
|
rm -f src/msgpack/zone.hpp
|
||||||
|
|||||||
@@ -105,9 +105,6 @@ int msgpack_pack_object(msgpack_packer* pk, msgpack_object d);
|
|||||||
#define msgpack_pack_inline_func_cint(name) \
|
#define msgpack_pack_inline_func_cint(name) \
|
||||||
inline int msgpack_pack ## 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) \
|
#define msgpack_pack_inline_func_fixint(name) \
|
||||||
inline int msgpack_pack_fix ## name
|
inline int msgpack_pack_fix ## name
|
||||||
|
|
||||||
|
|||||||
@@ -258,17 +258,7 @@ inline object unpacker::data()
|
|||||||
|
|
||||||
inline zone* unpacker::release_zone()
|
inline zone* unpacker::release_zone()
|
||||||
{
|
{
|
||||||
if(!msgpack_unpacker_flush_zone(this)) {
|
return static_cast<msgpack::zone*>(msgpack_unpacker_release_zone(static_cast<msgpack_unpacker*>(this)));
|
||||||
throw std::bad_alloc();
|
|
||||||
}
|
|
||||||
|
|
||||||
zone* r = new zone();
|
|
||||||
|
|
||||||
msgpack_zone old = *base::z;
|
|
||||||
*base::z = *r;
|
|
||||||
*static_cast<msgpack_zone*>(r) = old;
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void unpacker::reset_zone()
|
inline void unpacker::reset_zone()
|
||||||
|
|||||||
@@ -337,6 +337,7 @@ msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac)
|
|||||||
|
|
||||||
msgpack_zone* old = mpac->z;
|
msgpack_zone* old = mpac->z;
|
||||||
mpac->z = r;
|
mpac->z = r;
|
||||||
|
CTX_CAST(mpac->ctx)->user.z = mpac->z;
|
||||||
|
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
AM_CPPFLAGS = -I../src
|
AM_CPPFLAGS = -I../src
|
||||||
AM_C_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 = \
|
check_PROGRAMS = \
|
||||||
zone \
|
zone \
|
||||||
|
|||||||
+65
-24
@@ -7,9 +7,21 @@ TEST(streaming, basic)
|
|||||||
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
|
msgpack_sbuffer* buffer = msgpack_sbuffer_new();
|
||||||
|
|
||||||
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
|
msgpack_packer* pk = msgpack_packer_new(buffer, msgpack_sbuffer_write);
|
||||||
|
|
||||||
|
// 1, 2, 3, "raw", ["data"], {0.3: 0.4}
|
||||||
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
|
EXPECT_EQ(0, msgpack_pack_int(pk, 1));
|
||||||
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
|
EXPECT_EQ(0, msgpack_pack_int(pk, 2));
|
||||||
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
|
EXPECT_EQ(0, msgpack_pack_int(pk, 3));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_raw(pk, 3));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_raw_body(pk, "raw", 3));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_array(pk, 1));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_raw(pk, 4));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_raw_body(pk, "data", 4));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_map(pk, 1));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_float(pk, 0.4));
|
||||||
|
EXPECT_EQ(0, msgpack_pack_double(pk, 0.8));
|
||||||
|
int max_count = 6;
|
||||||
|
|
||||||
msgpack_packer_free(pk);
|
msgpack_packer_free(pk);
|
||||||
|
|
||||||
const char* input = buffer->data;
|
const char* input = buffer->data;
|
||||||
@@ -22,36 +34,65 @@ TEST(streaming, basic)
|
|||||||
msgpack_unpacked_init(&result);
|
msgpack_unpacked_init(&result);
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
while(count < 3) {
|
while(count < max_count) {
|
||||||
|
bool unpacked = false;
|
||||||
|
|
||||||
msgpack_unpacker_reserve_buffer(&pac, 32*1024);
|
msgpack_unpacker_reserve_buffer(&pac, 32*1024);
|
||||||
|
|
||||||
/* read buffer into msgpack_unapcker_buffer(&pac) upto
|
while(!unpacked) {
|
||||||
* msgpack_unpacker_buffer_capacity(&pac) bytes. */
|
/* read buffer into msgpack_unapcker_buffer(&pac) upto
|
||||||
size_t len = 1;
|
* msgpack_unpacker_buffer_capacity(&pac) bytes. */
|
||||||
memcpy(msgpack_unpacker_buffer(&pac), input, len);
|
memcpy(msgpack_unpacker_buffer(&pac), input, 1);
|
||||||
input += len;
|
input += 1;
|
||||||
|
|
||||||
msgpack_unpacker_buffer_consumed(&pac, len);
|
EXPECT_TRUE(input <= eof);
|
||||||
|
|
||||||
while(msgpack_unpacker_next(&pac, &result)) {
|
msgpack_unpacker_buffer_consumed(&pac, 1);
|
||||||
msgpack_object obj = result.data;
|
|
||||||
switch(count++) {
|
while(msgpack_unpacker_next(&pac, &result)) {
|
||||||
case 0:
|
unpacked = 1;
|
||||||
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, result.data.type);
|
msgpack_object obj = result.data;
|
||||||
EXPECT_EQ(1, result.data.via.u64);
|
msgpack_object e;
|
||||||
break;
|
switch(count++) {
|
||||||
case 1:
|
case 0:
|
||||||
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, result.data.type);
|
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type);
|
||||||
EXPECT_EQ(2, result.data.via.u64);
|
EXPECT_EQ(1, obj.via.u64);
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 1:
|
||||||
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, result.data.type);
|
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type);
|
||||||
EXPECT_EQ(3, result.data.via.u64);
|
EXPECT_EQ(2, obj.via.u64);
|
||||||
return;
|
break;
|
||||||
|
case 2:
|
||||||
|
EXPECT_EQ(MSGPACK_OBJECT_POSITIVE_INTEGER, obj.type);
|
||||||
|
EXPECT_EQ(3, obj.via.u64);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
EXPECT_EQ(MSGPACK_OBJECT_RAW, obj.type);
|
||||||
|
EXPECT_EQ(std::string("raw",3), std::string(obj.via.raw.ptr, obj.via.raw.size));
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
EXPECT_EQ(MSGPACK_OBJECT_ARRAY, obj.type);
|
||||||
|
EXPECT_EQ(1, obj.via.array.size);
|
||||||
|
e = obj.via.array.ptr[0];
|
||||||
|
EXPECT_EQ(MSGPACK_OBJECT_RAW, e.type);
|
||||||
|
EXPECT_EQ(std::string("data",4), std::string(e.via.raw.ptr, e.via.raw.size));
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
EXPECT_EQ(MSGPACK_OBJECT_MAP, obj.type);
|
||||||
|
EXPECT_EQ(1, obj.via.map.size);
|
||||||
|
e = obj.via.map.ptr[0].key;
|
||||||
|
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, e.type);
|
||||||
|
ASSERT_FLOAT_EQ(0.4, (float)e.via.dec);
|
||||||
|
e = obj.via.map.ptr[0].val;
|
||||||
|
EXPECT_EQ(MSGPACK_OBJECT_DOUBLE, e.type);
|
||||||
|
ASSERT_DOUBLE_EQ(0.8, e.via.dec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPECT_TRUE(input < eof);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
msgpack_unpacker_destroy(&pac);
|
||||||
|
msgpack_unpacked_destroy(&result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+11
@@ -0,0 +1,11 @@
|
|||||||
|
include $(GOROOT)/src/Make.inc
|
||||||
|
|
||||||
|
TARG=msgpack
|
||||||
|
|
||||||
|
GOFILES=pack.go unpack.go
|
||||||
|
|
||||||
|
include $(GOROOT)/src/Make.pkg
|
||||||
|
|
||||||
|
%: install %.go
|
||||||
|
$(GC) $*.go
|
||||||
|
$(LD) -o $@ $*.$O
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
package msgpack_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
. "msgpack"
|
||||||
|
"testing"
|
||||||
|
"bytes"
|
||||||
|
"reflect"
|
||||||
|
"math"
|
||||||
|
);
|
||||||
|
|
||||||
|
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.UintValue:
|
||||||
|
_rhs, ok := rhs.(*reflect.UintValue)
|
||||||
|
return ok && _lhs.Get() == _rhs.Get()
|
||||||
|
case *reflect.IntValue:
|
||||||
|
_rhs, ok := rhs.(*reflect.IntValue)
|
||||||
|
return ok && _lhs.Get() == _rhs.Get()
|
||||||
|
case *reflect.FloatValue:
|
||||||
|
_rhs, ok := rhs.(*reflect.FloatValue)
|
||||||
|
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 } {
|
||||||
|
_, 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 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(-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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+591
@@ -0,0 +1,591 @@
|
|||||||
|
package msgpack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
"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) })
|
||||||
|
}
|
||||||
|
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) })
|
||||||
|
} else if value < 256 {
|
||||||
|
return writer.Write([]byte { 0xcc, byte(value) })
|
||||||
|
}
|
||||||
|
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) })
|
||||||
|
} 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) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) })
|
||||||
|
} 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) {
|
||||||
|
// Packs a given value and writes it into the specified writer.
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) })
|
||||||
|
}
|
||||||
|
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) })
|
||||||
|
} else if value < -32 {
|
||||||
|
return writer.Write([]byte { 0xd0, byte(value) })
|
||||||
|
}
|
||||||
|
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) })
|
||||||
|
} 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) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) })
|
||||||
|
} 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) })
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
return PackInt32(writer, *(*int32)(unsafe.Pointer(&value)))
|
||||||
|
case 8:
|
||||||
|
return PackInt64(writer, *(*int64)(unsafe.Pointer(&value)))
|
||||||
|
}
|
||||||
|
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 {
|
||||||
|
code = 0xc3
|
||||||
|
} else {
|
||||||
|
code = 0xc2
|
||||||
|
}
|
||||||
|
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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
return PackUint32Array(writer, *(*[]uint32)(unsafe.Pointer(&value)))
|
||||||
|
case 8:
|
||||||
|
return PackUint64Array(writer, *(*[]uint64)(unsafe.Pointer(&value)))
|
||||||
|
}
|
||||||
|
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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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:
|
||||||
|
return PackInt32Array(writer, *(*[]int32)(unsafe.Pointer(&value)))
|
||||||
|
case 8:
|
||||||
|
return PackInt64Array(writer, *(*[]int64)(unsafe.Pointer(&value)))
|
||||||
|
}
|
||||||
|
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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
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) })
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
case *reflect.BoolValue: return PackBool(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)
|
||||||
|
case *reflect.InterfaceValue:
|
||||||
|
__value := reflect.NewValue(_value.Interface())
|
||||||
|
_, ok := __value.(*reflect.InterfaceValue)
|
||||||
|
if !ok {
|
||||||
|
return PackValue(writer, __value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
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 []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)
|
||||||
|
default:
|
||||||
|
return PackValue(writer, reflect.NewValue(value))
|
||||||
|
}
|
||||||
|
return 0, nil // never get here
|
||||||
|
}
|
||||||
+288
@@ -0,0 +1,288 @@
|
|||||||
|
package msgpack
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"unsafe"
|
||||||
|
"strconv"
|
||||||
|
"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[3]), 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[3]), 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 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
|
||||||
|
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 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
|
||||||
|
|
||||||
|
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 {
|
||||||
|
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 {
|
||||||
|
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
|
||||||
|
} 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 }
|
||||||
|
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 }
|
||||||
|
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 }
|
||||||
|
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 }
|
||||||
|
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 }
|
||||||
|
default:
|
||||||
|
panic("unsupported code: " + strconv.Itoa(int(c)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
+13
-11
@@ -1,12 +1,12 @@
|
|||||||
Name: msgpack
|
Name: msgpack
|
||||||
Version: 0.4.0.1
|
Version: 0.6.1.1
|
||||||
Synopsis: A Haskell binding to MessagePack
|
Synopsis: A Haskell implementation of MessagePack
|
||||||
Description:
|
Description:
|
||||||
A Haskell binding to MessagePack <http://msgpack.org/>
|
A Haskell implementation of MessagePack <http://msgpack.org/>
|
||||||
|
|
||||||
License: BSD3
|
License: BSD3
|
||||||
License-File: LICENSE
|
License-File: LICENSE
|
||||||
Copyright: Copyright (c) 2009-2010, Hideyuki Tanaka
|
Copyright: Copyright (c) 2009-2011, Hideyuki Tanaka
|
||||||
Category: Data
|
Category: Data
|
||||||
Author: Hideyuki Tanaka
|
Author: Hideyuki Tanaka
|
||||||
Maintainer: Hideyuki Tanaka <tanaka.hideyuki@gmail.com>
|
Maintainer: Hideyuki Tanaka <tanaka.hideyuki@gmail.com>
|
||||||
@@ -21,28 +21,30 @@ Extra-source-files:
|
|||||||
|
|
||||||
Library
|
Library
|
||||||
Build-depends: base >=4 && <5,
|
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,
|
bytestring >= 0.9 && < 0.10,
|
||||||
vector >= 0.6.0 && < 0.6.1,
|
text >= 0.11 && < 0.12,
|
||||||
iteratee >= 0.4 && < 0.5,
|
vector >= 0.7 && < 0.8,
|
||||||
attoparsec >= 0.8.1 && < 0.8.2,
|
attoparsec >= 0.8 && < 0.9,
|
||||||
binary >= 0.5.0 && < 0.5.1,
|
binary >= 0.5.0 && < 0.5.1,
|
||||||
data-binary-ieee754 >= 0.4 && < 0.5,
|
data-binary-ieee754 >= 0.4 && < 0.5,
|
||||||
deepseq >= 1.1 && <1.2,
|
deepseq >= 1.1 && <1.2,
|
||||||
template-haskell >= 2.4 && < 2.5
|
template-haskell >= 2.4 && < 2.6
|
||||||
|
|
||||||
Ghc-options: -Wall
|
Ghc-options: -Wall
|
||||||
Hs-source-dirs: src
|
Hs-source-dirs: src
|
||||||
|
|
||||||
Exposed-modules:
|
Exposed-modules:
|
||||||
Data.MessagePack
|
Data.MessagePack
|
||||||
|
Data.MessagePack.Assoc
|
||||||
Data.MessagePack.Pack
|
Data.MessagePack.Pack
|
||||||
Data.MessagePack.Unpack
|
Data.MessagePack.Unpack
|
||||||
Data.MessagePack.Object
|
Data.MessagePack.Object
|
||||||
Data.MessagePack.Iteratee
|
|
||||||
Data.MessagePack.Derive
|
Data.MessagePack.Derive
|
||||||
|
|
||||||
|
Other-modules:
|
||||||
|
Data.MessagePack.Internal.Utf8
|
||||||
|
|
||||||
Source-repository head
|
Source-repository head
|
||||||
Type: git
|
Type: git
|
||||||
Location: git://github.com/msgpack/msgpack.git
|
Location: git://github.com/msgpack/msgpack.git
|
||||||
|
|||||||
@@ -13,91 +13,15 @@
|
|||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
module Data.MessagePack(
|
module Data.MessagePack(
|
||||||
|
module Data.MessagePack.Assoc,
|
||||||
module Data.MessagePack.Pack,
|
module Data.MessagePack.Pack,
|
||||||
module Data.MessagePack.Unpack,
|
module Data.MessagePack.Unpack,
|
||||||
module Data.MessagePack.Object,
|
module Data.MessagePack.Object,
|
||||||
module Data.MessagePack.Iteratee,
|
|
||||||
module Data.MessagePack.Derive,
|
module Data.MessagePack.Derive,
|
||||||
|
|
||||||
-- * Pack functions
|
|
||||||
packToString,
|
|
||||||
packToHandle,
|
|
||||||
packToHandle',
|
|
||||||
packToFile,
|
|
||||||
|
|
||||||
-- * Unpack functions
|
|
||||||
unpackFromString,
|
|
||||||
unpackFromHandle,
|
|
||||||
unpackFromFile,
|
|
||||||
unpackFromStringI,
|
|
||||||
unpackFromHandleI,
|
|
||||||
unpackFromFileI,
|
|
||||||
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import qualified Control.Monad.CatchIO as CIO
|
import Data.MessagePack.Assoc
|
||||||
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.Pack
|
import Data.MessagePack.Pack
|
||||||
import Data.MessagePack.Unpack
|
import Data.MessagePack.Unpack
|
||||||
import Data.MessagePack.Object
|
import Data.MessagePack.Object
|
||||||
import Data.MessagePack.Iteratee
|
|
||||||
import Data.MessagePack.Derive
|
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)
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|
||||||
@@ -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
|
||||||
@@ -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 -> m (Either SomeException (Bool, B.ByteString))
|
|
||||||
readSome bufSize h = 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)
|
|
||||||
Right bs ->
|
|
||||||
return $ Right (True, 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)
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
{-# Language TypeSynonymInstances #-}
|
{-# Language TypeSynonymInstances #-}
|
||||||
{-# Language FlexibleInstances #-}
|
{-# Language FlexibleInstances #-}
|
||||||
{-# Language OverlappingInstances #-}
|
|
||||||
{-# Language IncoherentInstances #-}
|
{-# Language IncoherentInstances #-}
|
||||||
{-# Language DeriveDataTypeable #-}
|
{-# Language DeriveDataTypeable #-}
|
||||||
|
|
||||||
@@ -33,22 +32,30 @@ import Control.Monad
|
|||||||
import Control.Monad.Trans.Error ()
|
import Control.Monad.Trans.Error ()
|
||||||
import qualified Data.Attoparsec as A
|
import qualified Data.Attoparsec as A
|
||||||
import qualified Data.ByteString as B
|
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.Typeable
|
||||||
|
|
||||||
|
import Data.MessagePack.Assoc
|
||||||
import Data.MessagePack.Pack
|
import Data.MessagePack.Pack
|
||||||
import Data.MessagePack.Unpack
|
import Data.MessagePack.Unpack
|
||||||
|
import Data.MessagePack.Internal.Utf8
|
||||||
|
|
||||||
-- | Object Representation of MessagePack data.
|
-- | Object Representation of MessagePack data.
|
||||||
data Object =
|
data Object
|
||||||
ObjectNil
|
= ObjectNil
|
||||||
| ObjectBool Bool
|
| ObjectBool Bool
|
||||||
| ObjectInteger Int
|
| ObjectInteger Int
|
||||||
|
| ObjectFloat Float
|
||||||
| ObjectDouble Double
|
| ObjectDouble Double
|
||||||
| ObjectRAW B.ByteString
|
| ObjectRAW B.ByteString
|
||||||
| ObjectArray [Object]
|
| ObjectArray [Object]
|
||||||
| ObjectMap [(Object, Object)]
|
| ObjectMap [(Object, Object)]
|
||||||
deriving (Show, Eq, Ord, Typeable)
|
deriving (Show, Eq, Ord, Typeable)
|
||||||
|
|
||||||
|
|
||||||
instance NFData Object where
|
instance NFData Object where
|
||||||
rnf obj =
|
rnf obj =
|
||||||
@@ -56,21 +63,24 @@ instance NFData Object where
|
|||||||
ObjectNil -> ()
|
ObjectNil -> ()
|
||||||
ObjectBool b -> rnf b
|
ObjectBool b -> rnf b
|
||||||
ObjectInteger n -> rnf n
|
ObjectInteger n -> rnf n
|
||||||
|
ObjectFloat f -> rnf f
|
||||||
ObjectDouble d -> rnf d
|
ObjectDouble d -> rnf d
|
||||||
ObjectRAW bs -> bs `seq` ()
|
ObjectRAW bs -> bs `seq` ()
|
||||||
ObjectArray a -> rnf a
|
ObjectArray a -> rnf a
|
||||||
ObjectMap m -> rnf m
|
ObjectMap m -> rnf m
|
||||||
|
|
||||||
|
|
||||||
instance Unpackable Object where
|
instance Unpackable Object where
|
||||||
get =
|
get =
|
||||||
A.choice
|
A.choice
|
||||||
[ liftM ObjectInteger get
|
[ liftM ObjectInteger get
|
||||||
, liftM (\() -> ObjectNil) get
|
, liftM (\() -> ObjectNil) get
|
||||||
, liftM ObjectBool get
|
, liftM ObjectBool get
|
||||||
|
, liftM ObjectFloat get
|
||||||
, liftM ObjectDouble get
|
, liftM ObjectDouble get
|
||||||
, liftM ObjectRAW get
|
, liftM ObjectRAW get
|
||||||
, liftM ObjectArray get
|
, liftM ObjectArray get
|
||||||
, liftM ObjectMap get
|
, liftM (ObjectMap . unAssoc) get
|
||||||
]
|
]
|
||||||
|
|
||||||
instance Packable Object where
|
instance Packable Object where
|
||||||
@@ -82,6 +92,8 @@ instance Packable Object where
|
|||||||
put ()
|
put ()
|
||||||
ObjectBool b ->
|
ObjectBool b ->
|
||||||
put b
|
put b
|
||||||
|
ObjectFloat f ->
|
||||||
|
put f
|
||||||
ObjectDouble d ->
|
ObjectDouble d ->
|
||||||
put d
|
put d
|
||||||
ObjectRAW raw ->
|
ObjectRAW raw ->
|
||||||
@@ -89,7 +101,7 @@ instance Packable Object where
|
|||||||
ObjectArray arr ->
|
ObjectArray arr ->
|
||||||
put arr
|
put arr
|
||||||
ObjectMap m ->
|
ObjectMap m ->
|
||||||
put m
|
put $ Assoc m
|
||||||
|
|
||||||
-- | The class of types serializable to and from MessagePack object
|
-- | The class of types serializable to and from MessagePack object
|
||||||
class (Unpackable a, Packable a) => OBJECT a where
|
class (Unpackable a, Packable a) => OBJECT a where
|
||||||
@@ -137,14 +149,34 @@ instance OBJECT Double where
|
|||||||
tryFromObject (ObjectDouble d) = Right d
|
tryFromObject (ObjectDouble d) = Right d
|
||||||
tryFromObject _ = tryFromObjectError
|
tryFromObject _ = tryFromObjectError
|
||||||
|
|
||||||
|
instance OBJECT Float where
|
||||||
|
toObject = ObjectFloat
|
||||||
|
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
|
instance OBJECT B.ByteString where
|
||||||
toObject = ObjectRAW
|
toObject = ObjectRAW
|
||||||
tryFromObject (ObjectRAW bs) = Right bs
|
tryFromObject (ObjectRAW bs) = Right bs
|
||||||
tryFromObject _ = tryFromObjectError
|
tryFromObject _ = tryFromObjectError
|
||||||
|
|
||||||
instance OBJECT String where
|
instance OBJECT BL.ByteString where
|
||||||
toObject = toObject . C8.pack
|
toObject = ObjectRAW . fromLBS
|
||||||
tryFromObject obj = liftM C8.unpack $ tryFromObject obj
|
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
|
instance OBJECT a => OBJECT [a] where
|
||||||
toObject = ObjectArray . map toObject
|
toObject = ObjectArray . map toObject
|
||||||
@@ -285,11 +317,11 @@ instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5, OBJECT a6, OBJE
|
|||||||
tryFromObject _ =
|
tryFromObject _ =
|
||||||
tryFromObjectError
|
tryFromObjectError
|
||||||
|
|
||||||
instance (OBJECT a, OBJECT b) => OBJECT [(a, b)] where
|
instance (OBJECT a, OBJECT b) => OBJECT (Assoc [(a,b)]) where
|
||||||
toObject =
|
toObject =
|
||||||
ObjectMap . map (\(a, b) -> (toObject a, toObject b))
|
ObjectMap . map (\(a, b) -> (toObject a, toObject b)) . unAssoc
|
||||||
tryFromObject (ObjectMap mem) = do
|
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 _ =
|
tryFromObject _ =
|
||||||
tryFromObjectError
|
tryFromObjectError
|
||||||
|
|
||||||
@@ -299,3 +331,4 @@ instance OBJECT a => OBJECT (Maybe a) where
|
|||||||
|
|
||||||
tryFromObject ObjectNil = return Nothing
|
tryFromObject ObjectNil = return Nothing
|
||||||
tryFromObject obj = liftM Just $ tryFromObject obj
|
tryFromObject obj = liftM Just $ tryFromObject obj
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{-# Language FlexibleInstances #-}
|
{-# Language FlexibleInstances #-}
|
||||||
{-# Language IncoherentInstances #-}
|
{-# Language IncoherentInstances #-}
|
||||||
{-# Language OverlappingInstances #-}
|
|
||||||
{-# Language TypeSynonymInstances #-}
|
{-# Language TypeSynonymInstances #-}
|
||||||
|
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
@@ -28,17 +27,23 @@ import Data.Binary.Put
|
|||||||
import Data.Binary.IEEE754
|
import Data.Binary.IEEE754
|
||||||
import Data.Bits
|
import Data.Bits
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
import qualified Data.ByteString.Char8 as B8
|
import qualified Data.ByteString.Lazy as BL
|
||||||
import qualified Data.ByteString.Lazy as L
|
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 qualified Data.Vector as V
|
||||||
|
|
||||||
|
import Data.MessagePack.Assoc
|
||||||
|
import Data.MessagePack.Internal.Utf8
|
||||||
|
|
||||||
-- | Serializable class
|
-- | Serializable class
|
||||||
class Packable a where
|
class Packable a where
|
||||||
-- | Serialize a value
|
-- | Serialize a value
|
||||||
put :: a -> Put
|
put :: a -> Put
|
||||||
|
|
||||||
-- | Pack Haskell data to MessagePack string.
|
-- | Pack Haskell data to MessagePack string.
|
||||||
pack :: Packable a => a -> L.ByteString
|
pack :: Packable a => a -> BL.ByteString
|
||||||
pack = runPut . put
|
pack = runPut . put
|
||||||
|
|
||||||
instance Packable Int where
|
instance Packable Int where
|
||||||
@@ -81,23 +86,35 @@ instance Packable Bool where
|
|||||||
put True = putWord8 0xC3
|
put True = putWord8 0xC3
|
||||||
put False = putWord8 0xC2
|
put False = putWord8 0xC2
|
||||||
|
|
||||||
|
instance Packable Float where
|
||||||
|
put f = do
|
||||||
|
putWord8 0xCA
|
||||||
|
putFloat32be f
|
||||||
|
|
||||||
instance Packable Double where
|
instance Packable Double where
|
||||||
put d = do
|
put d = do
|
||||||
putWord8 0xCB
|
putWord8 0xCB
|
||||||
putFloat64be d
|
putFloat64be d
|
||||||
|
|
||||||
instance Packable String where
|
instance Packable String where
|
||||||
put = putString length (putByteString . B8.pack)
|
put = putString encodeUtf8 B.length putByteString
|
||||||
|
|
||||||
instance Packable B.ByteString where
|
instance Packable B.ByteString where
|
||||||
put = putString B.length putByteString
|
put = putString id B.length putByteString
|
||||||
|
|
||||||
instance Packable L.ByteString where
|
instance Packable BL.ByteString where
|
||||||
put = putString (fromIntegral . L.length) putLazyByteString
|
put = putString id (fromIntegral . BL.length) putLazyByteString
|
||||||
|
|
||||||
putString :: (s -> Int) -> (s -> Put) -> s -> Put
|
instance Packable T.Text where
|
||||||
putString lf pf str = do
|
put = putString T.encodeUtf8 B.length putByteString
|
||||||
case lf str of
|
|
||||||
|
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
|
len | len <= 31 -> do
|
||||||
putWord8 $ 0xA0 .|. fromIntegral len
|
putWord8 $ 0xA0 .|. fromIntegral len
|
||||||
len | len < 0x10000 -> do
|
len | len < 0x10000 -> do
|
||||||
@@ -106,7 +123,7 @@ putString lf pf str = do
|
|||||||
len -> do
|
len -> do
|
||||||
putWord8 0xDB
|
putWord8 0xDB
|
||||||
putWord32be $ fromIntegral len
|
putWord32be $ fromIntegral len
|
||||||
pf str
|
pf bs
|
||||||
|
|
||||||
instance Packable a => Packable [a] where
|
instance Packable a => Packable [a] where
|
||||||
put = putArray length (mapM_ put)
|
put = putArray length (mapM_ put)
|
||||||
@@ -159,11 +176,11 @@ putArray lf pf arr = do
|
|||||||
putWord32be $ fromIntegral len
|
putWord32be $ fromIntegral len
|
||||||
pf arr
|
pf arr
|
||||||
|
|
||||||
instance (Packable k, Packable v) => Packable [(k, v)] where
|
instance (Packable k, Packable v) => Packable (Assoc [(k,v)]) where
|
||||||
put = putMap length (mapM_ putPair)
|
put = putMap length (mapM_ putPair) . unAssoc
|
||||||
|
|
||||||
instance (Packable k, Packable v) => Packable (V.Vector (k, v)) where
|
instance (Packable k, Packable v) => Packable (Assoc (V.Vector (k,v))) where
|
||||||
put = putMap V.length (V.mapM_ putPair)
|
put = putMap V.length (V.mapM_ putPair) . unAssoc
|
||||||
|
|
||||||
putPair :: (Packable a, Packable b) => (a, b) -> Put
|
putPair :: (Packable a, Packable b) => (a, b) -> Put
|
||||||
putPair (a, b) = put a >> put b
|
putPair (a, b) = put a >> put b
|
||||||
@@ -184,3 +201,4 @@ putMap lf pf m = do
|
|||||||
instance Packable a => Packable (Maybe a) where
|
instance Packable a => Packable (Maybe a) where
|
||||||
put Nothing = put ()
|
put Nothing = put ()
|
||||||
put (Just a) = put a
|
put (Just a) = put a
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{-# Language FlexibleInstances #-}
|
{-# Language FlexibleInstances #-}
|
||||||
{-# Language IncoherentInstances #-}
|
{-# Language IncoherentInstances #-}
|
||||||
{-# Language OverlappingInstances #-}
|
|
||||||
{-# Language TypeSynonymInstances #-}
|
{-# Language TypeSynonymInstances #-}
|
||||||
{-# Language DeriveDataTypeable #-}
|
{-# Language DeriveDataTypeable #-}
|
||||||
|
|
||||||
@@ -37,14 +36,20 @@ import Data.Binary.Get
|
|||||||
import Data.Binary.IEEE754
|
import Data.Binary.IEEE754
|
||||||
import Data.Bits
|
import Data.Bits
|
||||||
import qualified Data.ByteString as B
|
import qualified Data.ByteString as B
|
||||||
import qualified Data.ByteString.Char8 as B8
|
import qualified Data.ByteString.Lazy as BL
|
||||||
import qualified Data.ByteString.Lazy as L
|
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.Int
|
||||||
import Data.Typeable
|
import Data.Typeable
|
||||||
import qualified Data.Vector as V
|
import qualified Data.Vector as V
|
||||||
import Data.Word
|
import Data.Word
|
||||||
import Text.Printf
|
import Text.Printf
|
||||||
|
|
||||||
|
import Data.MessagePack.Assoc
|
||||||
|
import Data.MessagePack.Internal.Utf8
|
||||||
|
|
||||||
-- | Deserializable class
|
-- | Deserializable class
|
||||||
class Unpackable a where
|
class Unpackable a where
|
||||||
-- | Deserialize a value
|
-- | Deserialize a value
|
||||||
@@ -56,8 +61,8 @@ class IsByteString s where
|
|||||||
instance IsByteString B.ByteString where
|
instance IsByteString B.ByteString where
|
||||||
toBS = id
|
toBS = id
|
||||||
|
|
||||||
instance IsByteString L.ByteString where
|
instance IsByteString BL.ByteString where
|
||||||
toBS = B.concat . L.toChunks
|
toBS = B.concat . BL.toChunks
|
||||||
|
|
||||||
-- | The exception of unpack
|
-- | The exception of unpack
|
||||||
data UnpackError =
|
data UnpackError =
|
||||||
@@ -133,25 +138,38 @@ instance Unpackable Bool where
|
|||||||
_ ->
|
_ ->
|
||||||
fail $ printf "invlid bool tag: 0x%02X" c
|
fail $ printf "invlid bool tag: 0x%02X" c
|
||||||
|
|
||||||
instance Unpackable Double where
|
instance Unpackable Float where
|
||||||
get = do
|
get = do
|
||||||
c <- A.anyWord8
|
c <- A.anyWord8
|
||||||
case c of
|
case c of
|
||||||
0xCA ->
|
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 ->
|
0xCB ->
|
||||||
return . runGet getFloat64be . toLBS =<< A.take 8
|
return . runGet getFloat64be . toLBS =<< A.take 8
|
||||||
_ ->
|
_ ->
|
||||||
fail $ printf "invlid double tag: 0x%02X" c
|
fail $ printf "invlid double tag: 0x%02X" c
|
||||||
|
|
||||||
instance Unpackable String where
|
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
|
instance Unpackable B.ByteString where
|
||||||
get = parseString A.take
|
get = parseString A.take
|
||||||
|
|
||||||
instance Unpackable L.ByteString where
|
instance Unpackable BL.ByteString where
|
||||||
get = parseString (\n -> do bs <- A.take n; return $ L.fromChunks [bs])
|
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 :: (Int -> A.Parser a) -> A.Parser a
|
||||||
parseString aget = do
|
parseString aget = do
|
||||||
@@ -225,11 +243,11 @@ parseArray aget = do
|
|||||||
_ ->
|
_ ->
|
||||||
fail $ printf "invlid array tag: 0x%02X" c
|
fail $ printf "invlid array tag: 0x%02X" c
|
||||||
|
|
||||||
instance (Unpackable k, Unpackable v) => Unpackable [(k, v)] where
|
instance (Unpackable k, Unpackable v) => Unpackable (Assoc [(k,v)]) where
|
||||||
get = parseMap (flip replicateM parsePair)
|
get = liftM Assoc $ parseMap (flip replicateM parsePair)
|
||||||
|
|
||||||
instance (Unpackable k, Unpackable v) => Unpackable (V.Vector (k, v)) where
|
instance (Unpackable k, Unpackable v) => Unpackable (Assoc (V.Vector (k, v))) where
|
||||||
get = parseMap (flip V.replicateM parsePair)
|
get = liftM Assoc $ parseMap (flip V.replicateM parsePair)
|
||||||
|
|
||||||
parsePair :: (Unpackable k, Unpackable v) => A.Parser (k, v)
|
parsePair :: (Unpackable k, Unpackable v) => A.Parser (k, v)
|
||||||
parsePair = do
|
parsePair = do
|
||||||
@@ -303,6 +321,3 @@ parseInt32 = return . fromIntegral =<< parseUint32
|
|||||||
|
|
||||||
parseInt64 :: A.Parser Int64
|
parseInt64 :: A.Parser Int64
|
||||||
parseInt64 = return . fromIntegral =<< parseUint64
|
parseInt64 = return . fromIntegral =<< parseUint64
|
||||||
|
|
||||||
toLBS :: B.ByteString -> L.ByteString
|
|
||||||
toLBS bs = L.fromChunks [bs]
|
|
||||||
|
|||||||
+10
-4
@@ -7,6 +7,9 @@ import qualified Data.ByteString.Char8 as B
|
|||||||
import qualified Data.ByteString.Lazy.Char8 as L
|
import qualified Data.ByteString.Lazy.Char8 as L
|
||||||
import Data.MessagePack
|
import Data.MessagePack
|
||||||
|
|
||||||
|
instance Arbitrary a => Arbitrary (Assoc a) where
|
||||||
|
arbitrary = liftM Assoc arbitrary
|
||||||
|
|
||||||
mid :: (Packable a, Unpackable a) => a -> a
|
mid :: (Packable a, Unpackable a) => a -> a
|
||||||
mid = unpack . pack
|
mid = unpack . pack
|
||||||
|
|
||||||
@@ -36,10 +39,12 @@ prop_mid_pair4 a = a == mid a
|
|||||||
where types = a :: (Int, Int, Int, Int)
|
where types = a :: (Int, Int, Int, Int)
|
||||||
prop_mid_pair5 a = a == mid a
|
prop_mid_pair5 a = a == mid a
|
||||||
where types = a :: (Int, Int, Int, Int, Int)
|
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)]
|
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)]
|
where types = a :: [(String, String)]
|
||||||
|
prop_mid_map_string_int a = a == mid a
|
||||||
|
where types = a :: Assoc [(String,Int)]
|
||||||
|
|
||||||
tests =
|
tests =
|
||||||
[ testGroup "simple"
|
[ testGroup "simple"
|
||||||
@@ -56,8 +61,9 @@ tests =
|
|||||||
, testProperty "(int, int, int)" prop_mid_pair3
|
, testProperty "(int, int, int)" prop_mid_pair3
|
||||||
, testProperty "(int, int, int, int)" prop_mid_pair4
|
, testProperty "(int, int, int, int)" prop_mid_pair4
|
||||||
, testProperty "(int, int, int, int, int)" prop_mid_pair5
|
, testProperty "(int, int, int, int, int)" prop_mid_pair5
|
||||||
, testProperty "[(int, double)]" prop_mid_map_int_double
|
, testProperty "[(int, double)]" prop_mid_list_int_double
|
||||||
, testProperty "[(string, string)]" prop_mid_map_string_string
|
, testProperty "[(string, string)]" prop_mid_list_string_string
|
||||||
|
, testProperty "Assoc [(string, int)]" prop_mid_map_string_int
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,13 @@
|
|||||||
#Mon Apr 19 22:18:48 JST 2010
|
#Tue Apr 12 19:14:17 JST 2011
|
||||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
eclipse.preferences.version=1
|
||||||
eclipse.preferences.version=1
|
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||||
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.codegen.unusedLocal=preserve
|
||||||
|
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||||
|
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||||
|
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||||
|
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||||
|
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||||
|
org.eclipse.jdt.core.compiler.source=1.6
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1,4 +1,23 @@
|
|||||||
|
|
||||||
|
Release 0.5.2 - 2011/04/23
|
||||||
|
NEW FEATURES
|
||||||
|
MSGPACK-6 Added TemplatePrecompiler program
|
||||||
|
|
||||||
|
Added built-in templates of BigDecimal and Date classes.
|
||||||
|
|
||||||
|
Added @MessagePackBeans annotation that enables you to serialize/deserialize
|
||||||
|
JavaBeans.
|
||||||
|
|
||||||
|
BUG FIXES
|
||||||
|
MSGPACK-4 Fixes the deserialization routine of Long value
|
||||||
|
|
||||||
|
IMPROVEMENTS
|
||||||
|
#35 Improves handling of ClassLoader on Javassist template builder.
|
||||||
|
|
||||||
|
MSGPACK-7 Improves compatibility with Java 1.5. Now it runs on JRE 5.
|
||||||
|
It is tested on Jenkins CI: http://ci.msgpack.org/job/java-jre5/
|
||||||
|
|
||||||
|
|
||||||
Release 0.5.1 - 2010/12/14
|
Release 0.5.1 - 2010/12/14
|
||||||
BUG FIXES
|
BUG FIXES
|
||||||
Fixes cast error on GenericArrayType
|
Fixes cast error on GenericArrayType
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule="true" type="JAVA_MODULE" version="4">
|
||||||
|
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
|
||||||
|
<output url="file://$MODULE_DIR$/target/classes" />
|
||||||
|
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||||
|
<exclude-output />
|
||||||
|
<content url="file://$MODULE_DIR$">
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/src/test/java" isTestSource="true" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
|
</content>
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
<orderEntry type="library" scope="TEST" name="Maven: junit:junit:4.8.1" level="project" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
|
|
||||||
+19
-3
@@ -3,7 +3,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>org.msgpack</groupId>
|
<groupId>org.msgpack</groupId>
|
||||||
<artifactId>msgpack</artifactId>
|
<artifactId>msgpack</artifactId>
|
||||||
<version>0.5.1-devel</version>
|
<version>0.5.2-devel</version>
|
||||||
<description>MessagePack for Java</description>
|
<description>MessagePack for Java</description>
|
||||||
|
|
||||||
<name>MessagePack for Java</name>
|
<name>MessagePack for Java</name>
|
||||||
@@ -63,8 +63,8 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<configuration>
|
<configuration>
|
||||||
<source>1.6</source>
|
<source>1.5</source>
|
||||||
<target>1.6</target>
|
<target>1.5</target>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
@@ -81,6 +81,20 @@
|
|||||||
<connectionUrl>scm:git://github.com/msgpack/msgpack.git</connectionUrl>
|
<connectionUrl>scm:git://github.com/msgpack/msgpack.git</connectionUrl>
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
@@ -132,12 +146,14 @@
|
|||||||
<id>msgpack.org</id>
|
<id>msgpack.org</id>
|
||||||
<name>Repository at msgpack.org</name>
|
<name>Repository at msgpack.org</name>
|
||||||
<url>file://${project.build.directory}/website/maven2/</url>
|
<url>file://${project.build.directory}/website/maven2/</url>
|
||||||
|
<!--<url>${deploy-release-url}</url>-->
|
||||||
</repository>
|
</repository>
|
||||||
<snapshotRepository>
|
<snapshotRepository>
|
||||||
<uniqueVersion>true</uniqueVersion>
|
<uniqueVersion>true</uniqueVersion>
|
||||||
<id>msgpack.org</id>
|
<id>msgpack.org</id>
|
||||||
<name>Repository at msgpack.org</name>
|
<name>Repository at msgpack.org</name>
|
||||||
<url>file://${project.build.directory}/website/maven2/</url>
|
<url>file://${project.build.directory}/website/maven2/</url>
|
||||||
|
<!--<url>${deploy-snapshot-url}</url>-->
|
||||||
</snapshotRepository>
|
</snapshotRepository>
|
||||||
</distributionManagement>
|
</distributionManagement>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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 {
|
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||||
return convert(pac.unpackObject(), to);
|
return convert(pac.unpackObject(), to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -146,10 +146,10 @@ abstract class BufferedUnpackerImpl extends UnpackerImpl {
|
|||||||
advance(3);
|
advance(3);
|
||||||
return (int)castBuffer.getShort(0);
|
return (int)castBuffer.getShort(0);
|
||||||
case 0xd2: // signed int 32
|
case 0xd2: // signed int 32
|
||||||
more(4);
|
more(5);
|
||||||
castBuffer.rewind();
|
castBuffer.rewind();
|
||||||
castBuffer.put(buffer, offset+1, 4);
|
castBuffer.put(buffer, offset+1, 4);
|
||||||
advance(4);
|
advance(5);
|
||||||
return (int)castBuffer.getInt(0);
|
return (int)castBuffer.getInt(0);
|
||||||
case 0xd3: // signed int 64
|
case 0xd3: // signed int 64
|
||||||
more(9);
|
more(9);
|
||||||
@@ -215,10 +215,10 @@ abstract class BufferedUnpackerImpl extends UnpackerImpl {
|
|||||||
advance(3);
|
advance(3);
|
||||||
return (long)castBuffer.getShort(0);
|
return (long)castBuffer.getShort(0);
|
||||||
case 0xd2: // signed int 32
|
case 0xd2: // signed int 32
|
||||||
more(4);
|
more(5);
|
||||||
castBuffer.rewind();
|
castBuffer.rewind();
|
||||||
castBuffer.put(buffer, offset+1, 4);
|
castBuffer.put(buffer, offset+1, 4);
|
||||||
advance(4);
|
advance(5);
|
||||||
return (long)castBuffer.getInt(0);
|
return (long)castBuffer.getInt(0);
|
||||||
case 0xd3: // signed int 64
|
case 0xd3: // signed int 64
|
||||||
more(9);
|
more(9);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -22,7 +22,6 @@ import java.io.InputStream;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import org.msgpack.template.TemplateRegistry;
|
import org.msgpack.template.TemplateRegistry;
|
||||||
import org.msgpack.template.TemplateBuilder;
|
|
||||||
import org.msgpack.template.FieldList;
|
import org.msgpack.template.FieldList;
|
||||||
|
|
||||||
public class MessagePack {
|
public class MessagePack {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -18,6 +18,5 @@
|
|||||||
package org.msgpack;
|
package org.msgpack;
|
||||||
|
|
||||||
public interface MessagePackTemplateProvider {
|
public interface MessagePackTemplateProvider {
|
||||||
|
|
||||||
Template getTemplate();
|
Template getTemplate();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -18,5 +18,4 @@
|
|||||||
package org.msgpack;
|
package org.msgpack;
|
||||||
|
|
||||||
public interface Template extends MessagePacker, MessageUnpacker, MessageConverter {
|
public interface Template extends MessagePacker, MessageUnpacker, MessageConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -76,6 +76,11 @@ public class Templates {
|
|||||||
return TBigInteger;
|
return TBigInteger;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final Template TBigDecimal = BigDecimalTemplate.getInstance();
|
||||||
|
public static Template tBigDecimal() {
|
||||||
|
return TBigDecimal;
|
||||||
|
}
|
||||||
|
|
||||||
public static final Template TFloat = FloatTemplate.getInstance();
|
public static final Template TFloat = FloatTemplate.getInstance();
|
||||||
public static Template tFloat() {
|
public static Template tFloat() {
|
||||||
return TFloat;
|
return TFloat;
|
||||||
@@ -105,5 +110,10 @@ public class Templates {
|
|||||||
public static Template tByteBuffer() {
|
public static Template tByteBuffer() {
|
||||||
return TByteBuffer;
|
return TByteBuffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static final Template TDate = DateTemplate.getInstance();
|
||||||
|
public static Template tDate() {
|
||||||
|
return TDate;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Ignore {
|
public @interface Ignore {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Index {
|
public @interface Index {
|
||||||
int value();
|
int value();
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// 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.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;
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Nullable {
|
public @interface Nullable {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Optional {
|
public @interface Optional {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
|||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
public @interface Required {
|
public @interface Required {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -79,7 +79,7 @@ public class RawType extends MessagePackObject {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return bytes.hashCode();
|
return Arrays.hashCode(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
//
|
||||||
|
// 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.beans.PropertyDescriptor;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
//
|
||||||
|
// 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.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.Method;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List up Java beans property methods.
|
||||||
|
* @author takeshita
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class BeansFieldEntryReader implements IFieldEntryReader{
|
||||||
|
|
||||||
|
|
||||||
|
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException {
|
||||||
|
List<FieldList.Entry> 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<PropertyDescriptor> list = new ArrayList<PropertyDescriptor>();
|
||||||
|
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<? extends Annotation> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
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;
|
||||||
|
try {
|
||||||
|
pk.packString(temp.toString());
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
throw new MessageTypeException("target is null.", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with 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() {
|
public static void load() {
|
||||||
AnyTemplate.getInstance();
|
AnyTemplate.getInstance();
|
||||||
BigIntegerTemplate.getInstance();
|
BigIntegerTemplate.getInstance();
|
||||||
|
BigDecimalTemplate.getInstance();
|
||||||
BooleanArrayTemplate.getInstance();
|
BooleanArrayTemplate.getInstance();
|
||||||
BooleanTemplate.getInstance();
|
BooleanTemplate.getInstance();
|
||||||
ByteArrayTemplate.getInstance();
|
ByteArrayTemplate.getInstance();
|
||||||
@@ -28,6 +29,7 @@ public class BuiltInTemplateLoader {
|
|||||||
ByteTemplate.getInstance();
|
ByteTemplate.getInstance();
|
||||||
DoubleArrayTemplate.getInstance();
|
DoubleArrayTemplate.getInstance();
|
||||||
DoubleTemplate.getInstance();
|
DoubleTemplate.getInstance();
|
||||||
|
DateTemplate.getInstance();
|
||||||
FloatArrayTemplate.getInstance();
|
FloatArrayTemplate.getInstance();
|
||||||
FloatTemplate.getInstance();
|
FloatTemplate.getInstance();
|
||||||
IntArrayTemplate.getInstance();
|
IntArrayTemplate.getInstance();
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -50,7 +50,7 @@ public class DefaultTemplate implements Template {
|
|||||||
}
|
}
|
||||||
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||||
if(tmpl == this || tmpl == null) {
|
if(tmpl == this || tmpl == null) {
|
||||||
throw new MessageTypeException();
|
throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName());
|
||||||
}
|
}
|
||||||
tmpl.pack(pk, target);
|
tmpl.pack(pk, target);
|
||||||
}
|
}
|
||||||
@@ -69,7 +69,7 @@ public class DefaultTemplate implements Template {
|
|||||||
}
|
}
|
||||||
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||||
if(tmpl == this || tmpl == null) {
|
if(tmpl == this || tmpl == null) {
|
||||||
throw new MessageTypeException();
|
throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName());
|
||||||
}
|
}
|
||||||
return tmpl.unpack(pac, to);
|
return tmpl.unpack(pac, to);
|
||||||
}
|
}
|
||||||
@@ -88,7 +88,7 @@ public class DefaultTemplate implements Template {
|
|||||||
}
|
}
|
||||||
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||||
if(tmpl == this || tmpl == null) {
|
if(tmpl == this || tmpl == null) {
|
||||||
throw new MessageTypeException();
|
throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName());
|
||||||
}
|
}
|
||||||
return tmpl.convert(from, to);
|
return tmpl.convert(from, to);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,143 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,182 @@
|
|||||||
|
//
|
||||||
|
// 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.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<FieldList.Entry> 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<FieldEntry> indexed = new ArrayList<FieldEntry>();
|
||||||
|
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<Field[]> succ = new ArrayList<Field[]>();
|
||||||
|
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<? extends Annotation> with) {
|
||||||
|
return ao.getAnnotation(with) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -43,19 +43,19 @@ public class FieldList {
|
|||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isAvailable() {
|
public boolean isAvailable() {
|
||||||
return this.option != FieldOption.IGNORE;
|
return this.option != FieldOption.IGNORE;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isRequired() {
|
public boolean isRequired() {
|
||||||
return this.option == FieldOption.REQUIRED;
|
return this.option == FieldOption.REQUIRED;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isOptional() {
|
public boolean isOptional() {
|
||||||
return this.option == FieldOption.OPTIONAL;
|
return this.option == FieldOption.OPTIONAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isNullable() {
|
public boolean isNullable() {
|
||||||
return this.option == FieldOption.NULLABLE;
|
return this.option == FieldOption.NULLABLE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ public class FieldList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Entry> getList() {
|
public List<Entry> getList() {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// 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.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();
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// 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 interface IFieldEntryReader {
|
||||||
|
|
||||||
|
public IFieldEntry[] convertFieldEntries(Class<?> targetClass, FieldList flist) throws NoSuchFieldException;
|
||||||
|
public IFieldEntry[] readFieldEntries(Class<?> targetClass, FieldOption implicitOption);
|
||||||
|
public FieldOption readImplicitFieldOption(Class<?> targetClass) ;
|
||||||
|
}
|
||||||
@@ -1,592 +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.Array;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
import org.msgpack.*;
|
|
||||||
|
|
||||||
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 org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
public class JavassistTemplateBuilder extends TemplateBuilder {
|
|
||||||
private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class);
|
|
||||||
|
|
||||||
private static JavassistTemplateBuilder instance;
|
|
||||||
|
|
||||||
public synchronized static JavassistTemplateBuilder getInstance() {
|
|
||||||
if(instance == null) {
|
|
||||||
instance = new JavassistTemplateBuilder();
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void addClassLoader(ClassLoader cl) {
|
|
||||||
getInstance().pool.appendClassPath(new LoaderClassPath(cl));
|
|
||||||
}
|
|
||||||
|
|
||||||
private JavassistTemplateBuilder() {
|
|
||||||
this.pool = ClassPool.getDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ClassPool pool;
|
|
||||||
|
|
||||||
private int seqId = 0;
|
|
||||||
|
|
||||||
CtClass makeCtClass(String className) {
|
|
||||||
return pool.makeClass(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
CtClass getCtClass(String className) throws NotFoundException {
|
|
||||||
return pool.get(className);
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
// FIXME private / packagefields
|
|
||||||
//for(FieldEntry e : entries) {
|
|
||||||
// Field f = e.getField();
|
|
||||||
// int mod = f.getModifiers();
|
|
||||||
// if(!Modifier.isPublic(mod)) {
|
|
||||||
// f.setAccessible(true);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
Template[] tmpls = new Template[entries.length];
|
|
||||||
for(int i=0; i < entries.length; i++) {
|
|
||||||
FieldEntry e = entries[i];
|
|
||||||
if(!e.isAvailable()) {
|
|
||||||
tmpls[i] = null;
|
|
||||||
} else {
|
|
||||||
Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true);
|
|
||||||
tmpls[i] = tmpl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
BuildContext bc = new BuildContext(this);
|
|
||||||
return bc.buildTemplate(targetClass, entries, tmpls);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class JavassistOrdinalEnumTemplate extends ReflectionTemplateBuilder.ReflectionOrdinalEnumTemplate {
|
|
||||||
JavassistOrdinalEnumTemplate(Enum<?>[] entries) {
|
|
||||||
super(entries);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Template buildOrdinalEnumTemplate(Class<?> targetClass, Enum<?>[] entries) {
|
|
||||||
return new JavassistOrdinalEnumTemplate(entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
|
|||||||
@@ -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<FieldList.Entry> 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<FieldEntry> indexed = new ArrayList<FieldEntry>();
|
|
||||||
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<Field[]> succ = new ArrayList<Field[]>();
|
|
||||||
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<? extends Annotation> with) {
|
|
||||||
return ao.getAnnotation(with) != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -20,48 +20,63 @@ package org.msgpack.template;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.lang.reflect.GenericArrayType;
|
|
||||||
import java.lang.reflect.ParameterizedType;
|
import java.lang.reflect.ParameterizedType;
|
||||||
import java.lang.annotation.Annotation;
|
import org.msgpack.template.builder.BuilderSelectorRegistry;
|
||||||
import org.msgpack.annotation.MessagePackMessage;
|
import org.msgpack.template.builder.CustomTemplateBuilder;
|
||||||
import org.msgpack.annotation.MessagePackDelegate;
|
import org.msgpack.template.builder.TemplateBuilder;
|
||||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
|
||||||
import org.msgpack.Template;
|
import org.msgpack.Template;
|
||||||
import org.msgpack.Templates;
|
|
||||||
|
|
||||||
public class TemplateRegistry {
|
public class TemplateRegistry {
|
||||||
private static Map<Type, Template> map;
|
private static Map<Type, Template> map;
|
||||||
private static Map<Type, GenericTemplate> genericMap;
|
private static Map<Type, GenericTemplate> genericMap;
|
||||||
|
private static BuilderSelectorRegistry builderSelectorRegistry;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
map = new HashMap<Type, Template>();
|
map = new HashMap<Type, Template>();
|
||||||
genericMap = new HashMap<Type, GenericTemplate>();
|
genericMap = new HashMap<Type, GenericTemplate>();
|
||||||
BuiltInTemplateLoader.load();
|
BuiltInTemplateLoader.load();
|
||||||
|
builderSelectorRegistry = BuilderSelectorRegistry.getInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void register(Class<?> target) { // auto-detect
|
public static void register(Class<?> target) {
|
||||||
if(target.isEnum()) {
|
TemplateBuilder builder = builderSelectorRegistry.select(target);
|
||||||
register(target, TemplateBuilder.buildOrdinalEnum(target));
|
if (builder != null) {
|
||||||
|
register(target,builder.buildTemplate(target));
|
||||||
} else {
|
} else {
|
||||||
register(target, TemplateBuilder.build(target));
|
register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void register(Class<?> target, FieldOption implicitOption) {
|
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 {
|
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) {
|
public static synchronized void register(Type rawType, Template tmpl) {
|
||||||
if(rawType instanceof ParameterizedType) {
|
if (rawType instanceof ParameterizedType) {
|
||||||
rawType = ((ParameterizedType)rawType).getRawType();
|
rawType = ((ParameterizedType)rawType).getRawType();
|
||||||
}
|
}
|
||||||
map.put(rawType, tmpl);
|
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) {
|
public static synchronized void registerGeneric(Type rawType, GenericTemplate gtmpl) {
|
||||||
if(rawType instanceof ParameterizedType) {
|
if(rawType instanceof ParameterizedType) {
|
||||||
rawType = ((ParameterizedType)rawType).getRawType();
|
rawType = ((ParameterizedType)rawType).getRawType();
|
||||||
@@ -70,22 +85,27 @@ public class TemplateRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static synchronized Template lookup(Type targetType) {
|
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) {
|
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) {
|
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) {
|
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;
|
Template tmpl;
|
||||||
|
|
||||||
if(targetType instanceof ParameterizedType) {
|
if(targetType instanceof ParameterizedType) {
|
||||||
@@ -102,35 +122,26 @@ public class TemplateRegistry {
|
|||||||
return tmpl;
|
return tmpl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(targetType instanceof GenericArrayType) {
|
// find match TemplateBuilder
|
||||||
// GenericArrayType is not a Class<?>
|
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetType);
|
||||||
tmpl = TemplateBuilder.buildArray(targetType);
|
if (builder != null) {
|
||||||
register(targetType, tmpl);
|
if (forceLoad) {
|
||||||
return tmpl;
|
tmpl = builder.loadTemplate(targetType);
|
||||||
|
if (tmpl != null) {
|
||||||
|
register(targetType, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tmpl = builder.buildTemplate(targetType);
|
||||||
|
if (tmpl != null) {
|
||||||
|
register(targetType, tmpl);
|
||||||
|
return tmpl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> target = (Class<?>)targetType;
|
Class<?> target = (Class<?>)targetType;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(Class<?> i : target.getInterfaces()) {
|
for(Class<?> i : target.getInterfaces()) {
|
||||||
tmpl = map.get(i);
|
tmpl = map.get(i);
|
||||||
if(tmpl != null) {
|
if(tmpl != null) {
|
||||||
@@ -150,7 +161,7 @@ public class TemplateRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(forceBuild) {
|
if(forceBuild) {
|
||||||
tmpl = TemplateBuilder.build(target);
|
tmpl = builderSelectorRegistry.getForceBuilder().buildTemplate(target);
|
||||||
register(target, tmpl);
|
register(target, tmpl);
|
||||||
return tmpl;
|
return tmpl;
|
||||||
}
|
}
|
||||||
@@ -174,7 +185,7 @@ public class TemplateRegistry {
|
|||||||
}
|
}
|
||||||
return new DefaultTemplate((Class<?>)parameterizedType.getRawType(), parameterizedType);
|
return new DefaultTemplate((Class<?>)parameterizedType.getRawType(), parameterizedType);
|
||||||
} else {
|
} 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,13 +204,5 @@ public class TemplateRegistry {
|
|||||||
|
|
||||||
return gtmpl.build(tmpls);
|
return gtmpl.build(tmpls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isAnnotated(Class<?> ao, Class<? extends Annotation> with) {
|
|
||||||
return ao.getAnnotation(with) != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setTemplateBuilder(TemplateBuilder builder) {
|
|
||||||
TemplateBuilder.setInstance(builder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import org.msgpack.annotation.MessagePackMessage;
|
||||||
|
|
||||||
|
public class AnnotationTemplateBuilderSelector implements BuilderSelector{
|
||||||
|
|
||||||
|
public static final String NAME = "AnnotationTemplateBuilder";
|
||||||
|
|
||||||
|
TemplateBuilder builder;
|
||||||
|
|
||||||
|
public AnnotationTemplateBuilderSelector(TemplateBuilder builder){
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName(){
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matchType(Type targetType) {
|
||||||
|
Class<?> targetClass = (Class<?>)targetType;
|
||||||
|
return isAnnotated(targetClass, MessagePackMessage.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAnnotated(Class<?> targetClass, Class<? extends Annotation> with) {
|
||||||
|
return targetClass.getAnnotation(with) != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
//
|
||||||
|
// 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 java.io.IOException;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.GenericArrayType;
|
||||||
|
import java.lang.reflect.ParameterizedType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
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.IntArrayTemplate;
|
||||||
|
import org.msgpack.template.LongArrayTemplate;
|
||||||
|
import org.msgpack.template.ShortArrayTemplate;
|
||||||
|
import org.msgpack.template.TemplateRegistry;
|
||||||
|
|
||||||
|
public class ArrayTemplateBuilder implements 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTemplate(Type targetType, String directoryName) {
|
||||||
|
throw new UnsupportedOperationException(targetType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Template loadTemplate(Type targetType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.GenericArrayType;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
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){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Class<?> targetClass = (Class<?>)targetType;
|
||||||
|
return targetClass.isArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateBuilder getTemplateBuilder(Type target) {
|
||||||
|
return templateBuilder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.msgpack.*;
|
||||||
|
import org.msgpack.template.*;
|
||||||
|
|
||||||
|
import javassist.CannotCompileException;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtConstructor;
|
||||||
|
import javassist.CtNewConstructor;
|
||||||
|
import javassist.NotFoundException;
|
||||||
|
|
||||||
|
public class BeansBuildContext extends BuildContextBase<BeansFieldEntry> {
|
||||||
|
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(JavassistTemplateBuilder.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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,328 @@
|
|||||||
|
//
|
||||||
|
// 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 java.io.IOException;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
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.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 BeansTemplateBuilder extends CustomTemplateBuilder{
|
||||||
|
|
||||||
|
IFieldEntryReader reader = new BeansFieldEntryReader();
|
||||||
|
|
||||||
|
public BeansTemplateBuilder(){}
|
||||||
|
|
||||||
|
@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<Object> type = (Class<Object>)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<Object> type = (Class<Object>)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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import org.msgpack.annotation.MessagePackBeans;
|
||||||
|
|
||||||
|
public class BeansTemplateBuilderSelector implements BuilderSelector{
|
||||||
|
|
||||||
|
public static final String NAME = "BeansTemplateBuilder";
|
||||||
|
|
||||||
|
TemplateBuilder builder;
|
||||||
|
|
||||||
|
public BeansTemplateBuilderSelector(TemplateBuilder builder){
|
||||||
|
this.builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName(){
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matchType(Type targetType) {
|
||||||
|
Class<?> targetClass = (Class<?>)targetType;
|
||||||
|
return AnnotationTemplateBuilderSelector.isAnnotated(targetClass, MessagePackBeans.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,293 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.msgpack.*;
|
||||||
|
import org.msgpack.template.*;
|
||||||
|
|
||||||
|
import javassist.CannotCompileException;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtConstructor;
|
||||||
|
import javassist.CtNewConstructor;
|
||||||
|
import javassist.NotFoundException;
|
||||||
|
|
||||||
|
public class BuildContext extends BuildContextBase<FieldEntry> {
|
||||||
|
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(JavassistTemplateBuilder.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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,285 @@
|
|||||||
|
//
|
||||||
|
// 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 java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
|
||||||
|
import org.msgpack.*;
|
||||||
|
import org.msgpack.template.*;
|
||||||
|
|
||||||
|
import javassist.CannotCompileException;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtMethod;
|
||||||
|
import javassist.CtNewMethod;
|
||||||
|
import javassist.NotFoundException;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
public abstract class BuildContextBase<T extends IFieldEntry> {
|
||||||
|
|
||||||
|
private static Logger LOG = LoggerFactory.getLogger(JavassistTemplateBuilder.class);
|
||||||
|
|
||||||
|
protected JavassistTemplateBuilder director;
|
||||||
|
|
||||||
|
protected String tmplName;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Template build(final String className) {
|
||||||
|
try {
|
||||||
|
reset(className, false);
|
||||||
|
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, boolean isWritten) {
|
||||||
|
String tmplName = null;
|
||||||
|
if (!isWritten) {
|
||||||
|
tmplName = className + "_$$_Template" + director.nextSeqId();
|
||||||
|
} else {
|
||||||
|
tmplName = className + "_$$_Template";
|
||||||
|
}
|
||||||
|
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 void saveClass(final String directoryName) throws CannotCompileException, IOException {
|
||||||
|
tmplCtClass.writeFile(directoryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
//
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
|
||||||
|
public interface BuildContextFactory {
|
||||||
|
|
||||||
|
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder);
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Match condition for TemplateBuilder.
|
||||||
|
* @author takeshita
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public interface BuilderSelector {
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
boolean matchType(Type targetType);
|
||||||
|
|
||||||
|
TemplateBuilder getTemplateBuilder(Type targetType);
|
||||||
|
}
|
||||||
@@ -0,0 +1,212 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Type;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.msgpack.template.BeansFieldEntryReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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<BuilderSelector> builderSelectors = new LinkedList<BuilderSelector>();
|
||||||
|
|
||||||
|
private BuilderSelectorRegistry(){
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize BuilderSelectors for basic java enviroment.
|
||||||
|
*/
|
||||||
|
private static void initForJava(){
|
||||||
|
instance.append(new ArrayTemplateBuilderSelector());
|
||||||
|
if(isSupportJavassist()){
|
||||||
|
instance.append(new AnnotationTemplateBuilderSelector(new JavassistTemplateBuilder()));
|
||||||
|
instance.forceBuilder = new JavassistTemplateBuilder();
|
||||||
|
instance.append(new BeansTemplateBuilderSelector(
|
||||||
|
new JavassistTemplateBuilder(
|
||||||
|
new BeansFieldEntryReader(),
|
||||||
|
new BuildContextFactory() {
|
||||||
|
@Override
|
||||||
|
public BuildContextBase createBuildContext(JavassistTemplateBuilder builder) {
|
||||||
|
return new BeansBuildContext(builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)));
|
||||||
|
}else{
|
||||||
|
instance.append(new AnnotationTemplateBuilderSelector(new ReflectionTemplateBuilder()));
|
||||||
|
instance.forceBuilder = new ReflectionTemplateBuilder();
|
||||||
|
instance.append(new BeansTemplateBuilderSelector(new BeansTemplateBuilder()));
|
||||||
|
}
|
||||||
|
instance.append(new OrdinalEnumTemplateBuilderSelector());
|
||||||
|
instance.append(new EnumTemplateBuilderSelector());
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
//
|
||||||
|
// 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 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;
|
||||||
|
|
||||||
|
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 ){
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTemplate(Type targetType, String directoryName) {
|
||||||
|
throw new UnsupportedOperationException(targetType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Template loadTemplate(Type targetType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Type;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,207 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.Thread;
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import org.msgpack.*;
|
||||||
|
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.LoaderClassPath;
|
||||||
|
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;
|
||||||
|
|
||||||
|
public synchronized static JavassistTemplateBuilder getInstance() {
|
||||||
|
if(instance == null) {
|
||||||
|
instance = new JavassistTemplateBuilder();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addClassLoader(ClassLoader cl) {
|
||||||
|
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;
|
||||||
|
ClassLoader cl = null;
|
||||||
|
try {
|
||||||
|
cl = 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
|
||||||
|
public CtClass makeCtClass(String className) {
|
||||||
|
return pool.makeClass(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CtClass getCtClass(String className) throws NotFoundException {
|
||||||
|
return pool.get(className);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int nextSeqId() {
|
||||||
|
return seqId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||||
|
// FIXME private / packagefields
|
||||||
|
//for(FieldEntry e : entries) {
|
||||||
|
// Field f = e.getField();
|
||||||
|
// int mod = f.getModifiers();
|
||||||
|
// if(!Modifier.isPublic(mod)) {
|
||||||
|
// f.setAccessible(true);
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
Template[] tmpls = toTemplate(entries);
|
||||||
|
BuildContextBase bc = getBuildContextFacotry().createBuildContext(this);
|
||||||
|
return bc.buildTemplate(targetClass, entries, tmpls);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 {
|
||||||
|
Template tmpl = TemplateRegistry.lookup(e.getGenericType(), true);
|
||||||
|
tmpls[i] = tmpl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tmpls;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IFieldEntryReader getFieldEntryReader() {
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BuildContextFactory getBuildContextFacotry() {
|
||||||
|
return buildContextFactory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Template loadTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||||
|
Template[] tmpls = toTemplate(entries);
|
||||||
|
BuildContextBase bc = getBuildContextFacotry().createBuildContext(this);
|
||||||
|
return bc.loadTemplate(targetClass, entries, tmpls);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
//
|
||||||
|
// 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 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 implements TemplateBuilder{
|
||||||
|
|
||||||
|
static class ReflectionOrdinalEnumTemplate extends AbstractTemplate {
|
||||||
|
protected Enum<?>[] entries;
|
||||||
|
protected Map<Enum<?>, Integer> reverse;
|
||||||
|
|
||||||
|
ReflectionOrdinalEnumTemplate(Enum<?>[] entries) {
|
||||||
|
this.entries = entries;
|
||||||
|
this.reverse = new HashMap<Enum<?>, 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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void writeTemplate(Type targetType, String directoryName) {
|
||||||
|
throw new UnsupportedOperationException(targetType.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Template loadTemplate(Type targetType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||||
|
|
||||||
|
public class OrdinalEnumTemplateBuilderSelector implements BuilderSelector {
|
||||||
|
|
||||||
|
public static final String NAME = "OrdinalEnumTemplateBuilder";
|
||||||
|
|
||||||
|
OrdinalEnumTemplateBuilder builder = new OrdinalEnumTemplateBuilder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName(){
|
||||||
|
return NAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean matchType(Type targetType) {
|
||||||
|
Class<?> targetClass = (Class<?>)targetType;
|
||||||
|
return AnnotationTemplateBuilderSelector.isAnnotated(targetClass, MessagePackOrdinalEnum.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public TemplateBuilder getTemplateBuilder(Type targetType) {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
}
|
||||||
+28
-174
@@ -1,7 +1,7 @@
|
|||||||
//
|
//
|
||||||
// MessagePack for Java
|
// 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");
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
// you may not use this file except in compliance with the License.
|
// you may not use this file except in compliance with the License.
|
||||||
@@ -15,24 +15,33 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
package org.msgpack.template;
|
package org.msgpack.template.builder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Map;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.HashMap;
|
|
||||||
import org.msgpack.*;
|
|
||||||
|
|
||||||
public class ReflectionTemplateBuilder extends TemplateBuilder {
|
import org.msgpack.AbstractTemplate;
|
||||||
private static ReflectionTemplateBuilder instance;
|
import org.msgpack.MessagePackObject;
|
||||||
public synchronized static ReflectionTemplateBuilder getInstance() {
|
import org.msgpack.MessageTypeException;
|
||||||
if(instance == null) {
|
import org.msgpack.Packer;
|
||||||
instance = new ReflectionTemplateBuilder();
|
import org.msgpack.Template;
|
||||||
}
|
import org.msgpack.Unpacker;
|
||||||
return instance;
|
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();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IFieldEntryReader getFieldEntryReader(){
|
||||||
|
return reader;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ReflectionTemplateBuilder() {
|
public ReflectionTemplateBuilder() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static abstract class ReflectionFieldEntry extends FieldEntry {
|
static abstract class ReflectionFieldEntry extends FieldEntry {
|
||||||
@@ -373,9 +382,10 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) {
|
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||||
for(FieldEntry e : entries) {
|
// TODO Now it is simply cast.
|
||||||
Field f = e.getField();
|
for(IFieldEntry e : entries) {
|
||||||
|
Field f = ((FieldEntry)e).getField();
|
||||||
int mod = f.getModifiers();
|
int mod = f.getModifiers();
|
||||||
if(!Modifier.isPublic(mod)) {
|
if(!Modifier.isPublic(mod)) {
|
||||||
f.setAccessible(true);
|
f.setAccessible(true);
|
||||||
@@ -384,7 +394,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
|||||||
|
|
||||||
ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length];
|
ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length];
|
||||||
for(int i=0; i < entries.length; i++) {
|
for(int i=0; i < entries.length; i++) {
|
||||||
FieldEntry e = entries[i];
|
FieldEntry e = (FieldEntry)entries[i];
|
||||||
Class<?> type = e.getType();
|
Class<?> type = e.getType();
|
||||||
if(!e.isAvailable()) {
|
if(!e.isAvailable()) {
|
||||||
res[i] = new NullFieldEntry(e);
|
res[i] = new NullFieldEntry(e);
|
||||||
@@ -407,163 +417,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
|||||||
res[i] = new ObjectFieldEntry(e, tmpl);
|
res[i] = new ObjectFieldEntry(e, tmpl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ReflectionTemplate(targetClass, res);
|
return new ReflectionTemplate(targetClass, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ReflectionOrdinalEnumTemplate extends AbstractTemplate {
|
|
||||||
protected Enum<?>[] entries;
|
|
||||||
protected Map<Enum<?>, Integer> reverse;
|
|
||||||
|
|
||||||
ReflectionOrdinalEnumTemplate(Enum<?>[] entries) {
|
|
||||||
this.entries = entries;
|
|
||||||
this.reverse = new HashMap<Enum<?>, 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// 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 java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import org.msgpack.Template;
|
||||||
|
|
||||||
|
public interface TemplateBuilder {
|
||||||
|
Template buildTemplate(Type targetType);
|
||||||
|
|
||||||
|
void writeTemplate(Type targetType, String directoryName);
|
||||||
|
|
||||||
|
Template loadTemplate(Type targetType);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
//
|
||||||
|
// 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.util;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import javax.tools.DiagnosticCollector;
|
||||||
|
import javax.tools.JavaCompiler;
|
||||||
|
import javax.tools.JavaFileManager;
|
||||||
|
import javax.tools.JavaFileObject;
|
||||||
|
import javax.tools.StandardLocation;
|
||||||
|
import javax.tools.ToolProvider;
|
||||||
|
|
||||||
|
import org.msgpack.template.builder.JavassistTemplateBuilder;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a template precompiler, which is used for saving templates
|
||||||
|
* that <code>TemplateBuilder</code> generated. It saves templates as .class files.
|
||||||
|
* Application enables to load the .class files and use templates.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class TemplatePrecompiler {
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(TemplatePrecompiler.class);
|
||||||
|
|
||||||
|
public static final String DEST = "msgpack.template.destdir";
|
||||||
|
|
||||||
|
public static final String DEFAULT_DEST = ".";
|
||||||
|
|
||||||
|
public static void saveTemplates(final String[] classNames) throws IOException, ClassNotFoundException {
|
||||||
|
List<String> ret = new ArrayList<String>();
|
||||||
|
for (String className : classNames) {
|
||||||
|
matchClassNames(ret, className);
|
||||||
|
}
|
||||||
|
List<Class<?>> ret0 = toClass(ret);
|
||||||
|
for (Class<?> c : ret0) {
|
||||||
|
saveTemplateClass(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
private static void matchClassNames(List<String> ret, final String className) throws IOException {
|
||||||
|
String packageName = className.substring(0, className.lastIndexOf('.'));
|
||||||
|
String relativedName = className.substring(className.lastIndexOf('.') + 1, className.length());
|
||||||
|
String patName = relativedName.replace("*", "(\\w+)");
|
||||||
|
Pattern pat = Pattern.compile(patName);
|
||||||
|
|
||||||
|
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||||
|
JavaFileManager fm = compiler.getStandardFileManager(
|
||||||
|
new DiagnosticCollector<JavaFileObject>(), null, null);
|
||||||
|
HashSet<JavaFileObject.Kind> kind = new HashSet<JavaFileObject.Kind>(){{
|
||||||
|
add(JavaFileObject.Kind.CLASS);
|
||||||
|
}};
|
||||||
|
|
||||||
|
for (JavaFileObject f : fm.list(StandardLocation.PLATFORM_CLASS_PATH, packageName, kind, false)) {
|
||||||
|
String relatived0 = f.getName();
|
||||||
|
String name0 = relatived0.substring(0, relatived0.length() - ".class".length());
|
||||||
|
Matcher m = pat.matcher(name0);
|
||||||
|
if (m.matches()) {
|
||||||
|
String name = packageName + '.' + name0;
|
||||||
|
if (!ret.contains(name)) {
|
||||||
|
ret.add(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<Class<?>> toClass(List<String> classNames) throws ClassNotFoundException {
|
||||||
|
List<Class<?>> ret = new ArrayList<Class<?>>(classNames.size());
|
||||||
|
ClassLoader cl = TemplatePrecompiler.class.getClassLoader();
|
||||||
|
for (String className : classNames) {
|
||||||
|
Class<?> c = cl.loadClass(className);
|
||||||
|
ret.add(c);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveTemplateClasses(Class<?>[] targetClasses) throws IOException {
|
||||||
|
for (Class<?> c : targetClasses) {
|
||||||
|
saveTemplateClass(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void saveTemplateClass(Class<?> targetClass) throws IOException {
|
||||||
|
LOG.info("Saving template of " + targetClass.getName() + "...");
|
||||||
|
Properties props = System.getProperties();
|
||||||
|
String distDirName = getDirName(props, DEST, DEFAULT_DEST);
|
||||||
|
if (targetClass.isEnum()) {
|
||||||
|
throw new UnsupportedOperationException("Not supported enum type yet: " + targetClass.getName());
|
||||||
|
} else {
|
||||||
|
new JavassistTemplateBuilder().writeTemplate(targetClass, distDirName);
|
||||||
|
}
|
||||||
|
LOG.info("Saved .class file of template class of " + targetClass.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static 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.saveTemplates(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,10 @@ import org.junit.Test;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
public class TestArrays extends TestCase {
|
public class TestArrays extends TestCase {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@MessagePackMessage
|
@MessagePackMessage
|
||||||
public static class PrimitiveTest {
|
public static class PrimitiveTest {
|
||||||
public PrimitiveTest() { }
|
public PrimitiveTest() { }
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.msgpack;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
@@ -20,7 +21,7 @@ public class TestCases {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCases() throws Exception {
|
public void testDynamicType() throws Exception {
|
||||||
Unpacker pac = new Unpacker();
|
Unpacker pac = new Unpacker();
|
||||||
Unpacker pac_compact = new Unpacker();
|
Unpacker pac_compact = new Unpacker();
|
||||||
|
|
||||||
@@ -28,13 +29,182 @@ public class TestCases {
|
|||||||
feedFile(pac_compact, "src/test/resources/cases_compact.mpac");
|
feedFile(pac_compact, "src/test/resources/cases_compact.mpac");
|
||||||
|
|
||||||
UnpackResult result = new UnpackResult();
|
UnpackResult result = new UnpackResult();
|
||||||
|
UnpackResult result_compact = new UnpackResult();
|
||||||
while(pac.next(result)) {
|
while(pac.next(result)) {
|
||||||
UnpackResult result_compact = new UnpackResult();
|
|
||||||
assertTrue( pac_compact.next(result_compact) );
|
assertTrue( pac_compact.next(result_compact) );
|
||||||
assertTrue( result.getData().equals(result_compact.getData()) );
|
assertTrue( result.getData().equals(result_compact.getData()) );
|
||||||
}
|
}
|
||||||
|
|
||||||
assertFalse( pac_compact.next(result) );
|
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<MessagePackObject, MessagePackObject> 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<MessagePackObject, MessagePackObject> expect = obj.asMap();
|
||||||
|
Map<MessagePackObject, MessagePackObject> actual = target.asMap();
|
||||||
|
assertEquals(expect.size(), actual.size());
|
||||||
|
for(Map.Entry<MessagePackObject,MessagePackObject> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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>{
|
||||||
|
|
||||||
|
Object expected;
|
||||||
|
|
||||||
|
HashSet<String> ignoreNames = new HashSet<String>();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.msgpack.template;
|
package org.msgpack.template;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -741,4 +742,88 @@ public class TestPackConvert extends TestCase {
|
|||||||
Collection<String> dst = (Collection<String>) tmpl.convert(obj, null);
|
Collection<String> dst = (Collection<String>) tmpl.convert(obj, null);
|
||||||
assertEquals(src, dst);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package org.msgpack.template;
|
|||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
@@ -768,4 +769,90 @@ public class TestPackUnpack extends TestCase {
|
|||||||
Collection<String> dst = (Collection<String>) tmpl.unpack(unpacker, null);
|
Collection<String> dst = (Collection<String>) tmpl.unpack(unpacker, null);
|
||||||
assertEquals(src, dst);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2200
File diff suppressed because it is too large
Load Diff
+1409
File diff suppressed because it is too large
Load Diff
+1414
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -24,7 +24,10 @@ import org.msgpack.Unpacker;
|
|||||||
import org.msgpack.annotation.MessagePackMessage;
|
import org.msgpack.annotation.MessagePackMessage;
|
||||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||||
import org.msgpack.annotation.Optional;
|
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;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
public class TestTemplateBuilderPackConvert extends TestCase {
|
public class TestTemplateBuilderPackConvert extends TestCase {
|
||||||
@@ -595,22 +598,18 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
|||||||
|
|
||||||
SampleMapTypes dst =
|
SampleMapTypes dst =
|
||||||
MessagePack.unpack(raw).convert(SampleMapTypes.class);
|
MessagePack.unpack(raw).convert(SampleMapTypes.class);
|
||||||
|
assertEquals(0, dst.f0.size());
|
||||||
|
assertEquals(src.f1.size(), dst.f1.size());
|
||||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
|
||||||
while (srcf1.hasNext()) {
|
while (srcf1.hasNext()) {
|
||||||
Integer s1 = srcf1.next();
|
Integer s1 = srcf1.next();
|
||||||
Integer d1 = dstf1.next();
|
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||||
assertEquals(s1, d1);
|
|
||||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
|
||||||
}
|
}
|
||||||
assertEquals(src.f2.size(), dst.f2.size());
|
assertEquals(src.f2.size(), dst.f2.size());
|
||||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
|
||||||
while (srcf2.hasNext()) {
|
while (srcf2.hasNext()) {
|
||||||
String s2 = srcf2.next();
|
String s2 = srcf2.next();
|
||||||
String d2 = dstf2.next();
|
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||||
assertEquals(s2, d2);
|
|
||||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,24 +650,18 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
|||||||
|
|
||||||
SampleOptionalMapTypes dst =
|
SampleOptionalMapTypes dst =
|
||||||
MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class);
|
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());
|
assertEquals(src.f1.size(), dst.f1.size());
|
||||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
|
||||||
while (srcf1.hasNext()) {
|
while (srcf1.hasNext()) {
|
||||||
Integer s1 = srcf1.next();
|
Integer s1 = srcf1.next();
|
||||||
Integer d1 = dstf1.next();
|
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||||
assertEquals(s1, d1);
|
|
||||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
|
||||||
}
|
}
|
||||||
assertEquals(src.f2.size(), dst.f2.size());
|
assertEquals(src.f2.size(), dst.f2.size());
|
||||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
|
||||||
while (srcf2.hasNext()) {
|
while (srcf2.hasNext()) {
|
||||||
String s2 = srcf2.next();
|
String s2 = srcf2.next();
|
||||||
String d2 = dstf2.next();
|
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||||
assertEquals(s2, d2);
|
|
||||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,7 +707,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testFinalClass() throws Exception {
|
public void testFinalClass() throws Exception {
|
||||||
try {
|
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);
|
assertTrue(true);
|
||||||
} catch (TemplateBuildException e) {
|
} catch (TemplateBuildException e) {
|
||||||
fail();
|
fail();
|
||||||
@@ -731,7 +726,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testInterfaceType00() throws Exception {
|
public void testInterfaceType00() throws Exception {
|
||||||
try {
|
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();
|
fail();
|
||||||
} catch (TemplateBuildException e) {
|
} catch (TemplateBuildException e) {
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
@@ -742,7 +739,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testInterfaceType01() throws Exception {
|
public void testInterfaceType01() throws Exception {
|
||||||
try {
|
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();
|
fail();
|
||||||
} catch (TemplateBuildException e) {
|
} catch (TemplateBuildException e) {
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.msgpack.template;
|
package org.msgpack.template;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@@ -15,16 +13,17 @@ import org.junit.Test;
|
|||||||
|
|
||||||
import org.msgpack.MessagePack;
|
import org.msgpack.MessagePack;
|
||||||
import org.msgpack.MessagePackable;
|
import org.msgpack.MessagePackable;
|
||||||
import org.msgpack.MessagePacker;
|
|
||||||
import org.msgpack.MessageTypeException;
|
import org.msgpack.MessageTypeException;
|
||||||
import org.msgpack.MessageUnpackable;
|
import org.msgpack.MessageUnpackable;
|
||||||
import org.msgpack.Packer;
|
import org.msgpack.Packer;
|
||||||
import org.msgpack.Template;
|
|
||||||
import org.msgpack.Unpacker;
|
import org.msgpack.Unpacker;
|
||||||
import org.msgpack.annotation.MessagePackMessage;
|
import org.msgpack.annotation.MessagePackMessage;
|
||||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||||
import org.msgpack.annotation.Optional;
|
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;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
public class TestTemplateBuilderPackUnpack extends TestCase {
|
public class TestTemplateBuilderPackUnpack extends TestCase {
|
||||||
@@ -595,22 +594,18 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
|||||||
|
|
||||||
SampleMapTypes dst =
|
SampleMapTypes dst =
|
||||||
MessagePack.unpack(raw, SampleMapTypes.class);
|
MessagePack.unpack(raw, SampleMapTypes.class);
|
||||||
|
assertEquals(0, dst.f0.size());
|
||||||
|
assertEquals(src.f1.size(), dst.f1.size());
|
||||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
|
||||||
while (srcf1.hasNext()) {
|
while (srcf1.hasNext()) {
|
||||||
Integer s1 = srcf1.next();
|
Integer s1 = srcf1.next();
|
||||||
Integer d1 = dstf1.next();
|
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||||
assertEquals(s1, d1);
|
|
||||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
|
||||||
}
|
}
|
||||||
assertEquals(src.f2.size(), dst.f2.size());
|
assertEquals(src.f2.size(), dst.f2.size());
|
||||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
|
||||||
while (srcf2.hasNext()) {
|
while (srcf2.hasNext()) {
|
||||||
String s2 = srcf2.next();
|
String s2 = srcf2.next();
|
||||||
String d2 = dstf2.next();
|
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||||
assertEquals(s2, d2);
|
|
||||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -651,24 +646,18 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
|||||||
|
|
||||||
SampleOptionalMapTypes dst =
|
SampleOptionalMapTypes dst =
|
||||||
MessagePack.unpack(raw, SampleOptionalMapTypes.class);
|
MessagePack.unpack(raw, SampleOptionalMapTypes.class);
|
||||||
assertEquals(src.f0.size(), dst.f0.size());
|
assertEquals(0, dst.f0.size());
|
||||||
assertEquals(src.f1.size(), dst.f1.size());
|
assertEquals(src.f1.size(), dst.f1.size());
|
||||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
|
||||||
while (srcf1.hasNext()) {
|
while (srcf1.hasNext()) {
|
||||||
Integer s1 = srcf1.next();
|
Integer s1 = srcf1.next();
|
||||||
Integer d1 = dstf1.next();
|
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||||
assertEquals(s1, d1);
|
|
||||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
|
||||||
}
|
}
|
||||||
assertEquals(src.f2.size(), dst.f2.size());
|
assertEquals(src.f2.size(), dst.f2.size());
|
||||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
|
||||||
while (srcf2.hasNext()) {
|
while (srcf2.hasNext()) {
|
||||||
String s2 = srcf2.next();
|
String s2 = srcf2.next();
|
||||||
String d2 = dstf2.next();
|
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||||
assertEquals(s2, d2);
|
|
||||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,7 +703,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testFinalClass() throws Exception {
|
public void testFinalClass() throws Exception {
|
||||||
try {
|
try {
|
||||||
TemplateBuilder.build(FinalModifierClass.class);
|
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class);
|
||||||
|
Assert.assertNull(builder);
|
||||||
|
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class);
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
} catch (TemplateBuildException e) {
|
} catch (TemplateBuildException e) {
|
||||||
fail();
|
fail();
|
||||||
@@ -731,7 +722,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testInterfaceType00() throws Exception {
|
public void testInterfaceType00() throws Exception {
|
||||||
try {
|
try {
|
||||||
TemplateBuilder.build(SampleInterface.class);
|
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
|
||||||
|
Assert.assertNull(builder);
|
||||||
|
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
|
||||||
fail();
|
fail();
|
||||||
} catch (TemplateBuildException e) {
|
} catch (TemplateBuildException e) {
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
@@ -742,7 +735,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
|||||||
@Test
|
@Test
|
||||||
public void testInterfaceType01() throws Exception {
|
public void testInterfaceType01() throws Exception {
|
||||||
try {
|
try {
|
||||||
TemplateBuilder.build(SampleInterface.class);
|
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
|
||||||
|
Assert.assertNull(builder);
|
||||||
|
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
|
||||||
fail();
|
fail();
|
||||||
} catch (TemplateBuildException e) {
|
} catch (TemplateBuildException e) {
|
||||||
assertTrue(true);
|
assertTrue(true);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,11 @@
|
|||||||
|
*~
|
||||||
|
*.omc
|
||||||
|
.omakedb
|
||||||
|
.omakedb.lock
|
||||||
|
*.vo
|
||||||
|
*.glob
|
||||||
|
*.cm[iox]
|
||||||
|
*.o
|
||||||
|
*.annot
|
||||||
|
*.opt
|
||||||
|
*.run
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
NATIVE_ENABLED = true
|
||||||
|
BYTE_ENABLED = true
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
.SUBDIRS: ocaml proof
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf *.vo *.glob *~ *.omc .omakedb .omakedb.lock
|
||||||
@@ -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: .
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
MsgPack for OCaml
|
||||||
|
==============================
|
||||||
|
|
||||||
|
See http://wiki.msgpack.org/display/MSGPACK/QuickStart+for+OCaml
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Executable
+14
@@ -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
|
||||||
Executable
+60
@@ -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 }"
|
||||||
|
}
|
||||||
|
|
||||||
Executable
+22
@@ -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
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
runner
|
||||||
|
doc
|
||||||
@@ -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"
|
||||||
@@ -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: 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.*
|
||||||
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
let version = (1,0,0)
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user