From 1b010a082b2e601961856d74bf76f638c31480f2 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Tue, 1 Jun 2010 10:53:19 +0900 Subject: [PATCH 01/13] Add go binding. --- go/Makefile | 11 + go/msgpack_test.go | 152 ++++++++++++ go/pack.go | 581 +++++++++++++++++++++++++++++++++++++++++++++ go/unpack.go | 203 ++++++++++++++++ 4 files changed, 947 insertions(+) create mode 100644 go/Makefile create mode 100644 go/msgpack_test.go create mode 100644 go/pack.go create mode 100644 go/unpack.go diff --git a/go/Makefile b/go/Makefile new file mode 100644 index 00000000..289bd122 --- /dev/null +++ b/go/Makefile @@ -0,0 +1,11 @@ +include $(GOROOT)/src/Make.$(GOARCH) + +TARG=msgpack + +GOFILES=pack.go unpack.go + +include $(GOROOT)/src/Make.pkg + +%: install %.go + $(GC) $*.go + $(LD) -o $@ $*.$O diff --git a/go/msgpack_test.go b/go/msgpack_test.go new file mode 100644 index 00000000..a5dda2a4 --- /dev/null +++ b/go/msgpack_test.go @@ -0,0 +1,152 @@ +package msgpack_test + +import ( + . "msgpack" + "testing" + "bytes" + "reflect" +); + +func TestPackUint8(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint8 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255 } { + _, err := PackUint8(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackUint16(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint16 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255, 256, 65533, 65534, 65535 } { + _, err := PackUint16(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xcd, 0x01, 0x00, 0xcd, 0xff, 0xfd, 0xcd, 0xff, 0xfe, 0xcd, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackUint32(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint32 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255, 256, 65533, 65534, 65535, 65536, 4294967293, 4294967294, 4294967295 } { + _, err := PackUint32(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xcd, 0x01, 0x00, 0xcd, 0xff, 0xfd, 0xcd, 0xff, 0xfe, 0xcd, 0xff, 0xff, 0xce, 0x00, 0x01, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0xfd, 0xce, 0xff, 0xff, 0xff, 0xfe, 0xce, 0xff, 0xff, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackUint64(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []uint64 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255, 256, 65533, 65534, 65535, 65536, 4294967293, 4294967294, 4294967295, 4294967296, 18446744073709551613, 18446744073709551614, 18446744073709551615 } { + _, err := PackUint64(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xcd, 0x01, 0x00, 0xcd, 0xff, 0xfd, 0xcd, 0xff, 0xfe, 0xcd, 0xff, 0xff, 0xce, 0x00, 0x01, 0x00, 0x00, 0xce, 0xff, 0xff, 0xff, 0xfd, 0xce, 0xff, 0xff, 0xff, 0xfe, 0xce, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfd, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt8(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int8 { -128, -127, -34, -33, -32, -31, 0, 1, 126, 127 } { + _, err := PackInt8(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt16(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int16 { -32768, -32767, -131, -130, -129, -128, -127, -34, -33, -32, -31, 0, 1, 126, 127, 128, 129, 130, 32765, 32766, 32767 } { + _, err := PackInt16(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd1, 0x80, 0x00, 0xd1, 0x80, 0x01, 0xd1, 0xff, 0x7d, 0xd1, 0xff, 0x7e, 0xd1, 0xff, 0x7f, 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f, 0xd1, 0x00, 0x80, 0xd1, 0x00, 0x81, 0xd1, 0x00, 0x82, 0xd1, 0x7f, 0xfd, 0xd1, 0x7f, 0xfe, 0xd1, 0x7f, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt32(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int32 { -2147483648, -2147483647, -2147483646, -32771, -32770, -32769, -32768, -32767, -131, -130, -129, -128, -127, -34, -33, -32, -31, 0, 1, 126, 127, 128, 129, 130, 32765, 32766, 32767, 32768, 32769, 32770, 2147483645, 2147483646, 2147483647 } { + _, err := PackInt32(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd2, 0x80, 0x00, 0x00, 0x00, 0xd2, 0x80, 0x00, 0x00, 0x01, 0xd2, 0x80, 0x00, 0x00, 0x02, 0xd2, 0xff, 0xff, 0x7f, 0xfd, 0xd2, 0xff, 0xff, 0x7f, 0xfe, 0xd2, 0xff, 0xff, 0x7f, 0xff, 0xd1, 0x80, 0x00, 0xd1, 0x80, 0x01, 0xd1, 0xff, 0x7d, 0xd1, 0xff, 0x7e, 0xd1, 0xff, 0x7f, 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f, 0xd1, 0x00, 0x80, 0xd1, 0x00, 0x81, 0xd1, 0x00, 0x82, 0xd1, 0x7f, 0xfd, 0xd1, 0x7f, 0xfe, 0xd1, 0x7f, 0xff, 0xd2, 0x00, 0x00, 0x80, 0x00, 0xd2, 0x00, 0x00, 0x80, 0x01, 0xd2, 0x00, 0x00, 0x80, 0x02, 0xd2, 0x7f, 0xff, 0xff, 0xfd, 0xd2, 0x7f, 0xff, 0xff, 0xfe, 0xd2, 0x7f, 0xff, 0xff, 0xff }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt64(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []int64 { -9223372036854775808, -9223372036854775807, -9223372036854775806, -2147483651, -2147483650, -2147483649, -2147483648, -2147483647, -2147483646, -32771, -32770, -32769, -32768, -32767, -131, -130, -129, -128, -127, -34, -33, -32, -31, 0, 1, 126, 127, 128, 129, 130, 32765, 32766, 32767, 32768, 32769, 32770, 2147483645, 2147483646, 2147483647, 2147483648, 2147483649, 2147483650, 4294967296, 4294967297, 4294967298 } { + _, err := PackInt64(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfd, 0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xfe, 0xd3, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0xd2, 0x80, 0x00, 0x00, 0x00, 0xd2, 0x80, 0x00, 0x00, 0x01, 0xd2, 0x80, 0x00, 0x00, 0x02, 0xd2, 0xff, 0xff, 0x7f, 0xfd, 0xd2, 0xff, 0xff, 0x7f, 0xfe, 0xd2, 0xff, 0xff, 0x7f, 0xff, 0xd1, 0x80, 0x00, 0xd1, 0x80, 0x01, 0xd1, 0xff, 0x7d, 0xd1, 0xff, 0x7e, 0xd1, 0xff, 0x7f, 0xd0, 0x80, 0xd0, 0x81, 0xd0, 0xde, 0xd0, 0xdf, 0xe0, 0xe1, 0x00, 0x01, 0x7e, 0x7f, 0xd1, 0x00, 0x80, 0xd1, 0x00, 0x81, 0xd1, 0x00, 0x82, 0xd1, 0x7f, 0xfd, 0xd1, 0x7f, 0xfe, 0xd1, 0x7f, 0xff, 0xd2, 0x00, 0x00, 0x80, 0x00, 0xd2, 0x00, 0x00, 0x80, 0x01, 0xd2, 0x00, 0x00, 0x80, 0x02, 0xd2, 0x7f, 0xff, 0xff, 0xfd, 0xd2, 0x7f, 0xff, 0xff, 0xfe, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x02, 0xd3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackNil(t *testing.T) { + b := &bytes.Buffer{} + nbyteswrite, err := PackNil(b) + if nbyteswrite != 1 { t.Error("nbyteswrite != 1") } + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0xc0 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackBool(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range []bool { false, true } { + nbyteswrite, err := PackBool(b, i) + if nbyteswrite != 1 { t.Error("nbyteswrite != 1") } + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xc2, 0xc3 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackInt32Array(t *testing.T) { + b := &bytes.Buffer{} + _, err := PackInt32Array(b, []int32 {}) + if err != nil { t.Error("err != nil") } + _, err = PackInt32Array(b, []int32 { 0 }) + if err != nil { t.Error("err != nil") } + _, err = PackInt32Array(b, []int32 { 0, 1 }) + if err != nil { t.Error("err != nil") } + _, err = PackInt32Array(b, []int32 { 0, 1, 2 }) + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0x90, 0x91, 0x00, 0x92, 0x00, 0x01, 0x93, 0x00, 0x01, 0x02 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackArray(t *testing.T) { + b := &bytes.Buffer{} + _, err := PackArray(b, reflect.NewValue([]int32 {}).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + _, err = PackArray(b, reflect.NewValue([]int32 { 0 }).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + _, err = PackArray(b, reflect.NewValue([]int32 { 0, 1 }).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + _, err = PackArray(b, reflect.NewValue([]int32 { 0, 1, 2 }).(reflect.ArrayOrSliceValue)) + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0x90, 0x91, 0x00, 0x92, 0x00, 0x01, 0x93, 0x00, 0x01, 0x02 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPackMap(t *testing.T) { + b := &bytes.Buffer{} + _, err := PackMap(b, reflect.NewValue(map[int] int { 0: 1, 2: 3, 4: 5 }).(*reflect.MapValue)) + if err != nil { t.Error("err != nil") } + if bytes.Compare(b.Bytes(), []byte { 0x83, 0x00, 0x01, 0x04, 0x05, 0x02, 0x03 }) != 0 { t.Error("wrong output", b.Bytes()) } +} + +func TestPack(t *testing.T) { + b := &bytes.Buffer{} + for _, i := range [](interface{}) { nil, false, true, 0, 1, 2, 3, 127, -32, -1, -33, 128 } { + _, err := Pack(b, i) + if err != nil { t.Error("err != nil") } + } + if bytes.Compare(b.Bytes(), []byte { 0xc0, 0xc2, 0xc3, 0x00, 0x01, 0x02, 0x03, 0x7f, 0xf0, 0xff, 0xd0, 0xef, 0xd1, 0x00, 0x80 }) == 0 { t.Error("wrong output") } +} + +func TestUnpack(t *testing.T) { + b := bytes.NewBuffer([]byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) + for _, v := range [](interface{}) { + int8(0), int8(1), int8(2), int8(125), int8(126), int8(127), + uint8(128), uint8(253), uint8(254), uint8(255), int32(2147483647), + int64(9223372036854775807) } { + retval, _, e := Unpack(b) + if e != nil { t.Error("err != nil") } + if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } + } +} diff --git a/go/pack.go b/go/pack.go new file mode 100644 index 00000000..8240394c --- /dev/null +++ b/go/pack.go @@ -0,0 +1,581 @@ +package msgpack + +import ( + "io" + "os" + "unsafe" + "reflect" +); + +func PackUint8(writer io.Writer, value uint8) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } + return writer.Write([]byte { 0xcc, byte(value) }) +} + +func PackUint16(writer io.Writer, value uint16) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } else if value < 256 { + return writer.Write([]byte { 0xcc, byte(value) }) + } + return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) +} + +func PackUint32(writer io.Writer, value uint32) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } else if value < 256 { + return writer.Write([]byte { 0xcc, byte(value) }) + } else if value < 65536 { + return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) + } + return writer.Write([]byte { 0xce, byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) +} + +func PackUint64(writer io.Writer, value uint64) (n int, err os.Error) { + if value < 128 { + return writer.Write([]byte { byte(value) }) + } else if value < 256 { + return writer.Write([]byte { 0xcc, byte(value) }) + } else if value < 65536 { + return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) + } else if value < 4294967296 { + return writer.Write([]byte { 0xce, byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) + } + return writer.Write([]byte { 0xcf, byte(value >> 56), byte(value >> 48), byte(value >> 40), byte(value >> 32), byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) +} + +func PackUint(writer io.Writer, value uint) (n int, err os.Error) { + switch unsafe.Sizeof(value) { + case 4: + return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) + case 8: + return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + + +func PackInt8(writer io.Writer, value int8) (n int, err os.Error) { + if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt16(writer io.Writer, value int16) (n int, err os.Error) { + if value < -128 || value >= 128 { + return writer.Write([]byte { 0xd1, byte(uint16(value) >> 8), byte(value) }) + } else if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt32(writer io.Writer, value int32) (n int, err os.Error) { + if value < -32768 || value >= 32768 { + return writer.Write([]byte { 0xd2, byte(uint32(value) >> 24), byte(uint32(value) >> 16), byte(uint32(value) >> 8), byte(value) }) + } else if value < -128 { + return writer.Write([]byte { 0xd1, byte(uint32(value) >> 8), byte(value) }) + } else if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } else if value >= 128 { + return writer.Write([]byte { 0xd1, byte(uint32(value) >> 8), byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt64(writer io.Writer, value int64) (n int, err os.Error) { + if value < -2147483648 || value >= 2147483648 { + return writer.Write([]byte { 0xd3, byte(uint64(value) >> 56), byte(uint64(value) >> 48), byte(uint64(value) >> 40), byte(uint64(value) >> 32), byte(uint64(value) >> 24), byte(uint64(value) >> 16), byte(uint64(value) >> 8), byte(value) }) + } else if value < -32768 || value >= 32768 { + return writer.Write([]byte { 0xd2, byte(uint64(value) >> 24), byte(uint64(value) >> 16), byte(uint64(value) >> 8), byte(value) }) + } else if value < -128 || value >= 128 { + return writer.Write([]byte { 0xd1, byte(uint64(value) >> 8), byte(value) }) + } else if value < -32 { + return writer.Write([]byte { 0xd0, byte(value) }) + } + return writer.Write([]byte { byte(value) }) +} + +func PackInt(writer io.Writer, value int) (n int, err os.Error) { + switch unsafe.Sizeof(value) { + case 4: + return PackInt32(writer, *(*int32)(unsafe.Pointer(&value))) + case 8: + return PackInt64(writer, *(*int64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackNil(writer io.Writer) (n int, err os.Error) { + return writer.Write([]byte{ 0xc0 }) +} + +func PackBool(writer io.Writer, value bool) (n int, err os.Error) { + var code byte; + if value { + code = 0xc3 + } else { + code = 0xc2 + } + return writer.Write([]byte{ code }) +} + +func PackFloat32(writer io.Writer, value float32) (n int, err os.Error) { + return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) +} + +func PackFloat64(writer io.Writer, value float64) (n int, err os.Error) { + return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) +} + +func PackFloat(writer io.Writer, value float) (n int, err os.Error) { + switch unsafe.Sizeof(value) { + case 4: + return PackFloat32(writer, *(*float32)(unsafe.Pointer(&value))) + case 8: + return PackFloat64(writer, *(*float64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { + if len(value) < 32 { + n1, err := writer.Write([]byte { 0xa0 | uint8(len(value)) }) + if err != nil { return n1, err } + n2, err := writer.Write(value) + return n1 + n2, err + } else if len(value) < 65536 { + n1, err := writer.Write([]byte { 0xda, byte(len(value) >> 16), byte(len(value)) }) + if err != nil { return n1, err } + n2, err := writer.Write(value) + return n1 + n2, err + } + n1, err := writer.Write([]byte { 0xdb, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n1, err } + n2, err := writer.Write(value) + return n1 + n2, err +} + +func PackUint16Array(writer io.Writer, value []uint16) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint16(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint16(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint16(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackUint32Array(writer io.Writer, value []uint32) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint32(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint32(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint32(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackUint64Array(writer io.Writer, value []uint64) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint64(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint64(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackUint64(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackUintArray(writer io.Writer, value []uint) (n int, err os.Error) { + switch unsafe.Sizeof(0) { + case 4: + return PackUint32Array(writer, *(*[]uint32)(unsafe.Pointer(&value))) + case 8: + return PackUint64Array(writer, *(*[]uint64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackInt8Array(writer io.Writer, value []int8) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt8(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt8(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt8(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackInt16Array(writer io.Writer, value []int16) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt16(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt16(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt16(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackInt32Array(writer io.Writer, value []int32) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt32(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt32(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt32(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackInt64Array(writer io.Writer, value []int64) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt64(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt64(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackInt64(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackIntArray(writer io.Writer, value []int) (n int, err os.Error) { + switch unsafe.Sizeof(0) { + case 4: + return PackInt32Array(writer, *(*[]int32)(unsafe.Pointer(&value))) + case 8: + return PackInt64Array(writer, *(*[]int64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackFloat32Array(writer io.Writer, value []float32) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat32(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat32(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat32(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { + if len(value) < 16 { + n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat64(writer, i) + if err != nil { return n, err } + n += _n + } + } else if len(value) < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat64(writer, i) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(len(value) >> 24), byte(len(value) >> 16), byte(len(value) >> 8), byte(len(value)) }) + if err != nil { return n, err } + for _, i := range value { + _n, err := PackFloat64(writer, i) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackFloatArray(writer io.Writer, value []float) (n int, err os.Error) { + switch unsafe.Sizeof(0) { + case 4: + return PackFloat32Array(writer, *(*[]float32)(unsafe.Pointer(&value))) + case 8: + return PackFloat64Array(writer, *(*[]float64)(unsafe.Pointer(&value))) + } + return 0, os.ENOENT // never get here +} + +func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { + l := value.Len() + if l < 16 { + n, err := writer.Write([]byte { 0x90 | byte(l) }) + if err != nil { return n, err } + for i := 0; i < l; i++ { + _n, err := PackValue(writer, value.Elem(i)) + if err != nil { return n, err } + n += _n + } + } else if l < 65536 { + n, err := writer.Write([]byte { 0xdc, byte(l >> 8), byte(l) }) + if err != nil { return n, err } + for i := 0; i < l; i++ { + _n, err := PackValue(writer, value.Elem(i)) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdd, byte(l >> 24), byte(l >> 16), byte(l >> 8), byte(l) }) + if err != nil { return n, err } + for i := 0; i < l; i++ { + _n, err := PackValue(writer, value.Elem(i)) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { + keys := value.Keys() + if value.Len() < 16 { + n, err := writer.Write([]byte { 0x80 | byte(len(keys)) }) + if err != nil { return n, err } + for _, k := range keys { + _n, err := PackValue(writer, k) + if err != nil { return n, err } + n += _n + _n, err = PackValue(writer, value.Elem(k)) + if err != nil { return n, err } + n += _n + } + } else if value.Len() < 65536 { + n, err := writer.Write([]byte { 0xde, byte(len(keys) >> 8), byte(len(keys)) }) + if err != nil { return n, err } + for _, k := range keys { + _n, err := PackValue(writer, k) + if err != nil { return n, err } + n += _n + _n, err = PackValue(writer, value.Elem(k)) + if err != nil { return n, err } + n += _n + } + } else { + n, err := writer.Write([]byte { 0xdf, byte(len(keys) >> 24), byte(len(keys) >> 16), byte(len(keys) >> 8), byte(len(keys)) }) + if err != nil { return n, err } + for _, k := range keys { + _n, err := PackValue(writer, k) + if err != nil { return n, err } + n += _n + _n, err = PackValue(writer, value.Elem(k)) + if err != nil { return n, err } + n += _n + } + } + return n, nil +} + +func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { + if value.Type() == nil { return PackNil(writer) } + switch _value := value.(type) { + case *reflect.BoolValue: return PackBool(writer, _value.Get()) + case *reflect.Uint8Value: return PackUint8(writer, _value.Get()) + case *reflect.Uint16Value: return PackUint16(writer, _value.Get()) + case *reflect.Uint32Value: return PackUint32(writer, _value.Get()) + case *reflect.Uint64Value: return PackUint64(writer, _value.Get()) + case *reflect.UintValue: return PackUint(writer, _value.Get()) + case *reflect.Int8Value: return PackInt8(writer, _value.Get()) + case *reflect.Int16Value: return PackInt16(writer, _value.Get()) + case *reflect.Int32Value: return PackInt32(writer, _value.Get()) + case *reflect.Int64Value: return PackInt64(writer, _value.Get()) + case *reflect.IntValue: return PackInt(writer, _value.Get()) + case *reflect.Float32Value: return PackFloat32(writer, _value.Get()) + case *reflect.Float64Value: return PackFloat64(writer, _value.Get()) + case *reflect.FloatValue: return PackFloat(writer, _value.Get()) + case *reflect.ArrayValue: return PackArray(writer, _value) + case *reflect.SliceValue: return PackArray(writer, _value) + case *reflect.MapValue: return PackMap(writer, _value) + } + panic("unsupported type: " + value.Type().String()) +} + +func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { + if value == nil { return PackNil(writer) } + switch _value := value.(type) { + case bool: return PackBool(writer, _value) + case uint8: return PackUint8(writer, _value) + case uint16: return PackUint16(writer, _value) + case uint32: return PackUint32(writer, _value) + case uint64: return PackUint64(writer, _value) + case uint: return PackUint(writer, _value) + case int8: return PackInt8(writer, _value) + case int16: return PackInt16(writer, _value) + case int32: return PackInt32(writer, _value) + case int64: return PackInt64(writer, _value) + case int: return PackInt(writer, _value) + case float32: return PackFloat32(writer, _value) + case float64: return PackFloat64(writer, _value) + case float: return PackFloat(writer, _value) + case []byte: return PackBytes(writer, _value) + case []uint16: return PackUint16Array(writer, _value) + case []uint32: return PackUint32Array(writer, _value) + case []uint64: return PackUint64Array(writer, _value) + case []uint: return PackUintArray(writer, _value) + case []int8: return PackInt8Array(writer, _value) + case []int16: return PackInt16Array(writer, _value) + case []int32: return PackInt32Array(writer, _value) + case []int64: return PackInt64Array(writer, _value) + case []int: return PackIntArray(writer, _value) + case []float32: return PackFloat32Array(writer, _value) + case []float64: return PackFloat64Array(writer, _value) + case []float: return PackFloatArray(writer, _value) + default: + return PackValue(writer, reflect.NewValue(value)) + } + return 0, nil // never get here +} diff --git a/go/unpack.go b/go/unpack.go new file mode 100644 index 00000000..4bae8a3b --- /dev/null +++ b/go/unpack.go @@ -0,0 +1,203 @@ +package msgpack + +import ( + "io" + "os" + "unsafe" + "reflect" +) + +func readByte(reader io.Reader) (v uint8, err os.Error) { + data := [1]byte{} + _, e := reader.Read(data[0:]) + if e != nil { return 0, e } + return data[0], nil +} + +func readUint16(reader io.Reader) (v uint16, n int, err os.Error) { + data := [2]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (uint16(data[0]) >> 8) | uint16(data[1]), n, nil +} + +func readUint32(reader io.Reader) (v uint32, n int, err os.Error) { + data := [4]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (uint32(data[0]) << 24) | (uint32(data[1]) << 16) | (uint32(data[2]) << 8) | uint32(data[1]), n, nil +} + +func readUint64(reader io.Reader) (v uint64, n int, err os.Error) { + data := [8]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (uint64(data[0]) << 56) | (uint64(data[1]) << 48) | (uint64(data[2]) << 40) | (uint64(data[3]) << 32) | (uint64(data[4]) << 24) | (uint64(data[5]) << 16) | (uint64(data[6]) << 8) | uint64(data[7]), n, nil +} + +func readInt16(reader io.Reader) (v int16, n int, err os.Error) { + data := [2]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (int16(data[0]) << 8) | int16(data[1]), n, nil +} + +func readInt32(reader io.Reader) (v int32, n int, err os.Error) { + data := [4]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (int32(data[0]) << 24) | (int32(data[1]) << 16) | (int32(data[2]) << 8) | int32(data[1]), n, nil +} + +func readInt64(reader io.Reader) (v int64, n int, err os.Error) { + data := [8]byte{} + n, e := reader.Read(data[0:]) + if e != nil { return 0, n, e } + return (int64(data[0]) << 56) | (int64(data[1]) << 48) | (int64(data[2]) << 40) | (int64(data[3]) << 32) | (int64(data[4]) << 24) | (int64(data[5]) << 16) | (int64(data[6]) << 8) | int64(data[7]), n, nil +} + +func unpackArray(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make([]interface{}, nelems) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + v, n, e := Unpack(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[i] = v.Interface() + } + return reflect.NewValue(retval), nbytesread, nil +} + +func unpackMap(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make(map [interface{}] interface{}) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + k, n, e := Unpack(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + v, n, e := Unpack(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[k.Interface()] = v.Interface() + } + return reflect.NewValue(retval), nbytesread, nil +} + +func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { + var retval reflect.Value + var nbytesread int = 0 + + c, e := readByte(reader) + if e != nil { return nil, 0, e } + nbytesread += 1 + if c < 0x80 || c >= 0xe0 { + retval = reflect.NewValue(int8(c)) + } else if c >= 0x80 && c <= 0x8f { + retval, n, e = unpackMap(reader, uint(c & 0xf)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + nbytesread += n + } else if c >= 0x90 && c <= 0x9f { + retval, n, e = unpackArray(reader, uint(c & 0xf)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + nbytesread += n + } else if c >= 0xa0 && c <= 0xbf { + data := make([]byte, c & 0xf); + n, e := reader.Read(data) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + } else { + switch c { + case 0xc0: retval = reflect.NewValue(nil) + case 0xc2: retval = reflect.NewValue(false) + case 0xc3: retval = reflect.NewValue(true) + case 0xca: + data, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(*(*float32)(unsafe.Pointer(&data))) + case 0xcb: + data, n, e := readUint64(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(*(*float64)(unsafe.Pointer(&data))) + case 0xcc: + data, e := readByte(reader) + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(uint8(data)) + nbytesread += 1 + case 0xcd: + data, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xce: + data, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xcf: + data, n, e := readUint64(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xd0: + data, e := readByte(reader) + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(int8(data)) + nbytesread += 1 + case 0xd1: + data, n, e := readInt16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xd2: + data, n, e := readInt32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xd3: + data, n, e := readInt64(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xda: + nbytestoread, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + data := make([]byte, nbytestoread) + n, e = reader.Read(data) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xdb: + nbytestoread, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + data := make([]byte, nbytestoread) + n, e = reader.Read(data) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval = reflect.NewValue(data) + case 0xdc: + nelemstoread, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackArray(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + case 0xdd: + nelemstoread, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackArray(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + } + } + return retval, nbytesread, nil +} From fccf1016e454c6972c6d6a15b71a102d1407f8e2 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Wed, 9 Jun 2010 03:28:28 +0900 Subject: [PATCH 02/13] Fix bugs in unpacker. --- go/unpack.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/go/unpack.go b/go/unpack.go index 4bae8a3b..e2e3dc01 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -18,14 +18,14 @@ func readUint16(reader io.Reader) (v uint16, n int, err os.Error) { data := [2]byte{} n, e := reader.Read(data[0:]) if e != nil { return 0, n, e } - return (uint16(data[0]) >> 8) | uint16(data[1]), n, nil + return (uint16(data[0]) << 8) | uint16(data[1]), n, nil } func readUint32(reader io.Reader) (v uint32, n int, err os.Error) { data := [4]byte{} n, e := reader.Read(data[0:]) if e != nil { return 0, n, e } - return (uint32(data[0]) << 24) | (uint32(data[1]) << 16) | (uint32(data[2]) << 8) | uint32(data[1]), n, nil + return (uint32(data[0]) << 24) | (uint32(data[1]) << 16) | (uint32(data[2]) << 8) | uint32(data[3]), n, nil } func readUint64(reader io.Reader) (v uint64, n int, err os.Error) { @@ -46,7 +46,7 @@ func readInt32(reader io.Reader) (v int32, n int, err os.Error) { data := [4]byte{} n, e := reader.Read(data[0:]) if e != nil { return 0, n, e } - return (int32(data[0]) << 24) | (int32(data[1]) << 16) | (int32(data[2]) << 8) | int32(data[1]), n, nil + return (int32(data[0]) << 24) | (int32(data[1]) << 16) | (int32(data[2]) << 8) | int32(data[3]), n, nil } func readInt64(reader io.Reader) (v int64, n int, err os.Error) { From 8f1bd12a1716ece95e762b5983f9e1e99f05576d Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Wed, 9 Jun 2010 03:28:43 +0900 Subject: [PATCH 03/13] Improve testsuite. --- go/msgpack_test.go | 83 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/go/msgpack_test.go b/go/msgpack_test.go index a5dda2a4..9c695553 100644 --- a/go/msgpack_test.go +++ b/go/msgpack_test.go @@ -7,6 +7,72 @@ import ( "reflect" ); +func equal(lhs reflect.Value, rhs reflect.Value) bool { + { + _rhs, ok := rhs.(*reflect.InterfaceValue) + if ok { return equal(lhs, _rhs.Elem()) } + } + switch _lhs := lhs.(type) { + case *reflect.InterfaceValue: + return equal(_lhs.Elem(), rhs) + case *reflect.BoolValue: + _rhs, ok := rhs.(*reflect.BoolValue) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint8Value: + _rhs, ok := rhs.(*reflect.Uint8Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint16Value: + _rhs, ok := rhs.(*reflect.Uint16Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint32Value: + _rhs, ok := rhs.(*reflect.Uint32Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Uint64Value: + _rhs, ok := rhs.(*reflect.Uint64Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.UintValue: + _rhs, ok := rhs.(*reflect.UintValue) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int8Value: + _rhs, ok := rhs.(*reflect.Int8Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int16Value: + _rhs, ok := rhs.(*reflect.Int16Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int32Value: + _rhs, ok := rhs.(*reflect.Int32Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Int64Value: + _rhs, ok := rhs.(*reflect.Int64Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.IntValue: + _rhs, ok := rhs.(*reflect.IntValue) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Float32Value: + _rhs, ok := rhs.(*reflect.Float32Value) + return ok && _lhs.Get() == _rhs.Get() + case *reflect.Float64Value: + _rhs, ok := rhs.(*reflect.Float64Value) + return ok && _lhs.Get() == _rhs.Get() + case reflect.ArrayOrSliceValue: + _rhs := rhs.(reflect.ArrayOrSliceValue) + if _lhs.Len() != _rhs.Len() { return false; } + for i := 0; i < _lhs.Len(); i++ { + if !equal(_lhs.Elem(i), _rhs.Elem(i)) { return false; } + } + return true; + case *reflect.MapValue: + _rhs := rhs.(*reflect.MapValue) + if _lhs.Len() != _rhs.Len() { return false; } + for _, k := range _lhs.Keys() { + lv, rv := _lhs.Elem(k), _rhs.Elem(k) + if lv == nil || rv == nil || !equal(lv, rv) { return false; } + } + return true; + } + return false; +} + func TestPackUint8(t *testing.T) { b := &bytes.Buffer{} for _, i := range []uint8 { 0, 1, 2, 125, 126, 127, 128, 253, 254, 255 } { @@ -139,12 +205,19 @@ func TestPack(t *testing.T) { if bytes.Compare(b.Bytes(), []byte { 0xc0, 0xc2, 0xc3, 0x00, 0x01, 0x02, 0x03, 0x7f, 0xf0, 0xff, 0xd0, 0xef, 0xd1, 0x00, 0x80 }) == 0 { t.Error("wrong output") } } -func TestUnpack(t *testing.T) { - b := bytes.NewBuffer([]byte { 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) +func TestUnpackArray(t *testing.T) { + b := bytes.NewBuffer([]byte { 0x90, 0x91, 0x00, 0x92, 0x00, 0x01, 0x93, 0xd1, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x00, 0x01, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xdc, 0x00, 0x02, 0x00, 0x01, 0xdd, 0x00, 0x00, 0x00, 0x04, 0x00, 0x01, 0x02, 0x03 }) + for _, v := range [](interface{}) { [](interface{}) {}, [](interface{}) { int8(0) }, [](interface{}) { int8(0), int8(1) }, [](interface{}) { int16(0), int32(1), int64(2) }, [](interface{}){ int8(0), int8(1) }, [](interface{}) { int8(0), int8(1), int8(2), int8(3) } } { + retval, _, e := Unpack(b) + if e != nil { t.Error("err != nil") } + if !equal(reflect.NewValue(retval.Interface()), reflect.NewValue(v)) { t.Errorf("%s != %s", retval.Interface(), v) } + } +} + +func TestUnpackInt(t *testing.T) { + b := bytes.NewBuffer([]byte { 0xff, 0xe0, 0x00, 0x01, 0x02, 0x7d, 0x7e, 0x7f, 0xd0, 0x01, 0xd0, 0x80, 0xd0, 0xff, 0xcc, 0x80, 0xcc, 0xfd, 0xcc, 0xfe, 0xcc, 0xff, 0xd1, 0x00, 0x00, 0xd1, 0x7f, 0xff, 0xd1, 0xff, 0xff, 0xcd, 0x80, 0x00, 0xcd, 0xff, 0xff, 0xd2, 0x7f, 0xff, 0xff, 0xff, 0xce, 0x7f, 0xff, 0xff, 0xff, 0xd3, 0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }) for _, v := range [](interface{}) { - int8(0), int8(1), int8(2), int8(125), int8(126), int8(127), - uint8(128), uint8(253), uint8(254), uint8(255), int32(2147483647), - int64(9223372036854775807) } { + int8(-1), int8(-32), int8(0), int8(1), int8(2), int8(125), int8(126), int8(127), int8(1), int8(-128), int8(-1), uint8(128), uint8(253), uint8(254), uint8(255), int16(0), int16(32767), int16(-1), uint16(32768), uint16(65535), int32(2147483647), uint32(2147483647), int64(9223372036854775807), uint64(18446744073709551615) } { retval, _, e := Unpack(b) if e != nil { t.Error("err != nil") } if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } From ee0debc5b350e4a40c04dbd9df6da69b8c44d7ad Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Thu, 24 Jun 2010 00:56:49 +0900 Subject: [PATCH 04/13] Add .gitignore --- .gitignore | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.gitignore b/.gitignore index d740b181..b39017b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ *.o *.so ruby/Makefile +*.5 +*.8 +*.6 +_obj +_test From 8325cce44c227e3b6fb5ffbf25b796ffd43bdd1b Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sat, 26 Jun 2010 20:31:53 +0900 Subject: [PATCH 05/13] Adapt to new reflection API (notified by mattn. thanks) --- go/msgpack_test.go | 31 ++----------------------------- go/pack.go | 16 +++------------- 2 files changed, 5 insertions(+), 42 deletions(-) diff --git a/go/msgpack_test.go b/go/msgpack_test.go index 9c695553..e324f2eb 100644 --- a/go/msgpack_test.go +++ b/go/msgpack_test.go @@ -18,41 +18,14 @@ func equal(lhs reflect.Value, rhs reflect.Value) bool { case *reflect.BoolValue: _rhs, ok := rhs.(*reflect.BoolValue) return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint8Value: - _rhs, ok := rhs.(*reflect.Uint8Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint16Value: - _rhs, ok := rhs.(*reflect.Uint16Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint32Value: - _rhs, ok := rhs.(*reflect.Uint32Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Uint64Value: - _rhs, ok := rhs.(*reflect.Uint64Value) - return ok && _lhs.Get() == _rhs.Get() case *reflect.UintValue: _rhs, ok := rhs.(*reflect.UintValue) return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int8Value: - _rhs, ok := rhs.(*reflect.Int8Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int16Value: - _rhs, ok := rhs.(*reflect.Int16Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int32Value: - _rhs, ok := rhs.(*reflect.Int32Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Int64Value: - _rhs, ok := rhs.(*reflect.Int64Value) - return ok && _lhs.Get() == _rhs.Get() case *reflect.IntValue: _rhs, ok := rhs.(*reflect.IntValue) return ok && _lhs.Get() == _rhs.Get() - case *reflect.Float32Value: - _rhs, ok := rhs.(*reflect.Float32Value) - return ok && _lhs.Get() == _rhs.Get() - case *reflect.Float64Value: - _rhs, ok := rhs.(*reflect.Float64Value) + case *reflect.FloatValue: + _rhs, ok := rhs.(*reflect.FloatValue) return ok && _lhs.Get() == _rhs.Get() case reflect.ArrayOrSliceValue: _rhs := rhs.(reflect.ArrayOrSliceValue) diff --git a/go/pack.go b/go/pack.go index 8240394c..d30eef89 100644 --- a/go/pack.go +++ b/go/pack.go @@ -524,19 +524,9 @@ func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { if value.Type() == nil { return PackNil(writer) } switch _value := value.(type) { case *reflect.BoolValue: return PackBool(writer, _value.Get()) - case *reflect.Uint8Value: return PackUint8(writer, _value.Get()) - case *reflect.Uint16Value: return PackUint16(writer, _value.Get()) - case *reflect.Uint32Value: return PackUint32(writer, _value.Get()) - case *reflect.Uint64Value: return PackUint64(writer, _value.Get()) - case *reflect.UintValue: return PackUint(writer, _value.Get()) - case *reflect.Int8Value: return PackInt8(writer, _value.Get()) - case *reflect.Int16Value: return PackInt16(writer, _value.Get()) - case *reflect.Int32Value: return PackInt32(writer, _value.Get()) - case *reflect.Int64Value: return PackInt64(writer, _value.Get()) - case *reflect.IntValue: return PackInt(writer, _value.Get()) - case *reflect.Float32Value: return PackFloat32(writer, _value.Get()) - case *reflect.Float64Value: return PackFloat64(writer, _value.Get()) - case *reflect.FloatValue: return PackFloat(writer, _value.Get()) + case *reflect.UintValue: return PackUint64(writer, _value.Get()) + case *reflect.IntValue: return PackInt64(writer, _value.Get()) + case *reflect.FloatValue: return PackFloat64(writer, _value.Get()) case *reflect.ArrayValue: return PackArray(writer, _value) case *reflect.SliceValue: return PackArray(writer, _value) case *reflect.MapValue: return PackMap(writer, _value) From d4d7495c0acc2de17dbda823d725a0133feea6da Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sat, 26 Jun 2010 20:44:08 +0900 Subject: [PATCH 06/13] Forgot to support map16 / map32 --- go/unpack.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/go/unpack.go b/go/unpack.go index e2e3dc01..38098941 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -197,6 +197,20 @@ func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { retval, n, e = unpackArray(reader, uint(nelemstoread)) nbytesread += n if e != nil { return nil, nbytesread, e } + case 0xde: + nelemstoread, n, e := readUint16(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackMap(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } + case 0xdf: + nelemstoread, n, e := readUint32(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval, n, e = unpackMap(reader, uint(nelemstoread)) + nbytesread += n + if e != nil { return nil, nbytesread, e } } } return retval, nbytesread, nil From 5b544248bc63b8592996f900181b43f8834b65f0 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sat, 26 Jun 2010 22:09:29 +0900 Subject: [PATCH 07/13] Add new API function UnpackReflected() that returns multiple reflect.Value for unpacked elements of arrays or maps. --- go/unpack.go | 78 +++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 7 deletions(-) diff --git a/go/unpack.go b/go/unpack.go index 38098941..3ca48042 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -69,6 +69,19 @@ func unpackArray(reader io.Reader, nelems uint) (v reflect.Value, n int, err os. return reflect.NewValue(retval), nbytesread, nil } +func unpackArrayReflected(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make([]reflect.Value, nelems) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + v, n, e := UnpackReflected(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[i] = v + } + return reflect.NewValue(retval), nbytesread, nil +} + func unpackMap(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { retval := make(map [interface{}] interface{}) nbytesread := 0 @@ -85,7 +98,23 @@ func unpackMap(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Er return reflect.NewValue(retval), nbytesread, nil } -func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { +func unpackMapReflected(reader io.Reader, nelems uint) (v reflect.Value, n int, err os.Error) { + retval := make(map [reflect.Value] reflect.Value) + nbytesread := 0 + var i uint + for i = 0; i < nelems; i++ { + k, n, e := UnpackReflected(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + v, n, e := UnpackReflected(reader) + nbytesread += n + if e != nil { return nil, nbytesread, e } + retval[k] = v + } + return reflect.NewValue(retval), nbytesread, nil +} + +func unpack(reader io.Reader, reflected bool) (v reflect.Value, n int, err os.Error) { var retval reflect.Value var nbytesread int = 0 @@ -95,12 +124,20 @@ func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { if c < 0x80 || c >= 0xe0 { retval = reflect.NewValue(int8(c)) } else if c >= 0x80 && c <= 0x8f { - retval, n, e = unpackMap(reader, uint(c & 0xf)) + if reflected { + retval, n, e = unpackMapReflected(reader, uint(c & 0xf)) + } else { + retval, n, e = unpackMap(reader, uint(c & 0xf)) + } nbytesread += n if e != nil { return nil, nbytesread, e } nbytesread += n } else if c >= 0x90 && c <= 0x9f { - retval, n, e = unpackArray(reader, uint(c & 0xf)) + if reflected { + retval, n, e = unpackArrayReflected(reader, uint(c & 0xf)) + } else { + retval, n, e = unpackArray(reader, uint(c & 0xf)) + } nbytesread += n if e != nil { return nil, nbytesread, e } nbytesread += n @@ -187,31 +224,58 @@ func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { nelemstoread, n, e := readUint16(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackArray(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackArrayReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackArray(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } case 0xdd: nelemstoread, n, e := readUint32(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackArray(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackArrayReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackArray(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } case 0xde: nelemstoread, n, e := readUint16(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackMap(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackMapReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackMap(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } case 0xdf: nelemstoread, n, e := readUint32(reader) nbytesread += n if e != nil { return nil, nbytesread, e } - retval, n, e = unpackMap(reader, uint(nelemstoread)) + if reflected { + retval, n, e = unpackMapReflected(reader, uint(nelemstoread)) + } else { + retval, n, e = unpackMap(reader, uint(nelemstoread)) + } nbytesread += n if e != nil { return nil, nbytesread, e } } } return retval, nbytesread, nil } + +func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { + return unpack(reader, false) +} + +func UnpackReflected(reader io.Reader) (v reflect.Value, n int, err os.Error) { + return unpack(reader, true) +} + + + From 0e82278cd505f8dc0b2c17bd0b43e7d22844f292 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sun, 27 Jun 2010 01:32:37 +0900 Subject: [PATCH 08/13] Fix: InterfaceValue wasnt' correctly unwrapped when passed to PackValue() --- go/pack.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/go/pack.go b/go/pack.go index d30eef89..602f48ac 100644 --- a/go/pack.go +++ b/go/pack.go @@ -521,7 +521,7 @@ func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { } func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { - if value.Type() == nil { return PackNil(writer) } + if value == nil || value.Type() == nil { return PackNil(writer) } switch _value := value.(type) { case *reflect.BoolValue: return PackBool(writer, _value.Get()) case *reflect.UintValue: return PackUint64(writer, _value.Get()) @@ -530,6 +530,12 @@ func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { case *reflect.ArrayValue: return PackArray(writer, _value) case *reflect.SliceValue: return PackArray(writer, _value) case *reflect.MapValue: return PackMap(writer, _value) + case *reflect.InterfaceValue: + __value := reflect.NewValue(_value.Interface()) + _, ok := __value.(*reflect.InterfaceValue) + if !ok { + return PackValue(writer, __value) + } } panic("unsupported type: " + value.Type().String()) } From 003fb3392fc749131f1904e53bf1aeafcbb4ca29 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sun, 27 Jun 2010 01:39:04 +0900 Subject: [PATCH 09/13] Byte arrays in Go should not be serialized as arrays. --- go/pack.go | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/go/pack.go b/go/pack.go index 602f48ac..f23652e3 100644 --- a/go/pack.go +++ b/go/pack.go @@ -452,6 +452,13 @@ func PackFloatArray(writer io.Writer, value []float) (n int, err os.Error) { } func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { + { + elemType, ok := value.Type().(reflect.ArrayOrSliceType).Elem().(*reflect.UintType) + if ok && elemType.Kind() == reflect.Uint8 { + return PackBytes(writer, value.Interface().([]byte)) + } + } + l := value.Len() if l < 16 { n, err := writer.Write([]byte { 0x90 | byte(l) }) From ee16e2eb30df2fd3ae2219fe95ade0941515b490 Mon Sep 17 00:00:00 2001 From: moriyoshi Date: Sun, 27 Jun 2010 03:02:18 +0900 Subject: [PATCH 10/13] Handle unsupported typecode --- go/unpack.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/go/unpack.go b/go/unpack.go index 3ca48042..a3753112 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -4,6 +4,7 @@ import ( "io" "os" "unsafe" + "strconv" "reflect" ) @@ -264,6 +265,8 @@ func unpack(reader io.Reader, reflected bool) (v reflect.Value, n int, err os.Er } nbytesread += n if e != nil { return nil, nbytesread, e } + default: + panic("unsupported code: " + strconv.Itoa(int(c))) } } return retval, nbytesread, nil From 7e31d487e0443658c0af1e80935ad60a1af62aa3 Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Sun, 3 Apr 2011 14:06:08 +0900 Subject: [PATCH 11/13] float type was gone from go language at some time I don't know. --- go/Makefile | 2 +- go/pack.go | 22 ---------------------- 2 files changed, 1 insertion(+), 23 deletions(-) diff --git a/go/Makefile b/go/Makefile index 289bd122..adc243af 100644 --- a/go/Makefile +++ b/go/Makefile @@ -1,4 +1,4 @@ -include $(GOROOT)/src/Make.$(GOARCH) +include $(GOROOT)/src/Make.inc TARG=msgpack diff --git a/go/pack.go b/go/pack.go index f23652e3..aadd7f93 100644 --- a/go/pack.go +++ b/go/pack.go @@ -132,16 +132,6 @@ func PackFloat64(writer io.Writer, value float64) (n int, err os.Error) { return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) } -func PackFloat(writer io.Writer, value float) (n int, err os.Error) { - switch unsafe.Sizeof(value) { - case 4: - return PackFloat32(writer, *(*float32)(unsafe.Pointer(&value))) - case 8: - return PackFloat64(writer, *(*float64)(unsafe.Pointer(&value))) - } - return 0, os.ENOENT // never get here -} - func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { if len(value) < 32 { n1, err := writer.Write([]byte { 0xa0 | uint8(len(value)) }) @@ -441,16 +431,6 @@ func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { return n, nil } -func PackFloatArray(writer io.Writer, value []float) (n int, err os.Error) { - switch unsafe.Sizeof(0) { - case 4: - return PackFloat32Array(writer, *(*[]float32)(unsafe.Pointer(&value))) - case 8: - return PackFloat64Array(writer, *(*[]float64)(unsafe.Pointer(&value))) - } - return 0, os.ENOENT // never get here -} - func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { { elemType, ok := value.Type().(reflect.ArrayOrSliceType).Elem().(*reflect.UintType) @@ -563,7 +543,6 @@ func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { case int: return PackInt(writer, _value) case float32: return PackFloat32(writer, _value) case float64: return PackFloat64(writer, _value) - case float: return PackFloat(writer, _value) case []byte: return PackBytes(writer, _value) case []uint16: return PackUint16Array(writer, _value) case []uint32: return PackUint32Array(writer, _value) @@ -576,7 +555,6 @@ func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { case []int: return PackIntArray(writer, _value) case []float32: return PackFloat32Array(writer, _value) case []float64: return PackFloat64Array(writer, _value) - case []float: return PackFloatArray(writer, _value) default: return PackValue(writer, reflect.NewValue(value)) } From 64fe90aabb69dea61794132d5390fc6659dcfe5c Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Sun, 3 Apr 2011 15:34:37 +0900 Subject: [PATCH 12/13] Add TestUnpackFloat(). --- go/msgpack_test.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/go/msgpack_test.go b/go/msgpack_test.go index e324f2eb..50de668a 100644 --- a/go/msgpack_test.go +++ b/go/msgpack_test.go @@ -5,6 +5,7 @@ import ( "testing" "bytes" "reflect" + "math" ); func equal(lhs reflect.Value, rhs reflect.Value) bool { @@ -196,3 +197,22 @@ func TestUnpackInt(t *testing.T) { if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } } } + +func TestUnpackFloat(t *testing.T) { + b := bytes.NewBuffer([]byte { 0xca, 0x3d, 0xcc, 0xcc, 0xcd, 0xca, 0x3e, 0x4c, 0xcc, 0xcd, 0xca, 0xbd, 0xcc, 0xcc, 0xcd, 0xca, 0xbe, 0x4c, 0xcc, 0xcd, 0xca, 0x7f, 0x80, 0x00, 0x00, 0xca, 0xff, 0x80, 0x00, 0x00, 0xca, 0xff, 0xc0, 0x00, 0x0, 0xcb, 0x3f, 0xb9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0x3f, 0xc9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0xbf, 0xb9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0xbf, 0xc9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x9a, 0xcb, 0x7f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xcb, 0xff, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcb, 0x7f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }) + for _, v := range [](interface{}) { float32(.1), float32(.2), float32(-.1), float32(-.2), float32(math.Inf(1)), float32(math.Inf(-1)), float32(math.NaN()), float64(.1), float64(.2), float64(-.1), float64(-.2) } { + retval, _, e := Unpack(b) + if e != nil { t.Error("err != nil") } + isnan := false + if _v, ok := v.(float64); ok { + isnan = math.IsNaN(_v) + } else if _v, ok := v.(float32); ok { + isnan = math.IsNaN(float64(_v)) + } + if isnan { + if retval.Interface() == v { t.Errorf("[NaN] %u == %u", retval.Interface(), v) } + } else { + if retval.Interface() != v { t.Errorf("%u != %u", retval.Interface(), v) } + } + } +} From d354f2e8c2275a443b2906396ff9f43ade6ecb23 Mon Sep 17 00:00:00 2001 From: Moriyoshi Koizumi Date: Sun, 3 Apr 2011 19:09:14 +0900 Subject: [PATCH 13/13] Documentation. --- go/pack.go | 31 ++++++++++++++++++++++++++++++- go/unpack.go | 4 ++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/go/pack.go b/go/pack.go index aadd7f93..c129166e 100644 --- a/go/pack.go +++ b/go/pack.go @@ -7,6 +7,7 @@ import ( "reflect" ); +// Packs a given value and writes it into the specified writer. func PackUint8(writer io.Writer, value uint8) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -14,6 +15,7 @@ func PackUint8(writer io.Writer, value uint8) (n int, err os.Error) { return writer.Write([]byte { 0xcc, byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackUint16(writer io.Writer, value uint16) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -23,6 +25,7 @@ func PackUint16(writer io.Writer, value uint16) (n int, err os.Error) { return writer.Write([]byte { 0xcd, byte(value >> 8), byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackUint32(writer io.Writer, value uint32) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -34,6 +37,7 @@ func PackUint32(writer io.Writer, value uint32) (n int, err os.Error) { return writer.Write([]byte { 0xce, byte(value >> 24), byte(value >> 16), byte(value >> 8), byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackUint64(writer io.Writer, value uint64) (n int, err os.Error) { if value < 128 { return writer.Write([]byte { byte(value) }) @@ -48,6 +52,7 @@ func PackUint64(writer io.Writer, value uint64) (n int, err os.Error) { } func PackUint(writer io.Writer, value uint) (n int, err os.Error) { +// Packs a given value and writes it into the specified writer. switch unsafe.Sizeof(value) { case 4: return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) @@ -57,7 +62,7 @@ func PackUint(writer io.Writer, value uint) (n int, err os.Error) { return 0, os.ENOENT // never get here } - +// Packs a given value and writes it into the specified writer. func PackInt8(writer io.Writer, value int8) (n int, err os.Error) { if value < -32 { return writer.Write([]byte { 0xd0, byte(value) }) @@ -65,6 +70,7 @@ func PackInt8(writer io.Writer, value int8) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt16(writer io.Writer, value int16) (n int, err os.Error) { if value < -128 || value >= 128 { return writer.Write([]byte { 0xd1, byte(uint16(value) >> 8), byte(value) }) @@ -74,6 +80,7 @@ func PackInt16(writer io.Writer, value int16) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt32(writer io.Writer, value int32) (n int, err os.Error) { if value < -32768 || value >= 32768 { return writer.Write([]byte { 0xd2, byte(uint32(value) >> 24), byte(uint32(value) >> 16), byte(uint32(value) >> 8), byte(value) }) @@ -87,6 +94,7 @@ func PackInt32(writer io.Writer, value int32) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt64(writer io.Writer, value int64) (n int, err os.Error) { if value < -2147483648 || value >= 2147483648 { return writer.Write([]byte { 0xd3, byte(uint64(value) >> 56), byte(uint64(value) >> 48), byte(uint64(value) >> 40), byte(uint64(value) >> 32), byte(uint64(value) >> 24), byte(uint64(value) >> 16), byte(uint64(value) >> 8), byte(value) }) @@ -100,6 +108,7 @@ func PackInt64(writer io.Writer, value int64) (n int, err os.Error) { return writer.Write([]byte { byte(value) }) } +// Packs a given value and writes it into the specified writer. func PackInt(writer io.Writer, value int) (n int, err os.Error) { switch unsafe.Sizeof(value) { case 4: @@ -110,10 +119,12 @@ func PackInt(writer io.Writer, value int) (n int, err os.Error) { return 0, os.ENOENT // never get here } +// Packs a given value and writes it into the specified writer. func PackNil(writer io.Writer) (n int, err os.Error) { return writer.Write([]byte{ 0xc0 }) } +// Packs a given value and writes it into the specified writer. func PackBool(writer io.Writer, value bool) (n int, err os.Error) { var code byte; if value { @@ -124,14 +135,17 @@ func PackBool(writer io.Writer, value bool) (n int, err os.Error) { return writer.Write([]byte{ code }) } +// Packs a given value and writes it into the specified writer. func PackFloat32(writer io.Writer, value float32) (n int, err os.Error) { return PackUint32(writer, *(*uint32)(unsafe.Pointer(&value))) } +// Packs a given value and writes it into the specified writer. func PackFloat64(writer io.Writer, value float64) (n int, err os.Error) { return PackUint64(writer, *(*uint64)(unsafe.Pointer(&value))) } +// Packs a given value and writes it into the specified writer. func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { if len(value) < 32 { n1, err := writer.Write([]byte { 0xa0 | uint8(len(value)) }) @@ -150,6 +164,7 @@ func PackBytes(writer io.Writer, value []byte) (n int, err os.Error) { return n1 + n2, err } +// Packs a given value and writes it into the specified writer. func PackUint16Array(writer io.Writer, value []uint16) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -179,6 +194,7 @@ func PackUint16Array(writer io.Writer, value []uint16) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackUint32Array(writer io.Writer, value []uint32) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -208,6 +224,7 @@ func PackUint32Array(writer io.Writer, value []uint32) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackUint64Array(writer io.Writer, value []uint64) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -237,6 +254,7 @@ func PackUint64Array(writer io.Writer, value []uint64) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackUintArray(writer io.Writer, value []uint) (n int, err os.Error) { switch unsafe.Sizeof(0) { case 4: @@ -247,6 +265,7 @@ func PackUintArray(writer io.Writer, value []uint) (n int, err os.Error) { return 0, os.ENOENT // never get here } +// Packs a given value and writes it into the specified writer. func PackInt8Array(writer io.Writer, value []int8) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -276,6 +295,7 @@ func PackInt8Array(writer io.Writer, value []int8) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackInt16Array(writer io.Writer, value []int16) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -305,6 +325,7 @@ func PackInt16Array(writer io.Writer, value []int16) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackInt32Array(writer io.Writer, value []int32) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -334,6 +355,7 @@ func PackInt32Array(writer io.Writer, value []int32) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackInt64Array(writer io.Writer, value []int64) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -363,6 +385,7 @@ func PackInt64Array(writer io.Writer, value []int64) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackIntArray(writer io.Writer, value []int) (n int, err os.Error) { switch unsafe.Sizeof(0) { case 4: @@ -373,6 +396,7 @@ func PackIntArray(writer io.Writer, value []int) (n int, err os.Error) { return 0, os.ENOENT // never get here } +// Packs a given value and writes it into the specified writer. func PackFloat32Array(writer io.Writer, value []float32) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -402,6 +426,7 @@ func PackFloat32Array(writer io.Writer, value []float32) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { if len(value) < 16 { n, err := writer.Write([]byte { 0x90 | byte(len(value)) }) @@ -431,6 +456,7 @@ func PackFloat64Array(writer io.Writer, value []float64) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os.Error) { { elemType, ok := value.Type().(reflect.ArrayOrSliceType).Elem().(*reflect.UintType) @@ -468,6 +494,7 @@ func PackArray(writer io.Writer, value reflect.ArrayOrSliceValue) (n int, err os return n, nil } +// Packs a given value and writes it into the specified writer. func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { keys := value.Keys() if value.Len() < 16 { @@ -507,6 +534,7 @@ func PackMap(writer io.Writer, value *reflect.MapValue) (n int, err os.Error) { return n, nil } +// Packs a given value and writes it into the specified writer. func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { if value == nil || value.Type() == nil { return PackNil(writer) } switch _value := value.(type) { @@ -527,6 +555,7 @@ func PackValue(writer io.Writer, value reflect.Value) (n int, err os.Error) { panic("unsupported type: " + value.Type().String()) } +// Packs a given value and writes it into the specified writer. func Pack(writer io.Writer, value interface{}) (n int, err os.Error) { if value == nil { return PackNil(writer) } switch _value := value.(type) { diff --git a/go/unpack.go b/go/unpack.go index a3753112..6bf0159d 100644 --- a/go/unpack.go +++ b/go/unpack.go @@ -272,10 +272,14 @@ func unpack(reader io.Reader, reflected bool) (v reflect.Value, n int, err os.Er return retval, nbytesread, nil } +// Reads a value from the reader, unpack and returns it. func Unpack(reader io.Reader) (v reflect.Value, n int, err os.Error) { return unpack(reader, false) } +// Reads unpack a value from the reader, unpack and returns it. When the +// value is an array or map, leaves the elements wrapped by corresponding +// wrapper objects defined in reflect package. func UnpackReflected(reader io.Reader) (v reflect.Value, n int, err os.Error) { return unpack(reader, true) }