浏览代码

Implemented tentative marshalling for decimal numbers

Ben Hood 11 年之前
父节点
当前提交
a4591a1064
共有 2 个文件被更改,包括 43 次插入0 次删除
  1. 37 0
      marshal.go
  2. 6 0
      marshal_test.go

+ 37 - 0
marshal.go

@@ -8,6 +8,7 @@ import (
 	"bytes"
 	"fmt"
 	"math"
+	"math/big"
 	"reflect"
 	"time"
 )
@@ -43,6 +44,8 @@ func Marshal(info *TypeInfo, value interface{}) ([]byte, error) {
 		return marshalFloat(info, value)
 	case TypeDouble:
 		return marshalDouble(info, value)
+	case TypeDecimal:
+		return marshalDecimal(info, value)
 	case TypeTimestamp:
 		return marshalTimestamp(info, value)
 	case TypeList, TypeSet:
@@ -76,6 +79,8 @@ func Unmarshal(info *TypeInfo, data []byte, value interface{}) error {
 		return unmarshalFloat(info, data, value)
 	case TypeDouble:
 		return unmarshalDouble(info, data, value)
+	case TypeDecimal:
+		return unmarshalDecimal(info, data, value)
 	case TypeTimestamp:
 		return unmarshalTimestamp(info, data, value)
 	case TypeList, TypeSet:
@@ -675,6 +680,38 @@ func unmarshalDouble(info *TypeInfo, data []byte, value interface{}) error {
 	return unmarshalErrorf("can not unmarshal %s into %T", info, value)
 }
 
+func marshalDecimal(info *TypeInfo, value interface{}) ([]byte, error) {
+	switch v := value.(type) {
+	case Marshaler:
+		return v.MarshalCQL(info)
+	case *big.Rat:
+
+		if v == nil {
+			return nil, nil
+		}
+		num := v.Num().Bytes()
+		denom := v.Denom().Bytes()
+		buf := make([]byte, 4+len(num))
+		copy(buf[4-len(denom):4], denom)
+		copy(buf[4:], num)
+		return buf, nil
+	}
+	return nil, marshalErrorf("can not marshal %T into %s", value, info)
+}
+
+func unmarshalDecimal(info *TypeInfo, data []byte, value interface{}) error {
+	switch v := value.(type) {
+	case Unmarshaler:
+		return v.UnmarshalCQL(info, data)
+	case **big.Rat:
+		denom := new(big.Int).SetBytes(data[0:4])
+		num := new(big.Int).SetBytes(data[4:])
+		*v = new(big.Rat).SetFrac(num, denom)
+		return nil
+	}
+	return unmarshalErrorf("can not unmarshal %s into %T", info, value)
+}
+
 func marshalTimestamp(info *TypeInfo, value interface{}) ([]byte, error) {
 	switch v := value.(type) {
 	case Marshaler:

+ 6 - 0
marshal_test.go

@@ -3,6 +3,7 @@ package gocql
 import (
 	"bytes"
 	"math"
+	"math/big"
 	"reflect"
 	"strings"
 	"testing"
@@ -117,6 +118,11 @@ var marshalTests = []struct {
 		[]byte("\x40\x09\x21\xfb\x53\xc8\xd4\xf1"),
 		float64(3.14159265),
 	},
+	{
+		&TypeInfo{Type: TypeDecimal},
+		[]byte("\x00\x01\x86\xa0\xcb\xd7\x12\xbb\x6d"),
+		big.NewRat(875486690157, 100000),
+	},
 	{
 		&TypeInfo{Type: TypeTimestamp},
 		[]byte("\x00\x00\x01\x40\x77\x16\xe1\xb8"),