diff --git a/marshal.go b/marshal.go index 05ce84d37..7599003c4 100644 --- a/marshal.go +++ b/marshal.go @@ -20,6 +20,7 @@ import ( "gopkg.in/inf.v0" + "github.com/gocql/gocql/marshal/bigint" "github.com/gocql/gocql/marshal/cqlint" "github.com/gocql/gocql/marshal/smallint" "github.com/gocql/gocql/marshal/tinyint" @@ -143,8 +144,10 @@ func Marshal(info TypeInfo, value interface{}) ([]byte, error) { return marshalSmallInt(value) case TypeInt: return marshalInt(value) - case TypeBigInt, TypeCounter: - return marshalBigInt(info, value) + case TypeBigInt: + return marshalBigInt(value) + case TypeCounter: + return marshalBigIntOld(info, value) case TypeFloat: return marshalFloat(info, value) case TypeDouble: @@ -241,8 +244,10 @@ func Unmarshal(info TypeInfo, data []byte, value interface{}) error { return unmarshalBool(info, data, value) case TypeInt: return unmarshalInt(data, value) - case TypeBigInt, TypeCounter: - return unmarshalBigInt(info, data, value) + case TypeBigInt: + return unmarshalBigInt(data, value) + case TypeCounter: + return unmarshalCounter(info, data, value) case TypeVarint: return unmarshalVarint(info, data, value) case TypeSmallInt: @@ -418,7 +423,16 @@ func decInt(x []byte) int32 { return int32(x[0])<<24 | int32(x[1])<<16 | int32(x[2])<<8 | int32(x[3]) } -func marshalBigInt(info TypeInfo, value interface{}) ([]byte, error) { +func marshalBigInt(value interface{}) ([]byte, error) { + data, err := bigint.Marshal(value) + if err != nil { + return nil, wrapMarshalError(err, "marshal error") + } + return data, nil + +} + +func marshalBigIntOld(info TypeInfo, value interface{}) ([]byte, error) { switch v := value.(type) { case Marshaler: return v.MarshalCQL(info) @@ -495,7 +509,7 @@ func bytesToUint64(data []byte) (ret uint64) { return ret } -func unmarshalBigInt(info TypeInfo, data []byte, value interface{}) error { +func unmarshalCounter(info TypeInfo, data []byte, value interface{}) error { return unmarshalIntlike(info, decBigInt(data), data, value) } @@ -507,6 +521,14 @@ func unmarshalInt(data []byte, value interface{}) error { return nil } +func unmarshalBigInt(data []byte, value interface{}) error { + err := bigint.Unmarshal(data, value) + if err != nil { + return wrapUnmarshalError(err, "unmarshal error") + } + return nil +} + func unmarshalSmallInt(data []byte, value interface{}) error { err := smallint.Unmarshal(data, value) if err != nil { @@ -562,7 +584,7 @@ func marshalVarint(info TypeInfo, value interface{}) ([]byte, error) { binary.BigEndian.PutUint64(retBytes, v) } default: - retBytes, err = marshalBigInt(info, value) + retBytes, err = marshalBigIntOld(info, value) } if err == nil { diff --git a/marshal/bigint/marshal.go b/marshal/bigint/marshal.go new file mode 100644 index 000000000..8a92295d1 --- /dev/null +++ b/marshal/bigint/marshal.go @@ -0,0 +1,74 @@ +package bigint + +import ( + "math/big" + "reflect" +) + +func Marshal(value interface{}) ([]byte, error) { + switch v := value.(type) { + case nil: + return nil, nil + case int8: + return EncInt8(v) + case int16: + return EncInt16(v) + case int32: + return EncInt32(v) + case int64: + return EncInt64(v) + case int: + return EncInt(v) + + case uint8: + return EncUint8(v) + case uint16: + return EncUint16(v) + case uint32: + return EncUint32(v) + case uint64: + return EncUint64(v) + case uint: + return EncUint(v) + + case big.Int: + return EncBigInt(v) + case string: + return EncString(v) + + case *int8: + return EncInt8R(v) + case *int16: + return EncInt16R(v) + case *int32: + return EncInt32R(v) + case *int64: + return EncInt64R(v) + case *int: + return EncIntR(v) + + case *uint8: + return EncUint8R(v) + case *uint16: + return EncUint16R(v) + case *uint32: + return EncUint32R(v) + case *uint64: + return EncUint64R(v) + case *uint: + return EncUintR(v) + + case *big.Int: + return EncBigIntR(v) + case *string: + return EncStringR(v) + default: + // Custom types (type MyInt int) can be serialized only via `reflect` package. + // Later, when generic-based serialization is introduced we can do that via generics. + rv := reflect.TypeOf(value) + if rv.Kind() != reflect.Ptr { + return EncReflect(reflect.ValueOf(v)) + } + return EncReflectR(reflect.ValueOf(v)) + } +} diff --git a/marshal/bigint/marshal_utils.go b/marshal/bigint/marshal_utils.go new file mode 100644 index 000000000..0683cb78d --- /dev/null +++ b/marshal/bigint/marshal_utils.go @@ -0,0 +1,201 @@ +package bigint + +import ( + "fmt" + "math" + "math/big" + "reflect" + "strconv" +) + +var ( + maxBigInt = big.NewInt(math.MaxInt64) + minBigInt = big.NewInt(math.MinInt64) +) + +func EncInt8(v int8) ([]byte, error) { + if v < 0 { + return []byte{255, 255, 255, 255, 255, 255, 255, byte(v)}, nil + } + return []byte{0, 0, 0, 0, 0, 0, 0, byte(v)}, nil +} + +func EncInt8R(v *int8) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncInt8(*v) +} + +func EncInt16(v int16) ([]byte, error) { + if v < 0 { + return []byte{255, 255, 255, 255, 255, 255, byte(v >> 8), byte(v)}, nil + } + return []byte{0, 0, 0, 0, 0, 0, byte(v >> 8), byte(v)}, nil +} + +func EncInt16R(v *int16) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncInt16(*v) +} + +func EncInt32(v int32) ([]byte, error) { + if v < 0 { + return []byte{255, 255, 255, 255, byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}, nil + } + return []byte{0, 0, 0, 0, byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}, nil +} + +func EncInt32R(v *int32) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncInt32(*v) +} + +func EncInt64(v int64) ([]byte, error) { + return encInt64(v), nil +} + +func EncInt64R(v *int64) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncInt64(*v) +} + +func EncInt(v int) ([]byte, error) { + return []byte{byte(v >> 56), byte(v >> 48), byte(v >> 40), byte(v >> 32), byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}, nil +} + +func EncIntR(v *int) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncInt(*v) +} + +func EncUint8(v uint8) ([]byte, error) { + return []byte{0, 0, 0, 0, 0, 0, 0, v}, nil +} + +func EncUint8R(v *uint8) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint8(*v) +} + +func EncUint16(v uint16) ([]byte, error) { + return []byte{0, 0, 0, 0, 0, 0, byte(v >> 8), byte(v)}, nil +} + +func EncUint16R(v *uint16) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint16(*v) +} + +func EncUint32(v uint32) ([]byte, error) { + return []byte{0, 0, 0, 0, byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}, nil +} + +func EncUint32R(v *uint32) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint32(*v) +} + +func EncUint64(v uint64) ([]byte, error) { + return []byte{byte(v >> 56), byte(v >> 48), byte(v >> 40), byte(v >> 32), byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}, nil +} + +func EncUint64R(v *uint64) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint64(*v) +} + +func EncUint(v uint) ([]byte, error) { + return []byte{byte(v >> 56), byte(v >> 48), byte(v >> 40), byte(v >> 32), byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)}, nil +} + +func EncUintR(v *uint) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint(*v) +} + +func EncBigInt(v big.Int) ([]byte, error) { + if v.Cmp(maxBigInt) == 1 || v.Cmp(minBigInt) == -1 { + return nil, fmt.Errorf("failed to marshal bigint: value (%T)(%s) out of range", v, v.String()) + } + return encInt64(v.Int64()), nil +} + +func EncBigIntR(v *big.Int) ([]byte, error) { + if v == nil { + return nil, nil + } + if v.Cmp(maxBigInt) == 1 || v.Cmp(minBigInt) == -1 { + return nil, fmt.Errorf("failed to marshal bigint: value (%T)(%s) out of range", v, v.String()) + } + return encInt64(v.Int64()), nil +} + +func EncString(v string) ([]byte, error) { + if v == "" { + return nil, nil + } + + n, err := strconv.ParseInt(v, 10, 64) + if err != nil { + return nil, fmt.Errorf("failed to marshal bigint: can not marshal %#v %s", v, err) + } + return encInt64(n), nil +} + +func EncStringR(v *string) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncString(*v) +} + +func EncReflect(v reflect.Value) ([]byte, error) { + switch v.Kind() { + case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8: + return EncInt64(v.Int()) + case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8: + return EncUint64(v.Uint()) + case reflect.String: + val := v.String() + if val == "" { + return nil, nil + } + n, err := strconv.ParseInt(val, 10, 64) + if err != nil { + return nil, fmt.Errorf("failed to marshal bigint: can not marshal %#v %s", v.Interface(), err) + } + return encInt64(n), nil + default: + return nil, fmt.Errorf("failed to marshal bigint: unsupported value type (%T)(%#[1]v)", v.Interface()) + } +} + +func EncReflectR(v reflect.Value) ([]byte, error) { + if v.IsNil() { + return nil, nil + } + return EncReflect(v.Elem()) +} + +func encInt64(v int64) []byte { + return []byte{byte(v >> 56), byte(v >> 48), byte(v >> 40), byte(v >> 32), byte(v >> 24), byte(v >> 16), byte(v >> 8), byte(v)} +} diff --git a/marshal/bigint/unmarshal.go b/marshal/bigint/unmarshal.go new file mode 100644 index 000000000..38ad81d00 --- /dev/null +++ b/marshal/bigint/unmarshal.go @@ -0,0 +1,81 @@ +package bigint + +import ( + "fmt" + "math/big" + "reflect" +) + +func Unmarshal(data []byte, value interface{}) error { + switch v := value.(type) { + case nil: + return nil + + case *int8: + return DecInt8(data, v) + case *int16: + return DecInt16(data, v) + case *int32: + return DecInt32(data, v) + case *int64: + return DecInt64(data, v) + case *int: + return DecInt(data, v) + + case *uint8: + return DecUint8(data, v) + case *uint16: + return DecUint16(data, v) + case *uint32: + return DecUint32(data, v) + case *uint64: + return DecUint64(data, v) + case *uint: + return DecUint(data, v) + + case *big.Int: + return DecBigInt(data, v) + case *string: + return DecString(data, v) + + case **int8: + return DecInt8R(data, v) + case **int16: + return DecInt16R(data, v) + case **int32: + return DecInt32R(data, v) + case **int64: + return DecInt64R(data, v) + case **int: + return DecIntR(data, v) + + case **uint8: + return DecUint8R(data, v) + case **uint16: + return DecUint16R(data, v) + case **uint32: + return DecUint32R(data, v) + case **uint64: + return DecUint64R(data, v) + case **uint: + return DecUintR(data, v) + + case **big.Int: + return DecBigIntR(data, v) + case **string: + return DecStringR(data, v) + default: + + // Custom types (type MyInt int) can be deserialized only via `reflect` package. + // Later, when generic-based serialization is introduced we can do that via generics. + rv := reflect.ValueOf(value) + rt := rv.Type() + if rt.Kind() != reflect.Ptr { + return fmt.Errorf("failed to unmarshal bigint: unsupported value type (%T)(%#[1]v)", value) + } + if rt.Elem().Kind() != reflect.Ptr { + return DecReflect(data, rv) + } + return DecReflectR(data, rv) + } +} diff --git a/marshal/bigint/unmarshal_utils.go b/marshal/bigint/unmarshal_utils.go new file mode 100644 index 000000000..0906cd144 --- /dev/null +++ b/marshal/bigint/unmarshal_utils.go @@ -0,0 +1,765 @@ +package bigint + +import ( + "fmt" + "math" + "math/big" + "reflect" + "strconv" +) + +var errWrongDataLen = fmt.Errorf("failed to unmarshal bigint: the length of the data should be 0 or 8") + +func DecInt8(p []byte, v *int8) error { + switch len(p) { + case 0: + *v = 0 + case 8: + val := decInt64(p) + if val > math.MaxInt8 || val < math.MinInt8 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into int8, the data should be in the int8 range") + } + *v = int8(val) + default: + return errWrongDataLen + } + return nil +} + +func DecInt8R(p []byte, v **int8) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(int8) + } + case 8: + val := decInt64(p) + if val > math.MaxInt8 || val < math.MinInt8 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into int8, the data should be in the int8 range") + } + tmp := int8(val) + *v = &tmp + default: + return errWrongDataLen + } + return nil +} + +func DecInt16(p []byte, v *int16) error { + switch len(p) { + case 0: + *v = 0 + case 8: + val := decInt64(p) + if val > math.MaxInt16 || val < math.MinInt16 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into int16, the data should be in the int16 range") + } + *v = int16(val) + default: + return errWrongDataLen + } + return nil +} + +func DecInt16R(p []byte, v **int16) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(int16) + } + case 8: + val := decInt64(p) + if val > math.MaxInt16 || val < math.MinInt16 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into int16, the data should be in the int16 range") + } + tmp := int16(val) + *v = &tmp + default: + return errWrongDataLen + } + return nil +} + +func DecInt32(p []byte, v *int32) error { + switch len(p) { + case 0: + *v = 0 + case 8: + val := decInt64(p) + if val > math.MaxInt32 || val < math.MinInt32 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into int32, the data should be in the int32 range") + } + *v = int32(val) + default: + return errWrongDataLen + } + return nil +} + +func DecInt32R(p []byte, v **int32) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(int32) + } + case 8: + val := decInt64(p) + if val > math.MaxInt32 || val < math.MinInt32 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into int32, the data should be in the int32 range") + } + tmp := int32(val) + *v = &tmp + default: + return errWrongDataLen + } + return nil +} + +func DecInt64(p []byte, v *int64) error { + switch len(p) { + case 0: + *v = 0 + case 8: + *v = decInt64(p) + default: + return errWrongDataLen + } + return nil +} + +func DecInt64R(p []byte, v **int64) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(int64) + } + case 8: + val := decInt64(p) + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecInt(p []byte, v *int) error { + switch len(p) { + case 0: + *v = 0 + case 8: + *v = int(p[0])<<56 | int(p[1])<<48 | int(p[2])<<40 | int(p[3])<<32 | int(p[4])<<24 | int(p[5])<<16 | int(p[6])<<8 | int(p[7]) + default: + return errWrongDataLen + } + return nil +} + +func DecIntR(p []byte, v **int) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(int) + } + case 8: + val := int(p[0])<<56 | int(p[1])<<48 | int(p[2])<<40 | int(p[3])<<32 | int(p[4])<<24 | int(p[5])<<16 | int(p[6])<<8 | int(p[7]) + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecUint8(p []byte, v *uint8) error { + switch len(p) { + case 0: + *v = 0 + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 || p[6] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into uint8, the data should be in the uint8 range") + } + *v = p[7] + default: + return errWrongDataLen + } + return nil +} + +func DecUint8R(p []byte, v **uint8) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(uint8) + } + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 || p[6] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into uint8, the data should be in the uint8 range") + } + val := p[7] + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecUint16(p []byte, v *uint16) error { + switch len(p) { + case 0: + *v = 0 + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into uint16, the data should be in the uint16 range") + } + *v = uint16(p[6])<<8 | uint16(p[7]) + default: + return errWrongDataLen + } + return nil +} + +func DecUint16R(p []byte, v **uint16) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(uint16) + } + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into uint16, the data should be in the uint16 range") + } + val := uint16(p[6])<<8 | uint16(p[7]) + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecUint32(p []byte, v *uint32) error { + switch len(p) { + case 0: + *v = 0 + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into uint32, the data should be in the uint32 range") + } + *v = uint32(p[4])<<24 | uint32(p[5])<<16 | uint32(p[6])<<8 | uint32(p[7]) + default: + return errWrongDataLen + } + return nil +} + +func DecUint32R(p []byte, v **uint32) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(uint32) + } + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into uint32, the data should be in the uint32 range") + } + val := uint32(p[4])<<24 | uint32(p[5])<<16 | uint32(p[6])<<8 | uint32(p[7]) + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecUint64(p []byte, v *uint64) error { + switch len(p) { + case 0: + *v = 0 + case 8: + *v = decUint64(p) + default: + return errWrongDataLen + } + return nil +} + +func DecUint64R(p []byte, v **uint64) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(uint64) + } + case 8: + val := decUint64(p) + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecUint(p []byte, v *uint) error { + switch len(p) { + case 0: + *v = 0 + case 8: + *v = uint(p[0])<<56 | uint(p[1])<<48 | uint(p[2])<<40 | uint(p[3])<<32 | uint(p[4])<<24 | uint(p[5])<<16 | uint(p[6])<<8 | uint(p[7]) + default: + return errWrongDataLen + } + return nil +} + +func DecUintR(p []byte, v **uint) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(uint) + } + case 8: + val := uint(p[0])<<56 | uint(p[1])<<48 | uint(p[2])<<40 | uint(p[3])<<32 | uint(p[4])<<24 | uint(p[5])<<16 | uint(p[6])<<8 | uint(p[7]) + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecString(p []byte, v *string) error { + switch len(p) { + case 0: + if p == nil { + *v = "" + } else { + *v = "0" + } + case 8: + *v = strconv.FormatInt(decInt64(p), 10) + default: + return errWrongDataLen + } + return nil +} + +func DecStringR(p []byte, v **string) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + val := "0" + *v = &val + } + case 8: + val := strconv.FormatInt(decInt64(p), 10) + *v = &val + default: + return errWrongDataLen + } + return nil +} + +func DecBigInt(p []byte, v *big.Int) error { + switch len(p) { + case 0: + v.SetInt64(0) + case 8: + v.SetInt64(decInt64(p)) + default: + return errWrongDataLen + } + return nil +} + +func DecBigIntR(p []byte, v **big.Int) error { + switch len(p) { + case 0: + if p == nil { + *v = nil + } else { + *v = new(big.Int) + } + case 8: + *v = big.NewInt(decInt64(p)) + default: + return errWrongDataLen + } + return nil +} + +func DecReflect(p []byte, v reflect.Value) error { + if v.IsNil() { + return fmt.Errorf("failed to unmarshal bigint: can not unmarshal into nil reference (%T)(%#[1]v)", v.Interface()) + } + + switch v = v.Elem(); v.Kind() { + case reflect.Int8: + return decReflectInt8(p, v) + case reflect.Int16: + return decReflectInt16(p, v) + case reflect.Int32: + return decReflectInt32(p, v) + case reflect.Int64, reflect.Int: + return decReflectInts(p, v) + case reflect.Uint8: + return decReflectUint8(p, v) + case reflect.Uint16: + return decReflectUint16(p, v) + case reflect.Uint32: + return decReflectUint32(p, v) + case reflect.Uint64, reflect.Uint: + return decReflectUints(p, v) + case reflect.String: + return decReflectString(p, v) + default: + return fmt.Errorf("failed to unmarshal bigint: unsupported value type (%T)(%#[1]v)", v.Interface()) + } +} + +func decReflectInt8(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetInt(0) + case 8: + val := decInt64(p) + if val > math.MaxInt8 || val < math.MinInt8 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom int8, the data should be in the int8 range") + } + v.SetInt(val) + default: + return errWrongDataLen + } + return nil +} + +func decReflectInt16(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetInt(0) + case 8: + val := decInt64(p) + if val > math.MaxInt16 || val < math.MinInt16 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom int16, the data should be in the int16 range") + } + v.SetInt(val) + default: + return errWrongDataLen + } + return nil +} + +func decReflectInt32(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetInt(0) + case 8: + val := decInt64(p) + if val > math.MaxInt32 || val < math.MinInt32 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom int32, the data should be in the int32 range") + } + v.SetInt(val) + default: + return errWrongDataLen + } + return nil +} + +func decReflectInts(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetInt(0) + case 8: + v.SetInt(decInt64(p)) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUint8(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetUint(0) + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 || p[6] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom uint8, the data should be in the uint8 range") + } + v.SetUint(uint64(p[7])) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUint16(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetUint(0) + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom uint16, the data should be in the uint16 range") + } + v.SetUint(uint64(p[6])<<8 | uint64(p[7])) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUint32(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetUint(0) + case 8: + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom uint32, the data should be in the uint32 range") + } + v.SetUint(uint64(p[4])<<24 | uint64(p[5])<<16 | uint64(p[6])<<8 | uint64(p[7])) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUints(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetUint(0) + case 8: + v.SetUint(decUint64(p)) + default: + return errWrongDataLen + } + return nil +} + +func decReflectString(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + if p == nil { + v.SetString("") + } else { + v.SetString("0") + } + case 8: + v.SetString(strconv.FormatInt(decInt64(p), 10)) + default: + return errWrongDataLen + } + return nil +} + +func DecReflectR(p []byte, v reflect.Value) error { + if v.IsNil() { + return fmt.Errorf("failed to unmarshal bigint: can not unmarshal into nil reference (%T)(%#[1]v)", v.Interface()) + } + + switch v.Type().Elem().Elem().Kind() { + case reflect.Int8: + return decReflectInt8R(p, v) + case reflect.Int16: + return decReflectInt16R(p, v) + case reflect.Int32: + return decReflectInt32R(p, v) + case reflect.Int64, reflect.Int: + return decReflectIntsR(p, v) + case reflect.Uint8: + return decReflectUint8R(p, v) + case reflect.Uint16: + return decReflectUint16R(p, v) + case reflect.Uint32: + return decReflectUint32R(p, v) + case reflect.Uint64, reflect.Uint: + return decReflectUintsR(p, v) + case reflect.String: + return decReflectStringR(p, v) + default: + return fmt.Errorf("failed to unmarshal bigint: unsupported value type (%T)(%#[1]v)", v.Interface()) + } +} + +func decReflectInt8R(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + val := decInt64(p) + if val > math.MaxInt8 || val < math.MinInt8 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom int8, the data should be in the int8 range") + } + newVal := reflect.New(v.Type().Elem().Elem()) + newVal.Elem().SetInt(val) + v.Elem().Set(newVal) + default: + return errWrongDataLen + } + return nil +} + +func decReflectInt16R(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + val := decInt64(p) + if val > math.MaxInt16 || val < math.MinInt16 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom int16, the data should be in the int16 range") + } + newVal := reflect.New(v.Type().Elem().Elem()) + newVal.Elem().SetInt(val) + v.Elem().Set(newVal) + default: + return errWrongDataLen + } + return nil +} + +func decReflectInt32R(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + val := decInt64(p) + if val > math.MaxInt32 || val < math.MinInt32 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom int32, the data should be in the int32 range") + } + newVal := reflect.New(v.Type().Elem().Elem()) + newVal.Elem().SetInt(val) + v.Elem().Set(newVal) + default: + return errWrongDataLen + } + return nil +} + +func decReflectIntsR(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + val := reflect.New(v.Type().Elem().Elem()) + val.Elem().SetInt(decInt64(p)) + v.Elem().Set(val) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUint8R(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + newVal := reflect.New(v.Type().Elem().Elem()) + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 || p[6] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom uint8, the data should be in the uint8 range") + } + newVal.Elem().SetUint(uint64(p[7])) + v.Elem().Set(newVal) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUint16R(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + newVal := reflect.New(v.Type().Elem().Elem()) + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 || p[4] != 0 || p[5] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom uint16, the data should be in the uint16 range") + } + newVal.Elem().SetUint(uint64(p[6])<<8 | uint64(p[7])) + v.Elem().Set(newVal) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUint32R(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + newVal := reflect.New(v.Type().Elem().Elem()) + if p[0] != 0 || p[1] != 0 || p[2] != 0 || p[3] != 0 { + return fmt.Errorf("failed to unmarshal bigint: to unmarshal into custom uint32, the data should be in the uint32 range") + } + newVal.Elem().SetUint(uint64(p[4])<<24 | uint64(p[5])<<16 | uint64(p[6])<<8 | uint64(p[7])) + v.Elem().Set(newVal) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUintsR(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.Elem().Set(decReflectNullableR(p, v)) + case 8: + val := reflect.New(v.Type().Elem().Elem()) + val.Elem().SetUint(decUint64(p)) + v.Elem().Set(val) + default: + return errWrongDataLen + } + return nil +} + +func decReflectStringR(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + var val reflect.Value + if p == nil { + val = reflect.Zero(v.Type().Elem()) + } else { + val = reflect.New(v.Type().Elem().Elem()) + val.Elem().SetString("0") + } + v.Elem().Set(val) + case 8: + val := reflect.New(v.Type().Elem().Elem()) + val.Elem().SetString(strconv.FormatInt(decInt64(p), 10)) + v.Elem().Set(val) + default: + return errWrongDataLen + } + return nil +} + +func decReflectNullableR(p []byte, v reflect.Value) reflect.Value { + if p == nil { + return reflect.Zero(v.Elem().Type()) + } + return reflect.New(v.Type().Elem().Elem()) +} + +func decInt64(p []byte) int64 { + return int64(p[0])<<56 | int64(p[1])<<48 | int64(p[2])<<40 | int64(p[3])<<32 | int64(p[4])<<24 | int64(p[5])<<16 | int64(p[6])<<8 | int64(p[7]) +} + +func decUint64(p []byte) uint64 { + return uint64(p[0])<<56 | uint64(p[1])<<48 | uint64(p[2])<<40 | uint64(p[3])<<32 | uint64(p[4])<<24 | uint64(p[5])<<16 | uint64(p[6])<<8 | uint64(p[7]) +} diff --git a/marshal_5_bigint_corrupt_test.go b/marshal_5_bigint_corrupt_test.go new file mode 100644 index 000000000..24f2696ee --- /dev/null +++ b/marshal_5_bigint_corrupt_test.go @@ -0,0 +1,133 @@ +package gocql_test + +import ( + "math/big" + "testing" + + "github.com/gocql/gocql" + "github.com/gocql/gocql/internal/tests/serialization" + "github.com/gocql/gocql/internal/tests/serialization/mod" + "github.com/gocql/gocql/marshal/bigint" +) + +func TestMarshalBigIntCorrupt(t *testing.T) { + type testSuite struct { + name string + marshal func(interface{}) ([]byte, error) + unmarshal func(bytes []byte, i interface{}) error + } + + tType := gocql.NewNativeType(4, gocql.TypeBigInt, "") + + testSuites := [2]testSuite{ + { + name: "serialization.bigint", + marshal: bigint.Marshal, + unmarshal: bigint.Unmarshal, + }, + { + name: "glob", + marshal: func(i interface{}) ([]byte, error) { + return gocql.Marshal(tType, i) + }, + unmarshal: func(bytes []byte, i interface{}) error { + return gocql.Unmarshal(tType, bytes, i) + }, + }, + } + + for _, tSuite := range testSuites { + marshal := tSuite.marshal + unmarshal := tSuite.unmarshal + + serialization.NegativeMarshalSet{ + Values: mod.Values{ + "9223372036854775808", + "-9223372036854775809", + *big.NewInt(0).Add(big.NewInt(9223372036854775807), big.NewInt(1)), + *big.NewInt(0).Add(big.NewInt(-9223372036854775808), big.NewInt(-1)), + }.AddVariants(mod.All...), + }.Run("big_vals", t, marshal) + + serialization.NegativeMarshalSet{ + Values: mod.Values{"1s2", "1s", "-1s", ".1", ",1", "0.1", "0,1"}.AddVariants(mod.All...), + }.Run("corrupt_vals", t, marshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x80\x00\x00\x00\x00\x00\x00\x00\x00"), + Values: mod.Values{ + int8(0), int16(0), int32(0), int64(0), int(0), + uint8(0), uint16(0), uint32(0), uint64(0), uint(0), + "", *big.NewInt(0), + }.AddVariants(mod.All...), + }.Run("big_data", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x80\x00\x00\x00\x00\x00\x00"), + Values: mod.Values{ + int8(0), int16(0), int32(0), int64(0), int(0), + uint8(0), uint16(0), uint32(0), uint64(0), uint(0), + "", *big.NewInt(0), + }.AddVariants(mod.All...), + }.Run("small_data", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x80"), + Values: mod.Values{ + int8(0), int16(0), int32(0), int64(0), int(0), + uint8(0), uint16(0), uint32(0), uint64(0), uint(0), + "", *big.NewInt(0), + }.AddVariants(mod.All...), + }.Run("small_data2", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x00\x80"), + Values: mod.Values{int8(0)}.AddVariants(mod.All...), + }.Run("small_type_int8_128", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\xff\xff\xff\xff\xff\xff\xff\x7f"), + Values: mod.Values{int8(0)}.AddVariants(mod.All...), + }.Run("small_type_int8_-129", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x80\x00"), + Values: mod.Values{int8(0), int16(0)}.AddVariants(mod.All...), + }.Run("small_type_int_32768", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\xff\xff\xff\xff\xff\xff\x7f\xff"), + Values: mod.Values{int8(0)}.AddVariants(mod.All...), + }.Run("small_type_int8_-32769", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x00\x00\x00\x00\x80\x00\x00\x00"), + Values: mod.Values{int8(0), int16(0), int32(0)}.AddVariants(mod.All...), + }.Run("small_type_int_2147483647", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\xff\xff\xff\x7f\xff\xff\xff\xff"), + Values: mod.Values{int8(0), int16(0), int32(0)}.AddVariants(mod.All...), + }.Run("small_type_int_-2147483648", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x01\x00"), + Values: mod.Values{uint8(0)}.AddVariants(mod.All...), + }.Run("small_type_uint8_256", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x00\x00\x00\x00\x00\x01\x00\x00"), + Values: mod.Values{uint8(0), uint16(0)}.AddVariants(mod.All...), + }.Run("small_type_uint_65536", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\x00\x00\x00\x01\x00\x00\x00\x00"), + Values: mod.Values{uint8(0), uint16(0), uint32(0)}.AddVariants(mod.All...), + }.Run("small_type_uint_4294967296", t, unmarshal) + + serialization.NegativeUnmarshalSet{ + Data: []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), + Values: mod.Values{uint8(0), uint16(0), uint32(0)}.AddVariants(mod.All...), + }.Run("small_type_uint_max", t, unmarshal) + } +} diff --git a/marshal_5_bigint_test.go b/marshal_5_bigint_test.go index c9a39a1f1..a8ec545d7 100644 --- a/marshal_5_bigint_test.go +++ b/marshal_5_bigint_test.go @@ -7,178 +7,188 @@ import ( "github.com/gocql/gocql" "github.com/gocql/gocql/internal/tests/serialization" "github.com/gocql/gocql/internal/tests/serialization/mod" + "github.com/gocql/gocql/marshal/bigint" ) func TestMarshalBigInt(t *testing.T) { + type testSuite struct { + name string + marshal func(interface{}) ([]byte, error) + unmarshal func(bytes []byte, i interface{}) error + } tType := gocql.NewNativeType(4, gocql.TypeBigInt, "") - marshal := func(i interface{}) ([]byte, error) { return gocql.Marshal(tType, i) } - unmarshal := func(bytes []byte, i interface{}) error { - return gocql.Unmarshal(tType, bytes, i) + testSuites := [2]testSuite{ + { + name: "serialization.bigint", + marshal: bigint.Marshal, + unmarshal: bigint.Unmarshal, + }, + { + name: "glob", + marshal: func(i interface{}) ([]byte, error) { + return gocql.Marshal(tType, i) + }, + unmarshal: func(bytes []byte, i interface{}) error { + return gocql.Unmarshal(tType, bytes, i) + }, + }, } - // unmarshal `custom string` unsupported - brokenCustomStrings := serialization.GetTypes(mod.String(""), (*mod.String)(nil)) - - // marshal "" (empty string) unsupported - // unmarshal nil value into (string)("0") - brokenEmptyStrings := serialization.GetTypes(string(""), mod.String("")) - - // marshal `custom string` unsupported - // marshal `big.Int` unsupported - brokenMarshalTypes := append(brokenCustomStrings, serialization.GetTypes(big.Int{}, &big.Int{})...) - - // marshal data, which equal math.MaxUint64, into uint and uit64 leads to an error - brokenUints := serialization.GetTypes(uint(0), mod.Uint64(0), mod.Uint(0), (*uint)(nil), (*mod.Uint64)(nil), (*mod.Uint)(nil)) - - serialization.PositiveSet{ - Data: nil, - Values: mod.Values{ - (*int8)(nil), (*int16)(nil), (*int32)(nil), (*int64)(nil), (*int)(nil), - (*uint8)(nil), (*uint16)(nil), (*uint32)(nil), (*uint64)(nil), (*uint)(nil), - (*string)(nil), (*big.Int)(nil), "", - }.AddVariants(mod.CustomType), - BrokenMarshalTypes: brokenEmptyStrings, - BrokenUnmarshalTypes: brokenEmptyStrings, - }.Run("[nil]nullable", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: nil, - Values: mod.Values{ - int8(0), int16(0), int32(0), int64(0), int(0), - uint8(0), uint16(0), uint32(0), uint64(0), uint(0), - "0", big.Int{}, - }.AddVariants(mod.CustomType), - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("[nil]unmarshal", t, nil, unmarshal) - - serialization.PositiveSet{ - Data: make([]byte, 0), - Values: mod.Values{ - int8(0), int16(0), int32(0), int64(0), int(0), - uint8(0), uint16(0), uint32(0), uint64(0), uint(0), - "0", *big.NewInt(0), - }.AddVariants(mod.All...), - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("[]unmarshal", t, nil, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), - Values: mod.Values{ - int8(0), int16(0), int32(0), int64(0), int(0), - uint8(0), uint16(0), uint32(0), uint64(0), uint(0), - "0", *big.NewInt(0), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenMarshalTypes, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("zeros", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x7f\xff\xff\xff\xff\xff\xff\xff"), - Values: mod.Values{ - int64(9223372036854775807), int(9223372036854775807), - "9223372036854775807", *big.NewInt(9223372036854775807), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenCustomStrings, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("max", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x80\x00\x00\x00\x00\x00\x00\x00"), - Values: mod.Values{ - int64(-9223372036854775808), int(-9223372036854775808), - "-9223372036854775808", *big.NewInt(-9223372036854775808), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenCustomStrings, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("min", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x00\x00\x00\x00\x7f\xff\xff\xff"), - Values: mod.Values{ - int32(2147483647), int64(2147483647), int(2147483647), - "2147483647", *big.NewInt(2147483647), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenMarshalTypes, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("2147483647", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\xff\xff\xff\xff\x80\x00\x00\x00"), - Values: mod.Values{ - int32(-2147483648), int64(-2147483648), int(-2147483648), - "-2147483648", *big.NewInt(-2147483648), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenMarshalTypes, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("-2147483648", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x00\x00\x00\x00\x00\x00\x7f\xff"), - Values: mod.Values{ - int16(32767), int32(32767), int64(32767), int(32767), - "32767", *big.NewInt(32767), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenMarshalTypes, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("32767", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\xff\xff\xff\xff\xff\xff\x80\x00"), - Values: mod.Values{ - int16(-32768), int32(-32768), int64(-32768), int(-32768), - "-32768", *big.NewInt(-32768), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenMarshalTypes, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("-32768", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x00\x00\x00\x00\x00\x00\x00\x7f"), - Values: mod.Values{ - int8(127), int16(127), int32(127), int64(127), int(127), - "127", *big.NewInt(127), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenMarshalTypes, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("127", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\xff\xff\xff\xff\xff\xff\xff\x80"), - Values: mod.Values{ - int8(-128), int16(-128), int32(-128), int64(-128), int(-128), - "-128", *big.NewInt(-128), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenMarshalTypes, - BrokenUnmarshalTypes: brokenCustomStrings, - }.Run("-128", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x00\x00\x00\x00\x00\x00\x00\xff"), - Values: mod.Values{ - uint8(255), uint16(255), uint32(255), uint64(255), uint(255), - }.AddVariants(mod.All...), - }.Run("255", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x00\x00\x00\x00\x00\x00\xff\xff"), - Values: mod.Values{ - uint16(65535), uint32(65535), uint64(65535), uint(65535), - }.AddVariants(mod.All...), - }.Run("65535", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\x00\x00\x00\x00\xff\xff\xff\xff"), - Values: mod.Values{ - uint32(4294967295), uint64(4294967295), uint(4294967295), - }.AddVariants(mod.All...), - }.Run("4294967295", t, marshal, unmarshal) - - serialization.PositiveSet{ - Data: []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - Values: mod.Values{ - uint64(18446744073709551615), uint(18446744073709551615), - }.AddVariants(mod.All...), - BrokenMarshalTypes: brokenUints, - }.Run("max_uint", t, marshal, unmarshal) + for _, tSuite := range testSuites { + marshal := tSuite.marshal + unmarshal := tSuite.unmarshal + + t.Run(tSuite.name, func(t *testing.T) { + + serialization.PositiveSet{ + Data: nil, + Values: mod.Values{ + (*int8)(nil), (*int16)(nil), (*int32)(nil), (*int64)(nil), (*int)(nil), + (*uint8)(nil), (*uint16)(nil), (*uint32)(nil), (*uint64)(nil), (*uint)(nil), + (*string)(nil), (*big.Int)(nil), "", + }.AddVariants(mod.CustomType), + }.Run("[nil]nullable", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: nil, + Values: mod.Values{ + int8(0), int16(0), int32(0), int64(0), int(0), + uint8(0), uint16(0), uint32(0), uint64(0), uint(0), + "", big.Int{}, + }.AddVariants(mod.CustomType), + }.Run("[nil]unmarshal", t, nil, unmarshal) + + serialization.PositiveSet{ + Data: make([]byte, 0), + Values: mod.Values{ + int8(0), int16(0), int32(0), int64(0), int(0), + uint8(0), uint16(0), uint32(0), uint64(0), uint(0), + "0", *big.NewInt(0), + }.AddVariants(mod.All...), + }.Run("[]unmarshal", t, nil, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), + Values: mod.Values{ + int8(0), int16(0), int32(0), int64(0), int(0), + uint8(0), uint16(0), uint32(0), uint64(0), uint(0), + "0", *big.NewInt(0), + }.AddVariants(mod.All...), + }.Run("zeros", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x7f\xff\xff\xff\xff\xff\xff\xff"), + Values: mod.Values{ + int64(9223372036854775807), int(9223372036854775807), + uint64(9223372036854775807), uint(9223372036854775807), + "9223372036854775807", *big.NewInt(9223372036854775807), + }.AddVariants(mod.All...), + }.Run("max", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x80\x00\x00\x00\x00\x00\x00\x00"), + Values: mod.Values{ + int64(-9223372036854775808), int(-9223372036854775808), + "-9223372036854775808", *big.NewInt(-9223372036854775808), + }.AddVariants(mod.All...), + }.Run("min", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\x7f\xff\xff\xff"), + Values: mod.Values{ + int32(2147483647), int64(2147483647), int(2147483647), + uint32(2147483647), uint64(2147483647), uint(2147483647), + "2147483647", *big.NewInt(2147483647), + }.AddVariants(mod.All...), + }.Run("2147483647", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\xff\xff\xff\xff\x80\x00\x00\x00"), + Values: mod.Values{ + int32(-2147483648), int64(-2147483648), int(-2147483648), + "-2147483648", *big.NewInt(-2147483648), + }.AddVariants(mod.All...), + }.Run("-2147483648", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x7f\xff"), + Values: mod.Values{ + int16(32767), int32(32767), int64(32767), int(32767), + uint16(32767), uint32(32767), uint64(32767), uint(32767), + "32767", *big.NewInt(32767), + }.AddVariants(mod.All...), + }.Run("32767", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\xff\xff\xff\xff\xff\xff\x80\x00"), + Values: mod.Values{ + int16(-32768), int32(-32768), int64(-32768), int(-32768), + "-32768", *big.NewInt(-32768), + }.AddVariants(mod.All...), + }.Run("-32768", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x00\x7f"), + Values: mod.Values{ + int8(127), int16(127), int32(127), int64(127), int(127), + uint8(127), uint16(127), uint32(127), uint64(127), uint(127), + "127", *big.NewInt(127), + }.AddVariants(mod.All...), + }.Run("127", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x00\x01"), + Values: mod.Values{ + int8(1), int16(1), int32(1), int64(1), int(1), + uint8(1), uint16(1), uint32(1), uint64(1), uint(1), + "1", *big.NewInt(1), + }.AddVariants(mod.All...), + }.Run("1", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\xff\xff\xff\xff\xff\xff\xff\x80"), + Values: mod.Values{ + int8(-128), int16(-128), int32(-128), int64(-128), int(-128), + "-128", *big.NewInt(-128), + }.AddVariants(mod.All...), + }.Run("-128", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), + Values: mod.Values{ + int8(-1), int16(-1), int32(-1), int64(-1), int(-1), + "-1", *big.NewInt(-1), + }.AddVariants(mod.All...), + }.Run("-1", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\x00\xff"), + Values: mod.Values{ + uint8(255), uint16(255), uint32(255), uint64(255), uint(255), + }.AddVariants(mod.All...), + }.Run("255", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\x00\x00\xff\xff"), + Values: mod.Values{ + uint16(65535), uint32(65535), uint64(65535), uint(65535), + }.AddVariants(mod.All...), + }.Run("65535", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\x00\x00\x00\x00\xff\xff\xff\xff"), + Values: mod.Values{ + uint32(4294967295), uint64(4294967295), uint(4294967295), + }.AddVariants(mod.All...), + }.Run("4294967295", t, marshal, unmarshal) + + serialization.PositiveSet{ + Data: []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), + Values: mod.Values{ + uint64(18446744073709551615), uint(18446744073709551615), + }.AddVariants(mod.All...), + }.Run("max_uint", t, marshal, unmarshal) + }) + } } diff --git a/marshal_test.go b/marshal_test.go index 84f73d760..86f629510 100644 --- a/marshal_test.go +++ b/marshal_test.go @@ -104,62 +104,6 @@ var marshalTests = []struct { nil, nil, }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), - 0, - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x01\x02\x03\x04\x05\x06\x07\x08"), - 72623859790382856, - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x80\x00\x00\x00\x00\x00\x00\x00"), - int64(math.MinInt64), - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x7f\xff\xff\xff\xff\xff\xff\xff"), - int64(math.MaxInt64), - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\x00\x00"), - "0", - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x01\x02\x03\x04\x05\x06\x07\x08"), - "72623859790382856", - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x80\x00\x00\x00\x00\x00\x00\x00"), - "-9223372036854775808", // math.MinInt64 - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x7f\xff\xff\xff\xff\xff\xff\xff"), - "9223372036854775807", // math.MaxInt64 - nil, - nil, - }, { NativeType{proto: 2, typ: TypeBoolean}, []byte("\x00"), @@ -825,34 +769,6 @@ var marshalTests = []struct { nil, nil, }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\x00\xff"), - uint8(math.MaxUint8), - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\xff\xff"), - uint64(math.MaxUint16), - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\xff\xff\xff\xff"), - uint64(math.MaxUint32), - nil, - nil, - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - uint64(math.MaxUint64), - nil, - nil, - }, { NativeType{proto: 2, typ: TypeBlob}, []byte(nil), @@ -885,102 +801,6 @@ var unmarshalTests = []struct { Value interface{} UnmarshalError error }{ - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - uint8(0), - unmarshalErrorf("unmarshal int: value -1 out of range for uint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\x01\x00"), - uint8(0), - unmarshalErrorf("unmarshal int: value 256 out of range for uint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - uint8(0), - unmarshalErrorf("unmarshal int: value -1 out of range for uint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\x01\x00"), - uint8(0), - unmarshalErrorf("unmarshal int: value 256 out of range for uint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - uint16(0), - unmarshalErrorf("unmarshal int: value -1 out of range for uint16"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x01\x00\x00"), - uint16(0), - unmarshalErrorf("unmarshal int: value 65536 out of range for uint16"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - uint32(0), - unmarshalErrorf("unmarshal int: value -1 out of range for uint32"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x01\x00\x00\x00\x00"), - uint32(0), - unmarshalErrorf("unmarshal int: value 4294967296 out of range for uint32"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - AliasUint8(0), - unmarshalErrorf("unmarshal int: value -1 out of range for gocql.AliasUint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\x01\x00"), - AliasUint8(0), - unmarshalErrorf("unmarshal int: value 256 out of range for gocql.AliasUint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - AliasUint8(0), - unmarshalErrorf("unmarshal int: value -1 out of range for gocql.AliasUint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x00\x01\x00"), - AliasUint8(0), - unmarshalErrorf("unmarshal int: value 256 out of range for gocql.AliasUint8"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - AliasUint16(0), - unmarshalErrorf("unmarshal int: value -1 out of range for gocql.AliasUint16"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x00\x00\x01\x00\x00"), - AliasUint16(0), - unmarshalErrorf("unmarshal int: value 65536 out of range for gocql.AliasUint16"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\xff\xff\xff\xff\xff\xff\xff\xff"), - AliasUint32(0), - unmarshalErrorf("unmarshal int: value -1 out of range for gocql.AliasUint32"), - }, - { - NativeType{proto: 2, typ: TypeBigInt}, - []byte("\x00\x00\x00\x01\x00\x00\x00\x00"), - AliasUint32(0), - unmarshalErrorf("unmarshal int: value 4294967296 out of range for gocql.AliasUint32"), - }, { CollectionType{ NativeType: NativeType{proto: 3, typ: TypeList},