Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix int marshal, unmarshall #290

Merged
merged 3 commits into from
Oct 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 14 additions & 87 deletions marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (

"gopkg.in/inf.v0"

"github.com/gocql/gocql/marshal/cqlint"
"github.com/gocql/gocql/marshal/smallint"
"github.com/gocql/gocql/marshal/tinyint"
)
Expand Down Expand Up @@ -141,7 +142,7 @@ func Marshal(info TypeInfo, value interface{}) ([]byte, error) {
case TypeSmallInt:
return marshalSmallInt(value)
case TypeInt:
return marshalInt(info, value)
return marshalInt(value)
case TypeBigInt, TypeCounter:
return marshalBigInt(info, value)
case TypeFloat:
Expand Down Expand Up @@ -239,7 +240,7 @@ func Unmarshal(info TypeInfo, data []byte, value interface{}) error {
case TypeBoolean:
return unmarshalBool(info, data, value)
case TypeInt:
return unmarshalInt(info, data, value)
return unmarshalInt(data, value)
case TypeBigInt, TypeCounter:
return unmarshalBigInt(info, data, value)
case TypeVarint:
Expand Down Expand Up @@ -398,76 +399,12 @@ func marshalTinyInt(value interface{}) ([]byte, error) {
return data, nil
}

func marshalInt(info TypeInfo, value interface{}) ([]byte, error) {
switch v := value.(type) {
case Marshaler:
return v.MarshalCQL(info)
case unsetColumn:
return nil, nil
case int:
if v > math.MaxInt32 || v < math.MinInt32 {
return nil, marshalErrorf("marshal int: value %d out of range", v)
}
return encInt(int32(v)), nil
case uint:
if v > math.MaxUint32 {
return nil, marshalErrorf("marshal int: value %d out of range", v)
}
return encInt(int32(v)), nil
case int64:
if v > math.MaxInt32 || v < math.MinInt32 {
return nil, marshalErrorf("marshal int: value %d out of range", v)
}
return encInt(int32(v)), nil
case uint64:
if v > math.MaxUint32 {
return nil, marshalErrorf("marshal int: value %d out of range", v)
}
return encInt(int32(v)), nil
case int32:
return encInt(v), nil
case uint32:
return encInt(int32(v)), nil
case int16:
return encInt(int32(v)), nil
case uint16:
return encInt(int32(v)), nil
case int8:
return encInt(int32(v)), nil
case uint8:
return encInt(int32(v)), nil
case string:
i, err := strconv.ParseInt(v, 10, 32)
if err != nil {
return nil, marshalErrorf("can not marshal string to int: %s", err)
}
return encInt(int32(i)), nil
}

if value == nil {
return nil, nil
}

switch rv := reflect.ValueOf(value); rv.Type().Kind() {
case reflect.Int, reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8:
v := rv.Int()
if v > math.MaxInt32 || v < math.MinInt32 {
return nil, marshalErrorf("marshal int: value %d out of range", v)
}
return encInt(int32(v)), nil
case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8:
v := rv.Uint()
if v > math.MaxInt32 {
return nil, marshalErrorf("marshal int: value %d out of range", v)
}
return encInt(int32(v)), nil
case reflect.Ptr:
if rv.IsNil() {
return nil, nil
}
func marshalInt(value interface{}) ([]byte, error) {
data, err := cqlint.Marshal(value)
if err != nil {
return nil, wrapMarshalError(err, "marshal error")
}

return nil, marshalErrorf("can not marshal %T into %s", value, info)
return data, nil
}

func encInt(x int32) []byte {
Expand All @@ -481,20 +418,6 @@ func decInt(x []byte) int32 {
return int32(x[0])<<24 | int32(x[1])<<16 | int32(x[2])<<8 | int32(x[3])
}

func encShort(x int16) []byte {
p := make([]byte, 2)
p[0] = byte(x >> 8)
p[1] = byte(x)
return p
}

func decShort(p []byte) int16 {
if len(p) != 2 {
return 0
}
return int16(p[0])<<8 | int16(p[1])
}

func marshalBigInt(info TypeInfo, value interface{}) ([]byte, error) {
switch v := value.(type) {
case Marshaler:
Expand Down Expand Up @@ -576,8 +499,12 @@ func unmarshalBigInt(info TypeInfo, data []byte, value interface{}) error {
return unmarshalIntlike(info, decBigInt(data), data, value)
}

func unmarshalInt(info TypeInfo, data []byte, value interface{}) error {
return unmarshalIntlike(info, int64(decInt(data)), data, value)
func unmarshalInt(data []byte, value interface{}) error {
err := cqlint.Unmarshal(data, value)
if err != nil {
return wrapUnmarshalError(err, "unmarshal error")
}
return nil
}

func unmarshalSmallInt(data []byte, value interface{}) error {
Expand Down
74 changes: 74 additions & 0 deletions marshal/cqlint/marshal.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package cqlint

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 int32:
return EncInt32(v)
case int16:
return EncInt16(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))
}
}
Loading
Loading