mirror of
https://github.com/msgpack/msgpack-c.git
synced 2025-03-22 08:26:35 +01:00
Merge branch 'master' of github.com:msgpack/msgpack
This commit is contained in:
commit
8446549ed8
5
.gitignore
vendored
5
.gitignore
vendored
@ -1,3 +1,8 @@
|
||||
*.o
|
||||
*.so
|
||||
ruby/Makefile
|
||||
*.5
|
||||
*.8
|
||||
*.6
|
||||
_obj
|
||||
_test
|
||||
|
@ -1,4 +1,10 @@
|
||||
|
||||
2011-02-24 version 0.5.5:
|
||||
|
||||
* eliminates dependency of winsock2.h header
|
||||
* fixes msgpack_vc.postbuild.bat file
|
||||
* fixes some implicit cast warnings
|
||||
|
||||
2010-08-29 version 0.5.4:
|
||||
|
||||
* includes msgpack_vc2008.vcproj file in source package
|
||||
|
@ -1,6 +1,6 @@
|
||||
AC_INIT(src/object.cpp)
|
||||
AC_CONFIG_AUX_DIR(ac)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.5.4)
|
||||
AM_INIT_AUTOMAKE(msgpack, 0.5.5)
|
||||
AC_CONFIG_HEADER(config.h)
|
||||
|
||||
AC_SUBST(CFLAGS)
|
||||
|
@ -12,7 +12,7 @@ preprocess() {
|
||||
fi
|
||||
}
|
||||
|
||||
if [ "$1" == "clean" ];then
|
||||
if [ "$1" = "clean" ];then
|
||||
rm -f src/msgpack/type/tuple.hpp
|
||||
rm -f src/msgpack/type/define.hpp
|
||||
rm -f src/msgpack/zone.hpp
|
||||
|
@ -105,9 +105,6 @@ int msgpack_pack_object(msgpack_packer* pk, msgpack_object d);
|
||||
#define msgpack_pack_inline_func_cint(name) \
|
||||
inline int msgpack_pack ## name
|
||||
|
||||
#define msgpack_pack_inline_func_cint(name) \
|
||||
inline int msgpack_pack ## name
|
||||
|
||||
#define msgpack_pack_inline_func_fixint(name) \
|
||||
inline int msgpack_pack_fix ## name
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
|
||||
AM_CPPFLAGS = -I../src
|
||||
AM_C_CPPFLAGS = -I../src
|
||||
AM_LDFLAGS = ../src/libmsgpack.la -lgtest_main
|
||||
AM_LDFLAGS = ../src/libmsgpack.la -lgtest_main -pthread
|
||||
|
||||
check_PROGRAMS = \
|
||||
zone \
|
||||
|
11
go/Makefile
Normal file
11
go/Makefile
Normal file
@ -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
|
218
go/msgpack_test.go
Normal file
218
go/msgpack_test.go
Normal file
@ -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
go/pack.go
Normal file
591
go/pack.go
Normal file
@ -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
go/unpack.go
Normal file
288
go/unpack.go
Normal file
@ -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)
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,12 +1,12 @@
|
||||
Name: msgpack
|
||||
Version: 0.4.0.1
|
||||
Synopsis: A Haskell binding to MessagePack
|
||||
Version: 0.6.1.1
|
||||
Synopsis: A Haskell implementation of MessagePack
|
||||
Description:
|
||||
A Haskell binding to MessagePack <http://msgpack.org/>
|
||||
A Haskell implementation of MessagePack <http://msgpack.org/>
|
||||
|
||||
License: BSD3
|
||||
License-File: LICENSE
|
||||
Copyright: Copyright (c) 2009-2010, Hideyuki Tanaka
|
||||
Copyright: Copyright (c) 2009-2011, Hideyuki Tanaka
|
||||
Category: Data
|
||||
Author: Hideyuki Tanaka
|
||||
Maintainer: Hideyuki Tanaka <tanaka.hideyuki@gmail.com>
|
||||
@ -21,28 +21,30 @@ Extra-source-files:
|
||||
|
||||
Library
|
||||
Build-depends: base >=4 && <5,
|
||||
transformers >= 0.2.1 && < 0.2.2,
|
||||
MonadCatchIO-transformers >= 0.2.2 && < 0.2.3,
|
||||
transformers >= 0.2 && < 0.3,
|
||||
bytestring >= 0.9 && < 0.10,
|
||||
vector >= 0.6.0 && < 0.6.1,
|
||||
iteratee >= 0.4 && < 0.5,
|
||||
attoparsec >= 0.8.1 && < 0.8.2,
|
||||
text >= 0.11 && < 0.12,
|
||||
vector >= 0.7 && < 0.8,
|
||||
attoparsec >= 0.8 && < 0.9,
|
||||
binary >= 0.5.0 && < 0.5.1,
|
||||
data-binary-ieee754 >= 0.4 && < 0.5,
|
||||
deepseq >= 1.1 && <1.2,
|
||||
template-haskell >= 2.4 && < 2.5
|
||||
template-haskell >= 2.4 && < 2.6
|
||||
|
||||
Ghc-options: -Wall
|
||||
Hs-source-dirs: src
|
||||
|
||||
Exposed-modules:
|
||||
Data.MessagePack
|
||||
Data.MessagePack.Assoc
|
||||
Data.MessagePack.Pack
|
||||
Data.MessagePack.Unpack
|
||||
Data.MessagePack.Object
|
||||
Data.MessagePack.Iteratee
|
||||
Data.MessagePack.Derive
|
||||
|
||||
Other-modules:
|
||||
Data.MessagePack.Internal.Utf8
|
||||
|
||||
Source-repository head
|
||||
Type: git
|
||||
Location: git://github.com/msgpack/msgpack.git
|
||||
|
@ -13,91 +13,15 @@
|
||||
--------------------------------------------------------------------
|
||||
|
||||
module Data.MessagePack(
|
||||
module Data.MessagePack.Assoc,
|
||||
module Data.MessagePack.Pack,
|
||||
module Data.MessagePack.Unpack,
|
||||
module Data.MessagePack.Object,
|
||||
module Data.MessagePack.Iteratee,
|
||||
module Data.MessagePack.Derive,
|
||||
|
||||
-- * Pack functions
|
||||
packToString,
|
||||
packToHandle,
|
||||
packToHandle',
|
||||
packToFile,
|
||||
|
||||
-- * Unpack functions
|
||||
unpackFromString,
|
||||
unpackFromHandle,
|
||||
unpackFromFile,
|
||||
unpackFromStringI,
|
||||
unpackFromHandleI,
|
||||
unpackFromFileI,
|
||||
|
||||
) where
|
||||
|
||||
import qualified Control.Monad.CatchIO as CIO
|
||||
import Control.Monad.IO.Class
|
||||
import qualified Data.Attoparsec as A
|
||||
import Data.Binary.Put
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import qualified Data.Iteratee as I
|
||||
import System.IO
|
||||
|
||||
import Data.MessagePack.Assoc
|
||||
import Data.MessagePack.Pack
|
||||
import Data.MessagePack.Unpack
|
||||
import Data.MessagePack.Object
|
||||
import Data.MessagePack.Iteratee
|
||||
import Data.MessagePack.Derive
|
||||
|
||||
bufferSize :: Int
|
||||
bufferSize = 4 * 1024
|
||||
|
||||
-- | Pack to ByteString.
|
||||
packToString :: Put -> L.ByteString
|
||||
packToString = runPut
|
||||
|
||||
-- | Pack to Handle
|
||||
packToHandle :: Handle -> Put -> IO ()
|
||||
packToHandle h = L.hPutStr h . packToString
|
||||
|
||||
-- | Pack to Handle and Flush Handle
|
||||
packToHandle' :: Handle -> Put -> IO ()
|
||||
packToHandle' h p = packToHandle h p >> hFlush h
|
||||
|
||||
-- | Pack to File
|
||||
packToFile :: FilePath -> Put -> IO ()
|
||||
packToFile path = L.writeFile path . packToString
|
||||
|
||||
-- | Unpack from ByteString
|
||||
unpackFromString :: (Monad m, IsByteString s) => s -> A.Parser a -> m a
|
||||
unpackFromString bs =
|
||||
unpackFromStringI bs . parserToIteratee
|
||||
|
||||
-- | Unpack from Handle
|
||||
unpackFromHandle :: CIO.MonadCatchIO m => Handle -> A.Parser a -> m a
|
||||
unpackFromHandle h =
|
||||
unpackFromHandleI h .parserToIteratee
|
||||
|
||||
-- | Unpack from File
|
||||
unpackFromFile :: CIO.MonadCatchIO m => FilePath -> A.Parser a -> m a
|
||||
unpackFromFile path =
|
||||
unpackFromFileI path . parserToIteratee
|
||||
|
||||
-- | Iteratee interface to unpack from ByteString
|
||||
unpackFromStringI :: (Monad m, IsByteString s) => s -> I.Iteratee B.ByteString m a -> m a
|
||||
unpackFromStringI bs =
|
||||
I.run . I.joinIM . I.enumPure1Chunk (toBS bs)
|
||||
|
||||
-- | Iteratee interface to unpack from Handle
|
||||
unpackFromHandleI :: CIO.MonadCatchIO m => Handle -> I.Iteratee B.ByteString m a -> m a
|
||||
unpackFromHandleI h =
|
||||
I.run . I.joinIM . enumHandleNonBlocking bufferSize h
|
||||
|
||||
-- | Iteratee interface to unpack from File
|
||||
unpackFromFileI :: CIO.MonadCatchIO m => FilePath -> I.Iteratee B.ByteString m a -> m a
|
||||
unpackFromFileI path p =
|
||||
CIO.bracket
|
||||
(liftIO $ openBinaryFile path ReadMode)
|
||||
(liftIO . hClose)
|
||||
(flip unpackFromHandleI p)
|
||||
|
28
haskell/src/Data/MessagePack/Assoc.hs
Normal file
28
haskell/src/Data/MessagePack/Assoc.hs
Normal file
@ -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)
|
||||
|
28
haskell/src/Data/MessagePack/Internal/Utf8.hs
Normal file
28
haskell/src/Data/MessagePack/Internal/Utf8.hs
Normal file
@ -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 FlexibleInstances #-}
|
||||
{-# Language OverlappingInstances #-}
|
||||
{-# Language IncoherentInstances #-}
|
||||
{-# Language DeriveDataTypeable #-}
|
||||
|
||||
@ -33,22 +32,30 @@ import Control.Monad
|
||||
import Control.Monad.Trans.Error ()
|
||||
import qualified Data.Attoparsec as A
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Char8 as C8
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as T
|
||||
import qualified Data.Text.Lazy as TL
|
||||
import qualified Data.Text.Lazy.Encoding as TL
|
||||
import Data.Typeable
|
||||
|
||||
import Data.MessagePack.Assoc
|
||||
import Data.MessagePack.Pack
|
||||
import Data.MessagePack.Unpack
|
||||
import Data.MessagePack.Internal.Utf8
|
||||
|
||||
-- | Object Representation of MessagePack data.
|
||||
data Object =
|
||||
ObjectNil
|
||||
data Object
|
||||
= ObjectNil
|
||||
| ObjectBool Bool
|
||||
| ObjectInteger Int
|
||||
| ObjectFloat Float
|
||||
| ObjectDouble Double
|
||||
| ObjectRAW B.ByteString
|
||||
| ObjectArray [Object]
|
||||
| ObjectMap [(Object, Object)]
|
||||
deriving (Show, Eq, Ord, Typeable)
|
||||
|
||||
|
||||
instance NFData Object where
|
||||
rnf obj =
|
||||
@ -56,21 +63,24 @@ instance NFData Object where
|
||||
ObjectNil -> ()
|
||||
ObjectBool b -> rnf b
|
||||
ObjectInteger n -> rnf n
|
||||
ObjectFloat f -> rnf f
|
||||
ObjectDouble d -> rnf d
|
||||
ObjectRAW bs -> bs `seq` ()
|
||||
ObjectArray a -> rnf a
|
||||
ObjectMap m -> rnf m
|
||||
|
||||
|
||||
instance Unpackable Object where
|
||||
get =
|
||||
A.choice
|
||||
[ liftM ObjectInteger get
|
||||
, liftM (\() -> ObjectNil) get
|
||||
, liftM ObjectBool get
|
||||
, liftM ObjectFloat get
|
||||
, liftM ObjectDouble get
|
||||
, liftM ObjectRAW get
|
||||
, liftM ObjectArray get
|
||||
, liftM ObjectMap get
|
||||
, liftM (ObjectMap . unAssoc) get
|
||||
]
|
||||
|
||||
instance Packable Object where
|
||||
@ -82,6 +92,8 @@ instance Packable Object where
|
||||
put ()
|
||||
ObjectBool b ->
|
||||
put b
|
||||
ObjectFloat f ->
|
||||
put f
|
||||
ObjectDouble d ->
|
||||
put d
|
||||
ObjectRAW raw ->
|
||||
@ -89,7 +101,7 @@ instance Packable Object where
|
||||
ObjectArray arr ->
|
||||
put arr
|
||||
ObjectMap m ->
|
||||
put m
|
||||
put $ Assoc m
|
||||
|
||||
-- | The class of types serializable to and from MessagePack object
|
||||
class (Unpackable a, Packable a) => OBJECT a where
|
||||
@ -137,14 +149,34 @@ instance OBJECT Double where
|
||||
tryFromObject (ObjectDouble d) = Right d
|
||||
tryFromObject _ = tryFromObjectError
|
||||
|
||||
instance OBJECT Float where
|
||||
toObject = ObjectFloat
|
||||
tryFromObject (ObjectFloat f) = Right f
|
||||
tryFromObject _ = tryFromObjectError
|
||||
|
||||
instance OBJECT String where
|
||||
toObject = toObject . encodeUtf8
|
||||
tryFromObject obj = liftM decodeUtf8 $ tryFromObject obj
|
||||
|
||||
instance OBJECT B.ByteString where
|
||||
toObject = ObjectRAW
|
||||
tryFromObject (ObjectRAW bs) = Right bs
|
||||
tryFromObject _ = tryFromObjectError
|
||||
|
||||
instance OBJECT String where
|
||||
toObject = toObject . C8.pack
|
||||
tryFromObject obj = liftM C8.unpack $ tryFromObject obj
|
||||
instance OBJECT BL.ByteString where
|
||||
toObject = ObjectRAW . fromLBS
|
||||
tryFromObject (ObjectRAW bs) = Right $ toLBS bs
|
||||
tryFromObject _ = tryFromObjectError
|
||||
|
||||
instance OBJECT T.Text where
|
||||
toObject = ObjectRAW . T.encodeUtf8
|
||||
tryFromObject (ObjectRAW bs) = Right $ T.decodeUtf8With skipChar bs
|
||||
tryFromObject _ = tryFromObjectError
|
||||
|
||||
instance OBJECT TL.Text where
|
||||
toObject = ObjectRAW . fromLBS . TL.encodeUtf8
|
||||
tryFromObject (ObjectRAW bs) = Right $ TL.decodeUtf8With skipChar $ toLBS bs
|
||||
tryFromObject _ = tryFromObjectError
|
||||
|
||||
instance OBJECT a => OBJECT [a] where
|
||||
toObject = ObjectArray . map toObject
|
||||
@ -285,11 +317,11 @@ instance (OBJECT a1, OBJECT a2, OBJECT a3, OBJECT a4, OBJECT a5, OBJECT a6, OBJE
|
||||
tryFromObject _ =
|
||||
tryFromObjectError
|
||||
|
||||
instance (OBJECT a, OBJECT b) => OBJECT [(a, b)] where
|
||||
instance (OBJECT a, OBJECT b) => OBJECT (Assoc [(a,b)]) where
|
||||
toObject =
|
||||
ObjectMap . map (\(a, b) -> (toObject a, toObject b))
|
||||
ObjectMap . map (\(a, b) -> (toObject a, toObject b)) . unAssoc
|
||||
tryFromObject (ObjectMap mem) = do
|
||||
mapM (\(a, b) -> liftM2 (,) (tryFromObject a) (tryFromObject b)) mem
|
||||
liftM Assoc $ mapM (\(a, b) -> liftM2 (,) (tryFromObject a) (tryFromObject b)) mem
|
||||
tryFromObject _ =
|
||||
tryFromObjectError
|
||||
|
||||
@ -299,3 +331,4 @@ instance OBJECT a => OBJECT (Maybe a) where
|
||||
|
||||
tryFromObject ObjectNil = return Nothing
|
||||
tryFromObject obj = liftM Just $ tryFromObject obj
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
{-# Language FlexibleInstances #-}
|
||||
{-# Language IncoherentInstances #-}
|
||||
{-# Language OverlappingInstances #-}
|
||||
{-# Language TypeSynonymInstances #-}
|
||||
|
||||
--------------------------------------------------------------------
|
||||
@ -28,17 +27,23 @@ import Data.Binary.Put
|
||||
import Data.Binary.IEEE754
|
||||
import Data.Bits
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Char8 as B8
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as T
|
||||
import qualified Data.Text.Lazy as TL
|
||||
import qualified Data.Text.Lazy.Encoding as TL
|
||||
import qualified Data.Vector as V
|
||||
|
||||
import Data.MessagePack.Assoc
|
||||
import Data.MessagePack.Internal.Utf8
|
||||
|
||||
-- | Serializable class
|
||||
class Packable a where
|
||||
-- | Serialize a value
|
||||
put :: a -> Put
|
||||
|
||||
-- | Pack Haskell data to MessagePack string.
|
||||
pack :: Packable a => a -> L.ByteString
|
||||
pack :: Packable a => a -> BL.ByteString
|
||||
pack = runPut . put
|
||||
|
||||
instance Packable Int where
|
||||
@ -81,23 +86,35 @@ instance Packable Bool where
|
||||
put True = putWord8 0xC3
|
||||
put False = putWord8 0xC2
|
||||
|
||||
instance Packable Float where
|
||||
put f = do
|
||||
putWord8 0xCA
|
||||
putFloat32be f
|
||||
|
||||
instance Packable Double where
|
||||
put d = do
|
||||
putWord8 0xCB
|
||||
putFloat64be d
|
||||
|
||||
instance Packable String where
|
||||
put = putString length (putByteString . B8.pack)
|
||||
put = putString encodeUtf8 B.length putByteString
|
||||
|
||||
instance Packable B.ByteString where
|
||||
put = putString B.length putByteString
|
||||
put = putString id B.length putByteString
|
||||
|
||||
instance Packable L.ByteString where
|
||||
put = putString (fromIntegral . L.length) putLazyByteString
|
||||
instance Packable BL.ByteString where
|
||||
put = putString id (fromIntegral . BL.length) putLazyByteString
|
||||
|
||||
putString :: (s -> Int) -> (s -> Put) -> s -> Put
|
||||
putString lf pf str = do
|
||||
case lf str of
|
||||
instance Packable T.Text where
|
||||
put = putString T.encodeUtf8 B.length putByteString
|
||||
|
||||
instance Packable TL.Text where
|
||||
put = putString TL.encodeUtf8 (fromIntegral . BL.length) putLazyByteString
|
||||
|
||||
putString :: (s -> t) -> (t -> Int) -> (t -> Put) -> s -> Put
|
||||
putString cnv lf pf str = do
|
||||
let bs = cnv str
|
||||
case lf bs of
|
||||
len | len <= 31 -> do
|
||||
putWord8 $ 0xA0 .|. fromIntegral len
|
||||
len | len < 0x10000 -> do
|
||||
@ -106,7 +123,7 @@ putString lf pf str = do
|
||||
len -> do
|
||||
putWord8 0xDB
|
||||
putWord32be $ fromIntegral len
|
||||
pf str
|
||||
pf bs
|
||||
|
||||
instance Packable a => Packable [a] where
|
||||
put = putArray length (mapM_ put)
|
||||
@ -159,11 +176,11 @@ putArray lf pf arr = do
|
||||
putWord32be $ fromIntegral len
|
||||
pf arr
|
||||
|
||||
instance (Packable k, Packable v) => Packable [(k, v)] where
|
||||
put = putMap length (mapM_ putPair)
|
||||
instance (Packable k, Packable v) => Packable (Assoc [(k,v)]) where
|
||||
put = putMap length (mapM_ putPair) . unAssoc
|
||||
|
||||
instance (Packable k, Packable v) => Packable (V.Vector (k, v)) where
|
||||
put = putMap V.length (V.mapM_ putPair)
|
||||
instance (Packable k, Packable v) => Packable (Assoc (V.Vector (k,v))) where
|
||||
put = putMap V.length (V.mapM_ putPair) . unAssoc
|
||||
|
||||
putPair :: (Packable a, Packable b) => (a, b) -> Put
|
||||
putPair (a, b) = put a >> put b
|
||||
@ -184,3 +201,4 @@ putMap lf pf m = do
|
||||
instance Packable a => Packable (Maybe a) where
|
||||
put Nothing = put ()
|
||||
put (Just a) = put a
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
{-# Language FlexibleInstances #-}
|
||||
{-# Language IncoherentInstances #-}
|
||||
{-# Language OverlappingInstances #-}
|
||||
{-# Language TypeSynonymInstances #-}
|
||||
{-# Language DeriveDataTypeable #-}
|
||||
|
||||
@ -37,14 +36,20 @@ import Data.Binary.Get
|
||||
import Data.Binary.IEEE754
|
||||
import Data.Bits
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Char8 as B8
|
||||
import qualified Data.ByteString.Lazy as L
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.Text as T
|
||||
import qualified Data.Text.Encoding as T
|
||||
import qualified Data.Text.Lazy as TL
|
||||
import qualified Data.Text.Lazy.Encoding as TL
|
||||
import Data.Int
|
||||
import Data.Typeable
|
||||
import qualified Data.Vector as V
|
||||
import Data.Word
|
||||
import Text.Printf
|
||||
|
||||
import Data.MessagePack.Assoc
|
||||
import Data.MessagePack.Internal.Utf8
|
||||
|
||||
-- | Deserializable class
|
||||
class Unpackable a where
|
||||
-- | Deserialize a value
|
||||
@ -56,8 +61,8 @@ class IsByteString s where
|
||||
instance IsByteString B.ByteString where
|
||||
toBS = id
|
||||
|
||||
instance IsByteString L.ByteString where
|
||||
toBS = B.concat . L.toChunks
|
||||
instance IsByteString BL.ByteString where
|
||||
toBS = B.concat . BL.toChunks
|
||||
|
||||
-- | The exception of unpack
|
||||
data UnpackError =
|
||||
@ -133,25 +138,38 @@ instance Unpackable Bool where
|
||||
_ ->
|
||||
fail $ printf "invlid bool tag: 0x%02X" c
|
||||
|
||||
instance Unpackable Double where
|
||||
instance Unpackable Float where
|
||||
get = do
|
||||
c <- A.anyWord8
|
||||
case c of
|
||||
0xCA ->
|
||||
return . realToFrac . runGet getFloat32be . toLBS =<< A.take 4
|
||||
return . runGet getFloat32be . toLBS =<< A.take 4
|
||||
_ ->
|
||||
fail $ printf "invlid float tag: 0x%02X" c
|
||||
|
||||
instance Unpackable Double where
|
||||
get = do
|
||||
c <- A.anyWord8
|
||||
case c of
|
||||
0xCB ->
|
||||
return . runGet getFloat64be . toLBS =<< A.take 8
|
||||
_ ->
|
||||
fail $ printf "invlid double tag: 0x%02X" c
|
||||
|
||||
instance Unpackable String where
|
||||
get = parseString (\n -> return . B8.unpack =<< A.take n)
|
||||
get = parseString (\n -> return . decodeUtf8 =<< A.take n)
|
||||
|
||||
instance Unpackable B.ByteString where
|
||||
get = parseString A.take
|
||||
|
||||
instance Unpackable L.ByteString where
|
||||
get = parseString (\n -> do bs <- A.take n; return $ L.fromChunks [bs])
|
||||
instance Unpackable BL.ByteString where
|
||||
get = parseString (\n -> return . toLBS =<< A.take n)
|
||||
|
||||
instance Unpackable T.Text where
|
||||
get = parseString (\n -> return . T.decodeUtf8With skipChar =<< A.take n)
|
||||
|
||||
instance Unpackable TL.Text where
|
||||
get = parseString (\n -> return . TL.decodeUtf8With skipChar . toLBS =<< A.take n)
|
||||
|
||||
parseString :: (Int -> A.Parser a) -> A.Parser a
|
||||
parseString aget = do
|
||||
@ -225,11 +243,11 @@ parseArray aget = do
|
||||
_ ->
|
||||
fail $ printf "invlid array tag: 0x%02X" c
|
||||
|
||||
instance (Unpackable k, Unpackable v) => Unpackable [(k, v)] where
|
||||
get = parseMap (flip replicateM parsePair)
|
||||
instance (Unpackable k, Unpackable v) => Unpackable (Assoc [(k,v)]) where
|
||||
get = liftM Assoc $ parseMap (flip replicateM parsePair)
|
||||
|
||||
instance (Unpackable k, Unpackable v) => Unpackable (V.Vector (k, v)) where
|
||||
get = parseMap (flip V.replicateM parsePair)
|
||||
instance (Unpackable k, Unpackable v) => Unpackable (Assoc (V.Vector (k, v))) where
|
||||
get = liftM Assoc $ parseMap (flip V.replicateM parsePair)
|
||||
|
||||
parsePair :: (Unpackable k, Unpackable v) => A.Parser (k, v)
|
||||
parsePair = do
|
||||
@ -303,6 +321,3 @@ parseInt32 = return . fromIntegral =<< parseUint32
|
||||
|
||||
parseInt64 :: A.Parser Int64
|
||||
parseInt64 = return . fromIntegral =<< parseUint64
|
||||
|
||||
toLBS :: B.ByteString -> L.ByteString
|
||||
toLBS bs = L.fromChunks [bs]
|
||||
|
@ -7,6 +7,9 @@ import qualified Data.ByteString.Char8 as B
|
||||
import qualified Data.ByteString.Lazy.Char8 as L
|
||||
import Data.MessagePack
|
||||
|
||||
instance Arbitrary a => Arbitrary (Assoc a) where
|
||||
arbitrary = liftM Assoc arbitrary
|
||||
|
||||
mid :: (Packable a, Unpackable a) => a -> a
|
||||
mid = unpack . pack
|
||||
|
||||
@ -36,10 +39,12 @@ prop_mid_pair4 a = a == mid a
|
||||
where types = a :: (Int, Int, Int, Int)
|
||||
prop_mid_pair5 a = a == mid a
|
||||
where types = a :: (Int, Int, Int, Int, Int)
|
||||
prop_mid_map_int_double a = a == mid a
|
||||
prop_mid_list_int_double a = a == mid a
|
||||
where types = a :: [(Int, Double)]
|
||||
prop_mid_map_string_string a = a == mid a
|
||||
prop_mid_list_string_string a = a == mid a
|
||||
where types = a :: [(String, String)]
|
||||
prop_mid_map_string_int a = a == mid a
|
||||
where types = a :: Assoc [(String,Int)]
|
||||
|
||||
tests =
|
||||
[ testGroup "simple"
|
||||
@ -56,8 +61,9 @@ tests =
|
||||
, testProperty "(int, int, int)" prop_mid_pair3
|
||||
, testProperty "(int, int, int, int)" prop_mid_pair4
|
||||
, testProperty "(int, int, int, int, int)" prop_mid_pair5
|
||||
, testProperty "[(int, double)]" prop_mid_map_int_double
|
||||
, testProperty "[(string, string)]" prop_mid_map_string_string
|
||||
, testProperty "[(int, double)]" prop_mid_list_int_double
|
||||
, testProperty "[(string, string)]" prop_mid_list_string_string
|
||||
, testProperty "Assoc [(string, int)]" prop_mid_map_string_int
|
||||
]
|
||||
]
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
#Mon Apr 19 22:18:48 JST 2010
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
#Mon Sep 27 07:43:48 JST 2010
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
|
||||
org.eclipse.jdt.core.compiler.compliance=1.6
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.6
|
||||
|
9
java/.settings/org.maven.ide.eclipse.prefs
Normal file
9
java/.settings/org.maven.ide.eclipse.prefs
Normal file
@ -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
|
17
java/msgpack.iml
Normal file
17
java/msgpack.iml
Normal file
@ -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>
|
||||
|
20
java/pom.xml
20
java/pom.xml
@ -63,8 +63,8 @@
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
@ -81,6 +81,20 @@
|
||||
<connectionUrl>scm:git://github.com/msgpack/msgpack.git</connectionUrl>
|
||||
</configuration>
|
||||
</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>
|
||||
</build>
|
||||
|
||||
@ -132,12 +146,14 @@
|
||||
<id>msgpack.org</id>
|
||||
<name>Repository at msgpack.org</name>
|
||||
<url>file://${project.build.directory}/website/maven2/</url>
|
||||
<!--<url>${deploy-release-url}</url>-->
|
||||
</repository>
|
||||
<snapshotRepository>
|
||||
<uniqueVersion>true</uniqueVersion>
|
||||
<id>msgpack.org</id>
|
||||
<name>Repository at msgpack.org</name>
|
||||
<url>file://${project.build.directory}/website/maven2/</url>
|
||||
<!--<url>${deploy-snapshot-url}</url>-->
|
||||
</snapshotRepository>
|
||||
</distributionManagement>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -23,5 +23,4 @@ public abstract class AbstractTemplate implements Template {
|
||||
public Object unpack(Unpacker pac, Object to) throws IOException, MessageTypeException {
|
||||
return convert(pac.unpackObject(), to);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -146,10 +146,10 @@ abstract class BufferedUnpackerImpl extends UnpackerImpl {
|
||||
advance(3);
|
||||
return (int)castBuffer.getShort(0);
|
||||
case 0xd2: // signed int 32
|
||||
more(4);
|
||||
more(5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
advance(4);
|
||||
advance(5);
|
||||
return (int)castBuffer.getInt(0);
|
||||
case 0xd3: // signed int 64
|
||||
more(9);
|
||||
@ -215,10 +215,10 @@ abstract class BufferedUnpackerImpl extends UnpackerImpl {
|
||||
advance(3);
|
||||
return (long)castBuffer.getShort(0);
|
||||
case 0xd2: // signed int 32
|
||||
more(4);
|
||||
more(5);
|
||||
castBuffer.rewind();
|
||||
castBuffer.put(buffer, offset+1, 4);
|
||||
advance(4);
|
||||
advance(5);
|
||||
return (long)castBuffer.getInt(0);
|
||||
case 0xd3: // signed int 64
|
||||
more(9);
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -22,7 +22,6 @@ import java.io.InputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
import org.msgpack.template.TemplateBuilder;
|
||||
import org.msgpack.template.FieldList;
|
||||
|
||||
public class MessagePack {
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -18,6 +18,5 @@
|
||||
package org.msgpack;
|
||||
|
||||
public interface MessagePackTemplateProvider {
|
||||
|
||||
Template getTemplate();
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -18,5 +18,4 @@
|
||||
package org.msgpack;
|
||||
|
||||
public interface Template extends MessagePacker, MessageUnpacker, MessageConverter {
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -76,6 +76,11 @@ public class Templates {
|
||||
return TBigInteger;
|
||||
}
|
||||
|
||||
public static final Template TBigDecimal = BigDecimalTemplate.getInstance();
|
||||
public static Template tBigDecimal() {
|
||||
return TBigDecimal;
|
||||
}
|
||||
|
||||
public static final Template TFloat = FloatTemplate.getInstance();
|
||||
public static Template tFloat() {
|
||||
return TFloat;
|
||||
@ -105,5 +110,10 @@ public class Templates {
|
||||
public static Template tByteBuffer() {
|
||||
return TByteBuffer;
|
||||
}
|
||||
|
||||
public static final Template TDate = DateTemplate.getInstance();
|
||||
public static Template tDate() {
|
||||
return TDate;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Ignore {
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Index {
|
||||
int value();
|
||||
|
@ -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.Target;
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Nullable {
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Optional {
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER})
|
||||
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Required {
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -79,7 +79,7 @@ public class RawType extends MessagePackObject {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return bytes.hashCode();
|
||||
return Arrays.hashCode(bytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
143
java/src/main/java/org/msgpack/template/BeansFieldEntry.java
Normal file
143
java/src/main/java/org/msgpack/template/BeansFieldEntry.java
Normal file
@ -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
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -21,6 +21,7 @@ public class BuiltInTemplateLoader {
|
||||
public static void load() {
|
||||
AnyTemplate.getInstance();
|
||||
BigIntegerTemplate.getInstance();
|
||||
BigDecimalTemplate.getInstance();
|
||||
BooleanArrayTemplate.getInstance();
|
||||
BooleanTemplate.getInstance();
|
||||
ByteArrayTemplate.getInstance();
|
||||
@ -28,6 +29,7 @@ public class BuiltInTemplateLoader {
|
||||
ByteTemplate.getInstance();
|
||||
DoubleArrayTemplate.getInstance();
|
||||
DoubleTemplate.getInstance();
|
||||
DateTemplate.getInstance();
|
||||
FloatArrayTemplate.getInstance();
|
||||
FloatTemplate.getInstance();
|
||||
IntArrayTemplate.getInstance();
|
||||
|
57
java/src/main/java/org/msgpack/template/DateTemplate.java
Normal file
57
java/src/main/java/org/msgpack/template/DateTemplate.java
Normal file
@ -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
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -50,7 +50,7 @@ public class DefaultTemplate implements Template {
|
||||
}
|
||||
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||
if(tmpl == this || tmpl == null) {
|
||||
throw new MessageTypeException();
|
||||
throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName());
|
||||
}
|
||||
tmpl.pack(pk, target);
|
||||
}
|
||||
@ -69,7 +69,7 @@ public class DefaultTemplate implements Template {
|
||||
}
|
||||
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||
if(tmpl == this || tmpl == null) {
|
||||
throw new MessageTypeException();
|
||||
throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName());
|
||||
}
|
||||
return tmpl.unpack(pac, to);
|
||||
}
|
||||
@ -88,7 +88,7 @@ public class DefaultTemplate implements Template {
|
||||
}
|
||||
Template tmpl = TemplateRegistry.tryLookup(lookupType);
|
||||
if(tmpl == this || tmpl == null) {
|
||||
throw new MessageTypeException();
|
||||
throw new MessageTypeException("Template lookup fail: " + lookupType.getClass().getName());
|
||||
}
|
||||
return tmpl.convert(from, to);
|
||||
}
|
||||
|
143
java/src/main/java/org/msgpack/template/FieldEntry.java
Normal file
143
java/src/main/java/org/msgpack/template/FieldEntry.java
Normal file
@ -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();
|
||||
}
|
||||
}
|
182
java/src/main/java/org/msgpack/template/FieldEntryReader.java
Normal file
182
java/src/main/java/org/msgpack/template/FieldEntryReader.java
Normal file
@ -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;
|
||||
}
|
||||
|
||||
boolean isAvailable() {
|
||||
public boolean isAvailable() {
|
||||
return this.option != FieldOption.IGNORE;
|
||||
}
|
||||
|
||||
boolean isRequired() {
|
||||
public boolean isRequired() {
|
||||
return this.option == FieldOption.REQUIRED;
|
||||
}
|
||||
|
||||
boolean isOptional() {
|
||||
public boolean isOptional() {
|
||||
return this.option == FieldOption.OPTIONAL;
|
||||
}
|
||||
|
||||
boolean isNullable() {
|
||||
public boolean isNullable() {
|
||||
return this.option == FieldOption.NULLABLE;
|
||||
}
|
||||
}
|
||||
@ -89,7 +89,7 @@ public class FieldList {
|
||||
}
|
||||
}
|
||||
|
||||
List<Entry> getList() {
|
||||
public List<Entry> getList() {
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
42
java/src/main/java/org/msgpack/template/IFieldEntry.java
Normal file
42
java/src/main/java/org/msgpack/template/IFieldEntry.java
Normal file
@ -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
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
|
@ -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
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -20,48 +20,63 @@ package org.msgpack.template;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.lang.reflect.Type;
|
||||
import java.lang.reflect.GenericArrayType;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.annotation.Annotation;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
import org.msgpack.annotation.MessagePackDelegate;
|
||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||
import org.msgpack.template.builder.BuilderSelectorRegistry;
|
||||
import org.msgpack.template.builder.CustomTemplateBuilder;
|
||||
import org.msgpack.template.builder.TemplateBuilder;
|
||||
import org.msgpack.Template;
|
||||
import org.msgpack.Templates;
|
||||
|
||||
public class TemplateRegistry {
|
||||
private static Map<Type, Template> map;
|
||||
private static Map<Type, GenericTemplate> genericMap;
|
||||
private static BuilderSelectorRegistry builderSelectorRegistry;
|
||||
|
||||
static {
|
||||
map = new HashMap<Type, Template>();
|
||||
genericMap = new HashMap<Type, GenericTemplate>();
|
||||
BuiltInTemplateLoader.load();
|
||||
builderSelectorRegistry = BuilderSelectorRegistry.getInstance();
|
||||
}
|
||||
|
||||
public static void register(Class<?> target) { // auto-detect
|
||||
if(target.isEnum()) {
|
||||
register(target, TemplateBuilder.buildOrdinalEnum(target));
|
||||
public static void register(Class<?> target) {
|
||||
TemplateBuilder builder = builderSelectorRegistry.select(target);
|
||||
if (builder != null) {
|
||||
register(target,builder.buildTemplate(target));
|
||||
} else {
|
||||
register(target, TemplateBuilder.build(target));
|
||||
register(target,builderSelectorRegistry.getForceBuilder().buildTemplate(target));
|
||||
}
|
||||
}
|
||||
|
||||
public static void register(Class<?> target, FieldOption implicitOption) {
|
||||
register(target, TemplateBuilder.build(target, implicitOption));
|
||||
TemplateBuilder builder = builderSelectorRegistry.select(target);
|
||||
if (builder != null && builder instanceof CustomTemplateBuilder) {
|
||||
register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, implicitOption));
|
||||
} else {
|
||||
throw new TemplateBuildException("Cannot build template with filed option");
|
||||
}
|
||||
}
|
||||
|
||||
public static void register(Class<?> target, FieldList flist) throws NoSuchFieldException {
|
||||
register(target, TemplateBuilder.build(target, flist));
|
||||
TemplateBuilder builder = builderSelectorRegistry.select(target);
|
||||
if (builder != null && builder instanceof CustomTemplateBuilder) {
|
||||
register(target, ((CustomTemplateBuilder)builder).buildTemplate(target, flist));
|
||||
} else {
|
||||
throw new TemplateBuildException("Cannot build template with filed list");
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void register(Type rawType, Template tmpl) {
|
||||
if(rawType instanceof ParameterizedType) {
|
||||
if (rawType instanceof ParameterizedType) {
|
||||
rawType = ((ParameterizedType)rawType).getRawType();
|
||||
}
|
||||
map.put(rawType, tmpl);
|
||||
}
|
||||
|
||||
public static boolean unregister(Class<?> target) {
|
||||
Template tmpl = map.remove(target);
|
||||
return tmpl != null;
|
||||
}
|
||||
|
||||
public static synchronized void registerGeneric(Type rawType, GenericTemplate gtmpl) {
|
||||
if(rawType instanceof ParameterizedType) {
|
||||
rawType = ((ParameterizedType)rawType).getRawType();
|
||||
@ -70,22 +85,27 @@ public class TemplateRegistry {
|
||||
}
|
||||
|
||||
public static synchronized Template lookup(Type targetType) {
|
||||
return lookupImpl(targetType, false, true);
|
||||
return lookupImpl(targetType, true, false, true);
|
||||
}
|
||||
|
||||
public static synchronized Template lookup(Type targetType, boolean forceBuild) {
|
||||
return lookupImpl(targetType, forceBuild, true);
|
||||
return lookupImpl(targetType, true, forceBuild, true);
|
||||
}
|
||||
|
||||
public static synchronized Template lookup(Type targetType, boolean forceLoad, boolean forceBuild) {
|
||||
return lookupImpl(targetType, forceLoad, forceBuild, true);
|
||||
}
|
||||
|
||||
public static synchronized Template tryLookup(Type targetType) {
|
||||
return lookupImpl(targetType, false, false);
|
||||
return lookupImpl(targetType, true, false, false);
|
||||
}
|
||||
|
||||
public static synchronized Template tryLookup(Type targetType, boolean forceBuild) {
|
||||
return lookupImpl(targetType, forceBuild, false);
|
||||
return lookupImpl(targetType, true, forceBuild, false);
|
||||
}
|
||||
|
||||
private static synchronized Template lookupImpl(Type targetType, boolean forceBuild, boolean fallbackDefault) {
|
||||
private static synchronized Template lookupImpl(Type targetType,
|
||||
boolean forceLoad, boolean forceBuild, boolean fallbackDefault) {
|
||||
Template tmpl;
|
||||
|
||||
if(targetType instanceof ParameterizedType) {
|
||||
@ -102,35 +122,26 @@ public class TemplateRegistry {
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
if(targetType instanceof GenericArrayType) {
|
||||
// GenericArrayType is not a Class<?>
|
||||
tmpl = TemplateBuilder.buildArray(targetType);
|
||||
register(targetType, tmpl);
|
||||
return tmpl;
|
||||
// find match TemplateBuilder
|
||||
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(targetType);
|
||||
if (builder != null) {
|
||||
if (forceLoad) {
|
||||
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;
|
||||
|
||||
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()) {
|
||||
tmpl = map.get(i);
|
||||
if(tmpl != null) {
|
||||
@ -150,7 +161,7 @@ public class TemplateRegistry {
|
||||
}
|
||||
|
||||
if(forceBuild) {
|
||||
tmpl = TemplateBuilder.build(target);
|
||||
tmpl = builderSelectorRegistry.getForceBuilder().buildTemplate(target);
|
||||
register(target, tmpl);
|
||||
return tmpl;
|
||||
}
|
||||
@ -174,7 +185,7 @@ public class TemplateRegistry {
|
||||
}
|
||||
return new DefaultTemplate((Class<?>)parameterizedType.getRawType(), parameterizedType);
|
||||
} else {
|
||||
throw new IllegalArgumentException("actual types of the generic type are erased: "+targetType);
|
||||
throw new IllegalArgumentException("Actual types of the generic type are erased: "+targetType);
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,13 +204,5 @@ public class TemplateRegistry {
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
throw new UnsupportedOperationException(targetClass.getName());
|
||||
}
|
||||
}
|
@ -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,223 @@
|
||||
//
|
||||
// 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();
|
||||
|
||||
//Java beans
|
||||
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();
|
||||
|
||||
//Java beans
|
||||
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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
//
|
||||
// MessagePack for Java
|
||||
//
|
||||
// Copyright (C) 2009-2010 FURUHASHI Sadayuki
|
||||
// Copyright (C) 2009-2011 FURUHASHI Sadayuki
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -15,24 +15,33 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
//
|
||||
package org.msgpack.template;
|
||||
package org.msgpack.template.builder;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import org.msgpack.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
private static ReflectionTemplateBuilder instance;
|
||||
public synchronized static ReflectionTemplateBuilder getInstance() {
|
||||
if(instance == null) {
|
||||
instance = new ReflectionTemplateBuilder();
|
||||
}
|
||||
return instance;
|
||||
import org.msgpack.AbstractTemplate;
|
||||
import org.msgpack.MessagePackObject;
|
||||
import org.msgpack.MessageTypeException;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.Template;
|
||||
import org.msgpack.Unpacker;
|
||||
import org.msgpack.template.FieldEntry;
|
||||
import org.msgpack.template.FieldEntryReader;
|
||||
import org.msgpack.template.IFieldEntry;
|
||||
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 {
|
||||
@ -373,9 +382,10 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
public Template buildTemplate(Class<?> targetClass, FieldEntry[] entries) {
|
||||
for(FieldEntry e : entries) {
|
||||
Field f = e.getField();
|
||||
public Template buildTemplate(Class<?> targetClass, IFieldEntry[] entries) {
|
||||
// TODO Now it is simply cast.
|
||||
for(IFieldEntry e : entries) {
|
||||
Field f = ((FieldEntry)e).getField();
|
||||
int mod = f.getModifiers();
|
||||
if(!Modifier.isPublic(mod)) {
|
||||
f.setAccessible(true);
|
||||
@ -384,7 +394,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
|
||||
ReflectionFieldEntry[] res = new ReflectionFieldEntry[entries.length];
|
||||
for(int i=0; i < entries.length; i++) {
|
||||
FieldEntry e = entries[i];
|
||||
FieldEntry e = (FieldEntry)entries[i];
|
||||
Class<?> type = e.getType();
|
||||
if(!e.isAvailable()) {
|
||||
res[i] = new NullFieldEntry(e);
|
||||
@ -407,163 +417,7 @@ public class ReflectionTemplateBuilder extends TemplateBuilder {
|
||||
res[i] = new ObjectFieldEntry(e, tmpl);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
78
java/src/main/java/org/msgpack/util/TemplatePrecompiler.java
Normal file
78
java/src/main/java/org/msgpack/util/TemplatePrecompiler.java
Normal file
@ -0,0 +1,78 @@
|
||||
//
|
||||
// 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.Properties;
|
||||
|
||||
import org.msgpack.template.builder.BuilderSelectorRegistry;
|
||||
import org.msgpack.template.builder.JavassistTemplateBuilder;
|
||||
import org.msgpack.template.builder.TemplateBuilder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class TemplatePrecompiler {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(TemplatePrecompiler.class);
|
||||
|
||||
//public static final String SRC = "msgpack.template.srcdir";
|
||||
|
||||
public static final String DIST = "msgpack.template.distdir";
|
||||
|
||||
//public static final String DEFAULT_SRC = ".";
|
||||
|
||||
public static final String DEFAULT_DIST = ".";
|
||||
|
||||
private static TemplatePrecompiler INSTANCE = null;
|
||||
|
||||
private TemplatePrecompiler() {
|
||||
}
|
||||
|
||||
public static void saveTemplates(final String[] classFileNames) throws IOException {
|
||||
throw new UnsupportedOperationException("Not supported yet.");// TODO
|
||||
}
|
||||
|
||||
public static void saveTemplateClass(Class<?> targetClass) throws IOException {
|
||||
if (INSTANCE != null) {
|
||||
INSTANCE = new TemplatePrecompiler();
|
||||
}
|
||||
LOG.info("Saving template of " + targetClass.getName() + "...");
|
||||
Properties props = System.getProperties();
|
||||
String distDirName = getDirName(props, DIST, DEFAULT_DIST);
|
||||
if (targetClass.isEnum()) {
|
||||
throw new UnsupportedOperationException("Enum not supported yet: " + targetClass.getName());
|
||||
} else {
|
||||
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;
|
||||
|
||||
public class TestArrays extends TestCase {
|
||||
|
||||
|
||||
|
||||
|
||||
@MessagePackMessage
|
||||
public static class PrimitiveTest {
|
||||
public PrimitiveTest() { }
|
||||
|
@ -2,6 +2,7 @@ package org.msgpack;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.math.BigInteger;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
@ -20,7 +21,7 @@ public class TestCases {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCases() throws Exception {
|
||||
public void testDynamicType() throws Exception {
|
||||
Unpacker pac = new Unpacker();
|
||||
Unpacker pac_compact = new Unpacker();
|
||||
|
||||
@ -28,13 +29,182 @@ public class TestCases {
|
||||
feedFile(pac_compact, "src/test/resources/cases_compact.mpac");
|
||||
|
||||
UnpackResult result = new UnpackResult();
|
||||
UnpackResult result_compact = new UnpackResult();
|
||||
while(pac.next(result)) {
|
||||
UnpackResult result_compact = new UnpackResult();
|
||||
assertTrue( pac_compact.next(result_compact) );
|
||||
assertTrue( result.getData().equals(result_compact.getData()) );
|
||||
}
|
||||
|
||||
assertFalse( pac_compact.next(result) );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDirectConversion() throws Exception {
|
||||
Unpacker pac = new Unpacker();
|
||||
Unpacker pac_compact = new Unpacker();
|
||||
|
||||
feedFile(pac, "src/test/resources/cases.mpac");
|
||||
feedFile(pac_compact, "src/test/resources/cases_compact.mpac");
|
||||
|
||||
UnpackResult result_compact = new UnpackResult();
|
||||
while(pac_compact.next(result_compact)) {
|
||||
MessagePackObject obj = result_compact.getData();
|
||||
testDirectConversionRecursive(pac, obj);
|
||||
}
|
||||
|
||||
assertFalse( pac_compact.next(result_compact) );
|
||||
}
|
||||
|
||||
private void testDirectConversionRecursive(Unpacker pac, MessagePackObject obj) throws Exception {
|
||||
if(obj.isBooleanType()) {
|
||||
boolean expect = obj.asBoolean();
|
||||
boolean actual = pac.unpackBoolean();
|
||||
assertEquals(expect, actual);
|
||||
|
||||
} else if(obj.isIntegerType()) {
|
||||
BigInteger expect = obj.asBigInteger();
|
||||
if(BigInteger.valueOf((long)Byte.MIN_VALUE).compareTo(expect) <= 0 &&
|
||||
expect.compareTo(BigInteger.valueOf((long)Byte.MAX_VALUE)) <= 0) {
|
||||
byte actual = pac.unpackByte();
|
||||
assertEquals(expect.byteValue(), actual);
|
||||
} else if(BigInteger.valueOf((long)Short.MIN_VALUE).compareTo(expect) <= 0 &&
|
||||
expect.compareTo(BigInteger.valueOf((long)Short.MAX_VALUE)) <= 0) {
|
||||
short actual = pac.unpackShort();
|
||||
assertEquals(expect.shortValue(), actual);
|
||||
} else if(BigInteger.valueOf((long)Integer.MIN_VALUE).compareTo(expect) <= 0 &&
|
||||
expect.compareTo(BigInteger.valueOf((long)Integer.MAX_VALUE)) <= 0) {
|
||||
int actual = pac.unpackInt();
|
||||
assertEquals(expect.intValue(), actual);
|
||||
} else if(BigInteger.valueOf(Long.MIN_VALUE).compareTo(expect) <= 0 &&
|
||||
expect.compareTo(BigInteger.valueOf(Long.MAX_VALUE)) <= 0) {
|
||||
long actual = pac.unpackLong();
|
||||
assertEquals(expect.longValue(), actual);
|
||||
} else {
|
||||
BigInteger actual = pac.unpackBigInteger();
|
||||
assertEquals(expect, actual);
|
||||
}
|
||||
|
||||
} else if(obj.isFloatType()) {
|
||||
double expect = obj.asFloat();
|
||||
double actual = pac.unpackDouble();
|
||||
assertEquals(expect, actual, 0.01);
|
||||
|
||||
} else if(obj.isArrayType()) {
|
||||
MessagePackObject[] expect = obj.asArray();
|
||||
int length = pac.unpackArray();
|
||||
assertEquals(expect.length, length);
|
||||
for(int i=0; i < length; i++) {
|
||||
testDirectConversionRecursive(pac, expect[i]);
|
||||
}
|
||||
|
||||
} else if(obj.isMapType()) {
|
||||
Map<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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
83
java/src/test/java/org/msgpack/template/BeansEquals.java
Normal file
83
java/src/test/java/org/msgpack/template/BeansEquals.java
Normal file
@ -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;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
@ -741,4 +742,88 @@ public class TestPackConvert extends TestCase {
|
||||
Collection<String> dst = (Collection<String>) tmpl.convert(obj, null);
|
||||
assertEquals(src, dst);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigDecimal() throws Exception {
|
||||
// String
|
||||
_testBigDecimal(new BigDecimal("0"));
|
||||
_testBigDecimal(new BigDecimal("-0"));
|
||||
_testBigDecimal(new BigDecimal("1"));
|
||||
_testBigDecimal(new BigDecimal("-1"));
|
||||
_testBigDecimal(new BigDecimal("123.456"));
|
||||
_testBigDecimal(new BigDecimal("-123.456"));
|
||||
_testBigDecimal(new BigDecimal("0.123456789"));
|
||||
_testBigDecimal(new BigDecimal("-0.123456789"));
|
||||
|
||||
// char array
|
||||
char[] zero = {'0'};
|
||||
_testBigDecimal(new BigDecimal(zero));
|
||||
char[] one = {'1'};
|
||||
_testBigDecimal(new BigDecimal(one));
|
||||
char[] minusOne = {'-', '1'};
|
||||
_testBigDecimal(new BigDecimal(minusOne));
|
||||
char[] decimal = {'1', '2', '3', '.', '4', '5', '6'};
|
||||
_testBigDecimal(new BigDecimal(decimal));
|
||||
char[] minusDecimal = {'-', '1', '2', '3', '.', '4', '5', '6'};
|
||||
_testBigDecimal(new BigDecimal(minusDecimal));
|
||||
char[] oneOrLessDecimal = {'0', '.', '1', '2', '3'};
|
||||
_testBigDecimal(new BigDecimal(oneOrLessDecimal));
|
||||
char[] minusOneOrLessDecimal = {'-', '0', '.', '1', '2', '3'};
|
||||
_testBigDecimal(new BigDecimal(minusOneOrLessDecimal));
|
||||
|
||||
// int
|
||||
_testBigDecimal(new BigDecimal(0));
|
||||
_testBigDecimal(new BigDecimal(-0));
|
||||
_testBigDecimal(new BigDecimal(1));
|
||||
_testBigDecimal(new BigDecimal(-1));
|
||||
_testBigDecimal(new BigDecimal(Integer.MAX_VALUE));
|
||||
_testBigDecimal(new BigDecimal(Integer.MIN_VALUE));
|
||||
|
||||
// double
|
||||
_testBigDecimal(new BigDecimal((double) 0.0));
|
||||
_testBigDecimal(new BigDecimal((double) -0.0));
|
||||
_testBigDecimal(new BigDecimal((double) 1.0));
|
||||
_testBigDecimal(new BigDecimal((double) -1.0));
|
||||
_testBigDecimal(new BigDecimal((double) 123.456));
|
||||
_testBigDecimal(new BigDecimal((double) -123.456));
|
||||
_testBigDecimal(new BigDecimal((double) 0.123456789));
|
||||
_testBigDecimal(new BigDecimal((double) -0.123456789));
|
||||
_testBigDecimal(new BigDecimal(Double.MAX_VALUE));
|
||||
_testBigDecimal(new BigDecimal(Double.MIN_VALUE));
|
||||
}
|
||||
|
||||
static void _testBigDecimal(BigDecimal src) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Template tmpl = BigDecimalTemplate.getInstance();
|
||||
tmpl.pack(new Packer(out), src);
|
||||
MessagePackObject obj = Util.unpackOne(out.toByteArray());
|
||||
BigDecimal dst = (BigDecimal) tmpl.convert(obj, null);
|
||||
assertEquals(src, dst);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullBigDecimal() throws Exception {
|
||||
BigDecimal src = null;
|
||||
Template tmpl = BigDecimalTemplate.getInstance();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Packer packer = new Packer(out);
|
||||
try {
|
||||
tmpl.pack(packer, src);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof MessageTypeException);
|
||||
}
|
||||
packer.pack(src);
|
||||
MessagePackObject obj = Util.unpackOne(out.toByteArray());
|
||||
try {
|
||||
tmpl.convert(obj, null);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof MessageTypeException);
|
||||
}
|
||||
obj = Util.unpackOne(out.toByteArray());
|
||||
tmpl = new NullableTemplate(BigDecimalTemplate.getInstance());
|
||||
BigDecimal dst = (BigDecimal) tmpl.convert(obj, null);
|
||||
assertEquals(src, dst);
|
||||
}
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ package org.msgpack.template;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.ArrayList;
|
||||
@ -768,4 +769,90 @@ public class TestPackUnpack extends TestCase {
|
||||
Collection<String> dst = (Collection<String>) tmpl.unpack(unpacker, null);
|
||||
assertEquals(src, dst);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBigDecimal() throws Exception {
|
||||
// String
|
||||
_testBigDecimal(new BigDecimal("0"));
|
||||
_testBigDecimal(new BigDecimal("-0"));
|
||||
_testBigDecimal(new BigDecimal("1"));
|
||||
_testBigDecimal(new BigDecimal("-1"));
|
||||
_testBigDecimal(new BigDecimal("123.456"));
|
||||
_testBigDecimal(new BigDecimal("-123.456"));
|
||||
_testBigDecimal(new BigDecimal("0.123456789"));
|
||||
_testBigDecimal(new BigDecimal("-0.123456789"));
|
||||
|
||||
// char array
|
||||
char[] zero = {'0'};
|
||||
_testBigDecimal(new BigDecimal(zero));
|
||||
char[] one = {'1'};
|
||||
_testBigDecimal(new BigDecimal(one));
|
||||
char[] minusOne = {'-', '1'};
|
||||
_testBigDecimal(new BigDecimal(minusOne));
|
||||
char[] decimal = {'1', '2', '3', '.', '4', '5', '6'};
|
||||
_testBigDecimal(new BigDecimal(decimal));
|
||||
char[] minusDecimal = {'-', '1', '2', '3', '.', '4', '5', '6'};
|
||||
_testBigDecimal(new BigDecimal(minusDecimal));
|
||||
char[] oneOrLessDecimal = {'0', '.', '1', '2', '3'};
|
||||
_testBigDecimal(new BigDecimal(oneOrLessDecimal));
|
||||
char[] minusOneOrLessDecimal = {'-', '0', '.', '1', '2', '3'};
|
||||
_testBigDecimal(new BigDecimal(minusOneOrLessDecimal));
|
||||
|
||||
// int
|
||||
_testBigDecimal(new BigDecimal(0));
|
||||
_testBigDecimal(new BigDecimal(-0));
|
||||
_testBigDecimal(new BigDecimal(1));
|
||||
_testBigDecimal(new BigDecimal(-1));
|
||||
_testBigDecimal(new BigDecimal(Integer.MAX_VALUE));
|
||||
_testBigDecimal(new BigDecimal(Integer.MIN_VALUE));
|
||||
|
||||
// double
|
||||
_testBigDecimal(new BigDecimal((double) 0.0));
|
||||
_testBigDecimal(new BigDecimal((double) -0.0));
|
||||
_testBigDecimal(new BigDecimal((double) 1.0));
|
||||
_testBigDecimal(new BigDecimal((double) -1.0));
|
||||
_testBigDecimal(new BigDecimal((double) 123.456));
|
||||
_testBigDecimal(new BigDecimal((double) -123.456));
|
||||
_testBigDecimal(new BigDecimal((double) 0.123456789));
|
||||
_testBigDecimal(new BigDecimal((double) -0.123456789));
|
||||
_testBigDecimal(new BigDecimal(Double.MAX_VALUE));
|
||||
_testBigDecimal(new BigDecimal(Double.MIN_VALUE));
|
||||
}
|
||||
|
||||
static void _testBigDecimal(BigDecimal src) throws Exception {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Template tmpl = BigDecimalTemplate.getInstance();
|
||||
tmpl.pack(new Packer(out), src);
|
||||
ByteArrayInputStream in = new ByteArrayInputStream(out.toByteArray());
|
||||
BigDecimal dst = (BigDecimal) tmpl.unpack(new Unpacker(in), null);
|
||||
assertEquals(src, dst);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullBigDecimal() throws Exception {
|
||||
BigDecimal src = null;
|
||||
Template tmpl = BigDecimalTemplate.getInstance();
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||
Packer packer = new Packer(out);
|
||||
try {
|
||||
tmpl.pack(packer, src);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof MessageTypeException);
|
||||
}
|
||||
packer.pack(src);
|
||||
byte[] bytes = out.toByteArray();
|
||||
Unpacker unpacker = new Unpacker();
|
||||
try {
|
||||
unpacker.wrap(bytes);
|
||||
tmpl.unpack(unpacker, null);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof MessageTypeException);
|
||||
}
|
||||
unpacker.wrap(bytes);
|
||||
tmpl = new NullableTemplate(BigDecimalTemplate.getInstance());
|
||||
BigDecimal dst = (BigDecimal) tmpl.unpack(unpacker, null);
|
||||
assertEquals(src, dst);
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
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.MessagePackOrdinalEnum;
|
||||
import org.msgpack.annotation.Optional;
|
||||
import org.msgpack.template.builder.BuilderSelectorRegistry;
|
||||
import org.msgpack.template.builder.TemplateBuilder;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestTemplateBuilderPackConvert extends TestCase {
|
||||
@ -595,22 +598,18 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
||||
|
||||
SampleMapTypes dst =
|
||||
MessagePack.unpack(raw).convert(SampleMapTypes.class);
|
||||
assertEquals(0, dst.f0.size());
|
||||
assertEquals(src.f1.size(), dst.f1.size());
|
||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
||||
while (srcf1.hasNext()) {
|
||||
Integer s1 = srcf1.next();
|
||||
Integer d1 = dstf1.next();
|
||||
assertEquals(s1, d1);
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||
}
|
||||
assertEquals(src.f2.size(), dst.f2.size());
|
||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
||||
while (srcf2.hasNext()) {
|
||||
String s2 = srcf2.next();
|
||||
String d2 = dstf2.next();
|
||||
assertEquals(s2, d2);
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,24 +650,18 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
||||
|
||||
SampleOptionalMapTypes dst =
|
||||
MessagePack.unpack(raw).convert(SampleOptionalMapTypes.class);
|
||||
assertEquals(src.f0.size(), dst.f0.size());
|
||||
assertEquals(0, dst.f0.size());
|
||||
assertEquals(src.f1.size(), dst.f1.size());
|
||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
||||
while (srcf1.hasNext()) {
|
||||
Integer s1 = srcf1.next();
|
||||
Integer d1 = dstf1.next();
|
||||
assertEquals(s1, d1);
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||
}
|
||||
assertEquals(src.f2.size(), dst.f2.size());
|
||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
||||
while (srcf2.hasNext()) {
|
||||
String s2 = srcf2.next();
|
||||
String d2 = dstf2.next();
|
||||
assertEquals(s2, d2);
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,7 +707,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
||||
@Test
|
||||
public void testFinalClass() throws Exception {
|
||||
try {
|
||||
TemplateBuilder.build(FinalModifierClass.class);
|
||||
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class);
|
||||
Assert.assertNull(builder);// no available builder
|
||||
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class);
|
||||
assertTrue(true);
|
||||
} catch (TemplateBuildException e) {
|
||||
fail();
|
||||
@ -731,7 +726,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
||||
@Test
|
||||
public void testInterfaceType00() throws Exception {
|
||||
try {
|
||||
TemplateBuilder.build(SampleInterface.class);
|
||||
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
|
||||
Assert.assertNull(builder);// no available builder
|
||||
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
|
||||
fail();
|
||||
} catch (TemplateBuildException e) {
|
||||
assertTrue(true);
|
||||
@ -742,7 +739,9 @@ public class TestTemplateBuilderPackConvert extends TestCase {
|
||||
@Test
|
||||
public void testInterfaceType01() throws Exception {
|
||||
try {
|
||||
TemplateBuilder.build(SampleInterface.class);
|
||||
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
|
||||
Assert.assertNull(builder);// no available builder
|
||||
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
|
||||
fail();
|
||||
} catch (TemplateBuildException e) {
|
||||
assertTrue(true);
|
||||
|
@ -1,7 +1,5 @@
|
||||
package org.msgpack.template;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigInteger;
|
||||
import java.nio.ByteBuffer;
|
||||
@ -15,16 +13,17 @@ import org.junit.Test;
|
||||
|
||||
import org.msgpack.MessagePack;
|
||||
import org.msgpack.MessagePackable;
|
||||
import org.msgpack.MessagePacker;
|
||||
import org.msgpack.MessageTypeException;
|
||||
import org.msgpack.MessageUnpackable;
|
||||
import org.msgpack.Packer;
|
||||
import org.msgpack.Template;
|
||||
import org.msgpack.Unpacker;
|
||||
import org.msgpack.annotation.MessagePackMessage;
|
||||
import org.msgpack.annotation.MessagePackOrdinalEnum;
|
||||
import org.msgpack.annotation.Optional;
|
||||
import org.msgpack.template.builder.BuilderSelectorRegistry;
|
||||
import org.msgpack.template.builder.TemplateBuilder;
|
||||
|
||||
import junit.framework.Assert;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class TestTemplateBuilderPackUnpack extends TestCase {
|
||||
@ -595,22 +594,18 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
||||
|
||||
SampleMapTypes dst =
|
||||
MessagePack.unpack(raw, SampleMapTypes.class);
|
||||
assertEquals(0, dst.f0.size());
|
||||
assertEquals(src.f1.size(), dst.f1.size());
|
||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
||||
while (srcf1.hasNext()) {
|
||||
Integer s1 = srcf1.next();
|
||||
Integer d1 = dstf1.next();
|
||||
assertEquals(s1, d1);
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||
}
|
||||
assertEquals(src.f2.size(), dst.f2.size());
|
||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
||||
while (srcf2.hasNext()) {
|
||||
String s2 = srcf2.next();
|
||||
String d2 = dstf2.next();
|
||||
assertEquals(s2, d2);
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -651,24 +646,18 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
||||
|
||||
SampleOptionalMapTypes dst =
|
||||
MessagePack.unpack(raw, SampleOptionalMapTypes.class);
|
||||
assertEquals(src.f0.size(), dst.f0.size());
|
||||
assertEquals(0, dst.f0.size());
|
||||
assertEquals(src.f1.size(), dst.f1.size());
|
||||
Iterator<Integer> srcf1 = src.f1.keySet().iterator();
|
||||
Iterator<Integer> dstf1 = dst.f1.keySet().iterator();
|
||||
while (srcf1.hasNext()) {
|
||||
Integer s1 = srcf1.next();
|
||||
Integer d1 = dstf1.next();
|
||||
assertEquals(s1, d1);
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(d1));
|
||||
assertEquals(src.f1.get(s1), dst.f1.get(s1));
|
||||
}
|
||||
assertEquals(src.f2.size(), dst.f2.size());
|
||||
Iterator<String> srcf2 = src.f2.keySet().iterator();
|
||||
Iterator<String> dstf2 = dst.f2.keySet().iterator();
|
||||
while (srcf2.hasNext()) {
|
||||
String s2 = srcf2.next();
|
||||
String d2 = dstf2.next();
|
||||
assertEquals(s2, d2);
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(d2));
|
||||
assertEquals(src.f2.get(s2), dst.f2.get(s2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -714,7 +703,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
||||
@Test
|
||||
public void testFinalClass() throws Exception {
|
||||
try {
|
||||
TemplateBuilder.build(FinalModifierClass.class);
|
||||
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(FinalModifierClass.class);
|
||||
Assert.assertNull(builder);
|
||||
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(FinalModifierClass.class);
|
||||
assertTrue(true);
|
||||
} catch (TemplateBuildException e) {
|
||||
fail();
|
||||
@ -731,7 +722,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
||||
@Test
|
||||
public void testInterfaceType00() throws Exception {
|
||||
try {
|
||||
TemplateBuilder.build(SampleInterface.class);
|
||||
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
|
||||
Assert.assertNull(builder);
|
||||
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
|
||||
fail();
|
||||
} catch (TemplateBuildException e) {
|
||||
assertTrue(true);
|
||||
@ -742,7 +735,9 @@ public class TestTemplateBuilderPackUnpack extends TestCase {
|
||||
@Test
|
||||
public void testInterfaceType01() throws Exception {
|
||||
try {
|
||||
TemplateBuilder.build(SampleInterface.class);
|
||||
TemplateBuilder builder = BuilderSelectorRegistry.getInstance().select(SampleInterface.class);
|
||||
Assert.assertNull(builder);
|
||||
BuilderSelectorRegistry.getInstance().getForceBuilder().buildTemplate(SampleInterface.class);
|
||||
fail();
|
||||
} catch (TemplateBuildException e) {
|
||||
assertTrue(true);
|
||||
|
110
java/src/test/java/org/msgpack/util/TestTemplatePrecompiler.java
Normal file
110
java/src/test/java/org/msgpack/util/TestTemplatePrecompiler.java
Normal file
@ -0,0 +1,110 @@
|
||||
package org.msgpack.util;
|
||||
|
||||
import org.junit.Test;
|
||||
import static org.junit.Assert.*;
|
||||
import org.msgpack.MessagePack;
|
||||
import org.msgpack.MessageTypeException;
|
||||
import org.msgpack.template.TemplateRegistry;
|
||||
|
||||
public class TestTemplatePrecompiler {
|
||||
|
||||
@Test
|
||||
public void testPrimitiveTypeFields00() throws Exception {
|
||||
System.getProperties().setProperty(TemplatePrecompiler.DIST, "./target/test-classes");
|
||||
Class<?> c = PrimitiveTypeFieldsClass.class;
|
||||
TemplatePrecompiler.saveTemplateClass(PrimitiveTypeFieldsClass.class);
|
||||
|
||||
PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass();
|
||||
src.f0 = (byte) 0;
|
||||
src.f1 = 1;
|
||||
src.f2 = 2;
|
||||
src.f3 = 3;
|
||||
src.f4 = 4;
|
||||
src.f5 = 5;
|
||||
src.f6 = false;
|
||||
|
||||
try {
|
||||
MessagePack.pack(src);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof MessageTypeException);
|
||||
assertTrue(TemplateRegistry.unregister(c));
|
||||
}
|
||||
try {
|
||||
TemplateRegistry.lookup(c, true, true);
|
||||
byte[] raw = MessagePack.pack(src);
|
||||
PrimitiveTypeFieldsClass dst = MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class);
|
||||
assertEquals(src.f0, dst.f0);
|
||||
assertEquals(src.f1, dst.f1);
|
||||
assertEquals(src.f2, dst.f2);
|
||||
assertEquals(src.f3, dst.f3);
|
||||
//assertEquals(src.f4, dst.f4);
|
||||
//assertEquals(src.f5, dst.f5);
|
||||
assertEquals(src.f6, dst.f6);
|
||||
} finally {
|
||||
TemplateRegistry.unregister(c);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveTypeFields01() throws Exception {
|
||||
System.getProperties().setProperty(TemplatePrecompiler.DIST, "./target/test-classes");
|
||||
Class<?> c = PrimitiveTypeFieldsClass.class;
|
||||
TemplatePrecompiler.saveTemplateClass(PrimitiveTypeFieldsClass.class);
|
||||
|
||||
PrimitiveTypeFieldsClass src = new PrimitiveTypeFieldsClass();
|
||||
|
||||
try {
|
||||
MessagePack.pack(src);
|
||||
fail();
|
||||
} catch (Exception e) {
|
||||
assertTrue(e instanceof MessageTypeException);
|
||||
assertTrue(TemplateRegistry.unregister(c));
|
||||
}
|
||||
try {
|
||||
TemplateRegistry.lookup(c, true, true);
|
||||
byte[] raw = MessagePack.pack(src);
|
||||
PrimitiveTypeFieldsClass dst = MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class);
|
||||
assertEquals(src.f0, dst.f0);
|
||||
assertEquals(src.f1, dst.f1);
|
||||
assertEquals(src.f2, dst.f2);
|
||||
assertEquals(src.f3, dst.f3);
|
||||
//assertEquals(src.f4, dst.f4);
|
||||
//assertEquals(src.f5, dst.f5);
|
||||
assertEquals(src.f6, dst.f6);
|
||||
} finally {
|
||||
TemplateRegistry.unregister(c);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveTypeFields02() throws Exception {
|
||||
System.getProperties().setProperty(TemplatePrecompiler.DIST, "./target/test-classes");
|
||||
Class<?> c = PrimitiveTypeFieldsClass.class;
|
||||
TemplatePrecompiler.saveTemplateClass(PrimitiveTypeFieldsClass.class);
|
||||
|
||||
PrimitiveTypeFieldsClass src = null;
|
||||
MessagePack.pack(src);
|
||||
try {
|
||||
TemplateRegistry.lookup(c, true, true);
|
||||
byte[] raw = MessagePack.pack(src);
|
||||
PrimitiveTypeFieldsClass dst = MessagePack.unpack(raw, PrimitiveTypeFieldsClass.class);
|
||||
assertEquals(src, dst);
|
||||
} finally {
|
||||
TemplateRegistry.unregister(c);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PrimitiveTypeFieldsClass {
|
||||
public byte f0;
|
||||
public short f1;
|
||||
public int f2;
|
||||
public long f3;
|
||||
public float f4;
|
||||
public double f5;
|
||||
public boolean f6;
|
||||
|
||||
public PrimitiveTypeFieldsClass() {
|
||||
}
|
||||
}
|
||||
}
|
11
ocaml/.gitignore
vendored
Normal file
11
ocaml/.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
*~
|
||||
*.omc
|
||||
.omakedb
|
||||
.omakedb.lock
|
||||
*.vo
|
||||
*.glob
|
||||
*.cm[iox]
|
||||
*.o
|
||||
*.annot
|
||||
*.opt
|
||||
*.run
|
8
ocaml/OMakefile
Normal file
8
ocaml/OMakefile
Normal file
@ -0,0 +1,8 @@
|
||||
NATIVE_ENABLED = true
|
||||
BYTE_ENABLED = true
|
||||
|
||||
.PHONY: clean
|
||||
.SUBDIRS: ocaml proof
|
||||
|
||||
clean:
|
||||
rm -rf *.vo *.glob *~ *.omc .omakedb .omakedb.lock
|
45
ocaml/OMakeroot
Normal file
45
ocaml/OMakeroot
Normal file
@ -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: .
|
22
ocaml/README.markdown
Normal file
22
ocaml/README.markdown
Normal file
@ -0,0 +1,22 @@
|
||||
MsgPack for OCaml
|
||||
==============================
|
||||
|
||||
See http://wiki.msgpack.org/display/MSGPACK/QuickStart+for+OCaml
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
14
ocaml/bleis-hooks/commit-msg
Executable file
14
ocaml/bleis-hooks/commit-msg
Executable file
@ -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
|
60
ocaml/bleis-hooks/common.sh
Executable file
60
ocaml/bleis-hooks/common.sh
Executable file
@ -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 }"
|
||||
}
|
||||
|
22
ocaml/bleis-hooks/pre-commit
Executable file
22
ocaml/bleis-hooks/pre-commit
Executable file
@ -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
|
2
ocaml/ocaml/.gitignore
vendored
Normal file
2
ocaml/ocaml/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
runner
|
||||
doc
|
6
ocaml/ocaml/META
Normal file
6
ocaml/ocaml/META
Normal file
@ -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"
|
80
ocaml/ocaml/OMakefile
Normal file
80
ocaml/ocaml/OMakefile
Normal file
@ -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.*
|
142
ocaml/ocaml/base.ml
Normal file
142
ocaml/ocaml/base.ml
Normal file
@ -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
|
1
ocaml/ocaml/config.ml
Normal file
1
ocaml/ocaml/config.ml
Normal file
@ -0,0 +1 @@
|
||||
let version = (1,0,0)
|
191
ocaml/ocaml/hList.ml
Normal file
191
ocaml/ocaml/hList.ml
Normal file
@ -0,0 +1,191 @@
|
||||
open Base
|
||||
|
||||
let rec last =
|
||||
function
|
||||
[] ->
|
||||
invalid_arg "HList.last"
|
||||
| [x] ->
|
||||
x
|
||||
| _::xs ->
|
||||
last xs
|
||||
|
||||
let init xs =
|
||||
let rec init' ys =
|
||||
function
|
||||
[] ->
|
||||
invalid_arg "HList.init"
|
||||
| [_] ->
|
||||
List.rev ys
|
||||
| x::xs ->
|
||||
init' (x::ys) xs in
|
||||
init' [] xs
|
||||
|
||||
let null =
|
||||
function
|
||||
[] ->
|
||||
true
|
||||
| _ ->
|
||||
false
|
||||
|
||||
let fold_left1 f =
|
||||
function
|
||||
[] ->
|
||||
invalid_arg "HList.fold_left1"
|
||||
| x::xs ->
|
||||
List.fold_left f x xs
|
||||
|
||||
let rec fold_right1 f =
|
||||
function
|
||||
[] ->
|
||||
invalid_arg "HList.fold_right1"
|
||||
| [x] ->
|
||||
x
|
||||
| x::xs ->
|
||||
f x (fold_right1 f xs)
|
||||
|
||||
let conj =
|
||||
List.fold_left (&&) true
|
||||
|
||||
let disj =
|
||||
List.fold_left (||) false
|
||||
|
||||
let sum =
|
||||
List.fold_left (+) 0
|
||||
|
||||
let product =
|
||||
List.fold_left ( * ) 1
|
||||
|
||||
let concat_map f xs =
|
||||
List.fold_right ((@) $ f) xs []
|
||||
|
||||
let maximum xs =
|
||||
fold_left1 max xs
|
||||
|
||||
let minimum xs =
|
||||
fold_left1 min xs
|
||||
|
||||
let rec scanl f y =
|
||||
function
|
||||
[] ->
|
||||
[y]
|
||||
| x::xs ->
|
||||
y::scanl f (f y x) xs
|
||||
|
||||
let scanl1 f =
|
||||
function
|
||||
[] ->
|
||||
[]
|
||||
| x::xs ->
|
||||
scanl f x xs
|
||||
|
||||
let rec scanr f z =
|
||||
function
|
||||
[] ->
|
||||
[z]
|
||||
| x::xs ->
|
||||
match scanr f z xs with
|
||||
y::_ as yss ->
|
||||
(f x y) :: yss
|
||||
| _ ->
|
||||
failwith "must not happen"
|
||||
|
||||
let scanr1 f =
|
||||
function
|
||||
[] ->
|
||||
[]
|
||||
| x::xs ->
|
||||
scanr f x xs
|
||||
|
||||
let replicate n x =
|
||||
let rec loop i ys =
|
||||
if i = 0 then
|
||||
ys
|
||||
else
|
||||
loop (i-1) (x::ys) in
|
||||
loop n []
|
||||
|
||||
let rec take n =
|
||||
function
|
||||
[] ->
|
||||
[]
|
||||
| x::xs ->
|
||||
if n <= 0 then
|
||||
[]
|
||||
else
|
||||
x :: take (n - 1) xs
|
||||
|
||||
let rec drop n =
|
||||
function
|
||||
[] ->
|
||||
[]
|
||||
| xs when n <= 0 ->
|
||||
xs
|
||||
| _::xs ->
|
||||
drop (n-1) xs
|
||||
|
||||
let rec splitAt n xs =
|
||||
match n,xs with
|
||||
0,_ | _,[] ->
|
||||
[],xs
|
||||
| _,y::ys ->
|
||||
let p,q =
|
||||
splitAt (n-1) ys in
|
||||
y::p,q
|
||||
|
||||
let rec takeWhile f =
|
||||
function
|
||||
x::xs when f x ->
|
||||
x :: takeWhile f xs
|
||||
| _ ->
|
||||
[]
|
||||
|
||||
let rec dropWhile f =
|
||||
function
|
||||
x::xs when f x ->
|
||||
dropWhile f xs
|
||||
| xs ->
|
||||
xs
|
||||
|
||||
let rec span f =
|
||||
function
|
||||
x::xs when f x ->
|
||||
let ys,zs =
|
||||
span f xs in
|
||||
x::ys,zs
|
||||
| xs ->
|
||||
[],xs
|
||||
|
||||
let break f =
|
||||
span (not $ f)
|
||||
|
||||
let rec zip_with f xs ys =
|
||||
match xs,ys with
|
||||
[],_ | _,[] ->
|
||||
[]
|
||||
| x::xs',y::ys' ->
|
||||
(f x y)::zip_with f xs' ys'
|
||||
|
||||
let rec zip_with3 f xs ys zs =
|
||||
match xs,ys,zs with
|
||||
[],_,_ | _,[],_ | _,_,[] ->
|
||||
[]
|
||||
| x::xs',y::ys',z::zs' ->
|
||||
(f x y z)::zip_with3 f xs' ys' zs'
|
||||
|
||||
let zip xs ys =
|
||||
zip_with (fun x y -> (x,y)) xs ys
|
||||
|
||||
let zip3 xs ys zs =
|
||||
zip_with3 (fun x y z -> (x,y,z)) xs ys zs
|
||||
|
||||
let unzip xs =
|
||||
List.fold_right (fun (x,y) (xs,ys) -> (x::xs,y::ys)) xs ([],[])
|
||||
|
||||
let unzip3 xs =
|
||||
List.fold_right (fun (x,y,z) (xs,ys,zs) -> (x::xs,y::ys,z::zs)) xs ([],[],[])
|
||||
|
||||
let lookup x xs =
|
||||
try
|
||||
Some (List.assoc x xs)
|
||||
with Not_found ->
|
||||
None
|
2
ocaml/ocaml/main.ml
Normal file
2
ocaml/ocaml/main.ml
Normal file
@ -0,0 +1,2 @@
|
||||
let _ =
|
||||
print_endline "hello"
|
46
ocaml/ocaml/msgpack.mli
Normal file
46
ocaml/ocaml/msgpack.mli
Normal file
@ -0,0 +1,46 @@
|
||||
(** MessagePack for OCaml *)
|
||||
|
||||
(** Conversion MessagePack object between OCaml and Coq. *)
|
||||
module Pack : sig
|
||||
(** exception when MesagePack object is invalid form *)
|
||||
exception Not_conversion of string
|
||||
end
|
||||
|
||||
(** MessagePack Serializer *)
|
||||
module Serialize : sig
|
||||
(** MesagePack object. See also {{:http://redmine.msgpack.org/projects/msgpack/wiki/FormatSpec}MessagePack specification}. *)
|
||||
type t =
|
||||
[ `Bool of bool
|
||||
| `Nil
|
||||
| `PFixnum of int
|
||||
| `NFixnum of int
|
||||
| `Uint8 of int
|
||||
| `Uint16 of int
|
||||
| `Uint32 of int64
|
||||
| `Uint64 of Big_int.big_int
|
||||
| `Int8 of int
|
||||
| `Int16 of int
|
||||
| `Int32 of int32
|
||||
| `Int64 of int64
|
||||
| `Float of float
|
||||
| `Double of float
|
||||
| `FixRaw of char list
|
||||
| `Raw16 of char list
|
||||
| `Raw32 of char list
|
||||
| `FixArray of t list
|
||||
| `Array16 of t list
|
||||
| `Array32 of t list
|
||||
| `FixMap of (t * t) list
|
||||
| `Map16 of (t * t) list
|
||||
| `Map32 of (t * t) list ]
|
||||
|
||||
(** [MessagePack.Serialize.deserialize_string str] deserialize MessagePack string [str] to MessagePack object. *)
|
||||
val deserialize_string : string -> t
|
||||
|
||||
(** [MessagePack.Serialize.serialize_string obj] serialize MessagePack object [obj] to MessagePack string. *)
|
||||
val serialize_string : t -> string
|
||||
end
|
||||
|
||||
module Config : sig
|
||||
val version : int * int * int
|
||||
end
|
2581
ocaml/ocaml/msgpackCore.ml
Normal file
2581
ocaml/ocaml/msgpackCore.ml
Normal file
File diff suppressed because it is too large
Load Diff
141
ocaml/ocaml/msgpackCore.mli
Normal file
141
ocaml/ocaml/msgpackCore.mli
Normal file
@ -0,0 +1,141 @@
|
||||
val fst : ('a1 * 'a2) -> 'a1
|
||||
|
||||
val snd : ('a1 * 'a2) -> 'a2
|
||||
|
||||
val length : 'a1 list -> int
|
||||
|
||||
val app : 'a1 list -> 'a1 list -> 'a1 list
|
||||
|
||||
val plus : int -> int -> int
|
||||
|
||||
val mult : int -> int -> int
|
||||
|
||||
type positive =
|
||||
| XI of positive
|
||||
| XO of positive
|
||||
| XH
|
||||
|
||||
val psucc : positive -> positive
|
||||
|
||||
val pplus : positive -> positive -> positive
|
||||
|
||||
val pplus_carry : positive -> positive -> positive
|
||||
|
||||
val pmult_nat : positive -> int -> int
|
||||
|
||||
val nat_of_P : positive -> int
|
||||
|
||||
val p_of_succ_nat : int -> positive
|
||||
|
||||
val pmult : positive -> positive -> positive
|
||||
|
||||
type n =
|
||||
| N0
|
||||
| Npos of positive
|
||||
|
||||
val nplus : n -> n -> n
|
||||
|
||||
val nmult : n -> n -> n
|
||||
|
||||
val nat_of_N : n -> int
|
||||
|
||||
val n_of_nat : int -> n
|
||||
|
||||
val flat_map : ('a1 -> 'a2 list) -> 'a1 list -> 'a2 list
|
||||
|
||||
val eucl_dev : int -> int -> (int * int)
|
||||
|
||||
type ascii =
|
||||
| Ascii of bool * bool * bool * bool * bool * bool * bool * bool
|
||||
|
||||
val zero : ascii
|
||||
|
||||
val one : ascii
|
||||
|
||||
val shift : bool -> ascii -> ascii
|
||||
|
||||
val ascii_of_pos : positive -> ascii
|
||||
|
||||
val ascii_of_N : n -> ascii
|
||||
|
||||
val ascii_of_nat : int -> ascii
|
||||
|
||||
val n_of_digits : bool list -> n
|
||||
|
||||
val n_of_ascii : ascii -> n
|
||||
|
||||
val nat_of_ascii : ascii -> int
|
||||
|
||||
val take : int -> 'a1 list -> 'a1 list
|
||||
|
||||
val drop : int -> 'a1 list -> 'a1 list
|
||||
|
||||
val split_at : int -> 'a1 list -> 'a1 list * 'a1 list
|
||||
|
||||
val pair : 'a1 list -> ('a1 * 'a1) list
|
||||
|
||||
val pow : int -> int
|
||||
|
||||
val divmod : int -> int -> (int * int)
|
||||
|
||||
type ascii8 = ascii
|
||||
|
||||
type ascii16 = ascii8 * ascii8
|
||||
|
||||
type ascii32 = ascii16 * ascii16
|
||||
|
||||
type ascii64 = ascii32 * ascii32
|
||||
|
||||
val nat_of_ascii8 : ascii -> int
|
||||
|
||||
val ascii8_of_nat : int -> ascii
|
||||
|
||||
val ascii16_of_nat : int -> ascii * ascii
|
||||
|
||||
val nat_of_ascii16 : ascii16 -> int
|
||||
|
||||
val ascii32_of_nat : int -> (ascii * ascii) * (ascii * ascii)
|
||||
|
||||
val nat_of_ascii32 : ascii32 -> int
|
||||
|
||||
val list_of_ascii8 : ascii8 -> ascii8 list
|
||||
|
||||
val list_of_ascii16 : ascii16 -> ascii8 list
|
||||
|
||||
val list_of_ascii32 : ascii32 -> ascii8 list
|
||||
|
||||
val list_of_ascii64 : ascii64 -> ascii8 list
|
||||
|
||||
type object0 =
|
||||
| Bool of bool
|
||||
| Nil
|
||||
| PFixnum of ascii8
|
||||
| NFixnum of ascii8
|
||||
| Uint8 of ascii8
|
||||
| Uint16 of ascii16
|
||||
| Uint32 of ascii32
|
||||
| Uint64 of ascii64
|
||||
| Int8 of ascii8
|
||||
| Int16 of ascii16
|
||||
| Int32 of ascii32
|
||||
| Int64 of ascii64
|
||||
| Float of ascii32
|
||||
| Double of ascii64
|
||||
| FixRaw of ascii8 list
|
||||
| Raw16 of ascii8 list
|
||||
| Raw32 of ascii8 list
|
||||
| FixArray of object0 list
|
||||
| Array16 of object0 list
|
||||
| Array32 of object0 list
|
||||
| FixMap of (object0 * object0) list
|
||||
| Map16 of (object0 * object0) list
|
||||
| Map32 of (object0 * object0) list
|
||||
|
||||
val atat : ('a1 -> 'a2) -> 'a1 -> 'a2
|
||||
|
||||
val serialize : object0 -> ascii8 list
|
||||
|
||||
val compact : object0 list -> ascii8 list
|
||||
|
||||
val deserialize : int -> ascii8 list -> object0 list
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user