From ced833c7d6f72cf8d9806b6db9a3c6d8f47c08f1 Mon Sep 17 00:00:00 2001 From: illia-li Date: Mon, 16 Sep 2024 13:19:26 -0400 Subject: [PATCH] refactoring --- marshal.go | 110 +------- marshal/interface.go | 31 +++ marshal/types/tinyint/marshal.go | 128 +++++---- marshal/types/tinyint/marshal_utils.go | 204 ++++++++++++++ marshal/types/tinyint/unmarshal.go | 153 ++++------- marshal/types/tinyint/unmarshal_utils.go | 326 +++++++++++++++++++++++ marshal/types/tinyint/utils.go | 25 -- 7 files changed, 680 insertions(+), 297 deletions(-) create mode 100644 marshal/interface.go create mode 100644 marshal/types/tinyint/marshal_utils.go create mode 100644 marshal/types/tinyint/unmarshal_utils.go delete mode 100644 marshal/types/tinyint/utils.go diff --git a/marshal.go b/marshal.go index 18596f66f..b7c54ccf2 100644 --- a/marshal.go +++ b/marshal.go @@ -9,6 +9,7 @@ import ( "encoding/binary" "errors" "fmt" + "github.com/gocql/gocql/marshal" "github.com/gocql/gocql/marshal/erro" "github.com/gocql/gocql/marshal/types/tinyint" "math" @@ -93,14 +94,13 @@ type Unmarshaler interface { // duration | gocql.Duration | // duration | string | parsed with time.ParseDuration func Marshal(info TypeInfo, value interface{}) ([]byte, error) { + if v, ok := value.(marshal.Marshaller); ok { + return v.MarshalCQLv2() + } if info.Version() < protoVersion1 { panic("protocol version not set") } - if _, ok := value.(unsetColumn); ok { - return nil, nil - } - if valueRef := reflect.ValueOf(value); valueRef.Kind() == reflect.Ptr { if valueRef.IsNil() { return nil, nil @@ -212,6 +212,9 @@ func Unmarshal(info TypeInfo, data []byte, value interface{}) error { if v, ok := value.(Unmarshaler); ok { return v.UnmarshalCQL(info, data) } + if v, ok := value.(marshal.Unmarshaller); ok { + return v.UnmarshalCQLv2(data) + } if isNullableValue(value) { return unmarshalNullable(info, data, value) @@ -444,90 +447,6 @@ func marshalSmallInt(info TypeInfo, value interface{}) ([]byte, error) { return nil, marshalErrorf("can not marshal %T into %s", value, info) } -func marshalTinyInt(info TypeInfo, value interface{}) ([]byte, error) { - switch v := value.(type) { - case Marshaler: - return v.MarshalCQL(info) - case unsetColumn: - return nil, nil - case int8: - return []byte{byte(v)}, nil - case uint8: - return []byte{byte(v)}, nil - case int16: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case uint16: - if v > math.MaxUint8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case int: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case int32: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case int64: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case uint: - if v > math.MaxUint8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case uint32: - if v > math.MaxUint8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case uint64: - if v > math.MaxUint8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case string: - n, err := strconv.ParseInt(v, 10, 8) - if err != nil { - return nil, marshalErrorf("can not marshal %T into %s: %v", value, info, err) - } - return []byte{byte(n)}, 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.MaxInt8 || v < math.MinInt8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8: - v := rv.Uint() - if v > math.MaxUint8 { - return nil, marshalErrorf("marshal tinyint: value %d out of range", v) - } - return []byte{byte(v)}, nil - case reflect.Ptr: - if rv.IsNil() { - return nil, nil - } - } - - return nil, marshalErrorf("can not marshal %T into %s", value, info) -} - func marshalInt(info TypeInfo, value interface{}) ([]byte, error) { switch v := value.(type) { case Marshaler: @@ -625,13 +544,6 @@ func decShort(p []byte) int16 { return int16(p[0])<<8 | int16(p[1]) } -func decTiny(p []byte) int8 { - if len(p) != 1 { - return 0 - } - return int8(p[0]) -} - func marshalBigInt(info TypeInfo, value interface{}) ([]byte, error) { switch v := value.(type) { case Marshaler: @@ -721,10 +633,6 @@ func unmarshalSmallInt(info TypeInfo, data []byte, value interface{}) error { return unmarshalIntlike(info, int64(decShort(data)), data, value) } -func unmarshalTinyInt(info TypeInfo, data []byte, value interface{}) error { - return tinyint.Unmarshal(data, value) -} - func unmarshalVarint(info TypeInfo, data []byte, value interface{}) error { switch v := value.(type) { case *big.Int: @@ -2744,6 +2652,8 @@ func mutateMarshal(info TypeInfo, value interface{}, f func(interface{}) ([]byte return nil, nil case Marshaler: return v.MarshalCQL(info) + case marshal.Marshaller: + return v.MarshalCQLv2() default: data, err := f(value) if err != nil { @@ -2757,6 +2667,8 @@ func mutateUnmarshal(info TypeInfo, data []byte, value interface{}, f func([]byt switch v := value.(type) { case Unmarshaler: return v.UnmarshalCQL(info, data) + case marshal.Unmarshaller: + return v.UnmarshalCQLv2(data) default: if err := f(data, value); err != nil { return UnmarshalError(err.(erro.Error)) diff --git a/marshal/interface.go b/marshal/interface.go new file mode 100644 index 000000000..838c1ff03 --- /dev/null +++ b/marshal/interface.go @@ -0,0 +1,31 @@ +package marshal + +// Marshaller is an interface for marshalling objects according to the CQL binary protocol. +// Initially, each value of the 'CQL binary protocol' consist of and . +// can be 'unset'(-2), 'nil'(-1), 'zero'(0) or any value up to 2147483647. +// In 'unset', 'nil' and 'zero' cases is not present. +// Basically, 'unset' is applicable only to columns, but there may be exceptions. +// The current version of 'gocql' writes through logic after marshaling functions, +// so you need to tell this logic about these cases: +// 1. In 'unset' case - you need to put gocql.UnsetValue instead of value. +// 2. In 'nil' case - your Marshaller implementation should return []byte==nil. +// 3. In 'zero' case - your Marshaller implementation should return initiated []byte with len==0. +// +// All CQL DB`s have proprietary value coding features, which you need to consider. +// CQL binary protocol info:https://github.com/apache/cassandra/tree/trunk/doc +type Marshaller interface { + MarshalCQLv2() ([]byte, error) +} + +// Unmarshaller is an interface for unmarshalling objects according to the CQL binary protocol. +// Initially, each value of the 'CQL binary protocol' consist of and . +// can be 'nil'(-1), 'zero'(0) or any value up to 2147483647. +// In 'nil' and 'zero' cases is not present. +// The current version of 'gocql' reads through logic before unmarshalling functions, +// so your Unmarshaller implementation will receive: +// in the 'nil' case - []byte==nil, +// in the 'zero' case - initiated []byte with len==0. +// CQL binary protocol info:https://github.com/apache/cassandra/tree/trunk/doc +type Unmarshaller interface { + UnmarshalCQLv2(data []byte) error +} diff --git a/marshal/types/tinyint/marshal.go b/marshal/types/tinyint/marshal.go index 5dd5e4b60..64c8c70f7 100644 --- a/marshal/types/tinyint/marshal.go +++ b/marshal/types/tinyint/marshal.go @@ -1,88 +1,80 @@ package tinyint import ( - "math" + "math/big" "reflect" - "strconv" - "github.com/gocql/gocql/marshal/erro" + "github.com/gocql/gocql/marshal" ) func Marshal(value interface{}) ([]byte, error) { switch v := value.(type) { + case nil: + return nil, nil + case marshal.Marshaller: + return v.MarshalCQLv2() + case int8: - return []byte{byte(v)}, nil - case uint8: - return []byte{byte(v)}, nil - case int16: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil - case uint16: - if v > math.MaxUint8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil - case int: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil + return EncInt8(v) case int32: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil + return EncInt32(v) + case int16: + return EncInt16(v) case int64: - if v > math.MaxInt8 || v < math.MinInt8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil - case uint: - if v > math.MaxUint8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil + return EncInt64(v) + case int: + return EncInt(v) + + case uint8: + return EncUint8(v) + case uint16: + return EncUint16(v) case uint32: - if v > math.MaxUint8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil + return EncUint32(v) case uint64: - if v > math.MaxUint8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil + return EncUint64(v) + case uint: + return EncUint(v) + + case big.Int: + return EncBigInt(v) case string: - n, err := strconv.ParseInt(v, 10, 8) - if err != nil { - return nil, erro.Newf("marshal tinyint: can not marshal %#v %s", value, err) - } - return []byte{byte(n)}, nil - } + return EncString(v) - if value == nil { - return nil, nil - } + 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) - 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.MaxInt8 || v < math.MinInt8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil - case reflect.Uint, reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8: - v := rv.Uint() - if v > math.MaxUint8 { - return nil, erro.Newf("marshal tinyint: value %#v out of range", v) - } - return []byte{byte(v)}, nil - case reflect.Ptr: - if rv.IsNil() { - return nil, nil + 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: + rv := reflect.TypeOf(value) + if rv.Kind() == reflect.Ptr { + if rv.Elem().Kind() != reflect.Ptr { + return EncReflect(reflect.ValueOf(v)) + } + return EncReflectR(reflect.ValueOf(v)) } + return nil, errMarshal.Addf("unsupported value type %#v", value) } - return nil, erro.Newf("marshal tinyint: can not marshal %#v", value) } diff --git a/marshal/types/tinyint/marshal_utils.go b/marshal/types/tinyint/marshal_utils.go new file mode 100644 index 000000000..8d425c53e --- /dev/null +++ b/marshal/types/tinyint/marshal_utils.go @@ -0,0 +1,204 @@ +package tinyint + +import ( + "math" + "math/big" + "reflect" + "strconv" + + "github.com/gocql/gocql/marshal/erro" +) + +var ( + errMarshal = erro.Default.Addf("marshal tinyint:") + + maxBigInt = big.NewInt(math.MaxInt64) + minBigInt = big.NewInt(math.MaxInt64) +) + +func EncInt8(v int8) ([]byte, error) { + return []byte{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 > math.MaxInt8 || v < math.MinInt8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{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 > math.MaxInt8 || v < math.MinInt8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{byte(v)}, nil +} + +func EncInt32R(v *int32) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncInt32(*v) +} + +func EncInt64(v int64) ([]byte, error) { + if v > math.MaxInt8 || v < math.MinInt8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{byte(v)}, nil +} + +func EncInt64R(v *int64) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncInt64(*v) +} + +func EncInt(v int) ([]byte, error) { + if v > math.MaxInt8 || v < math.MinInt8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{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{v}, nil +} + +func EncUint8R(v *uint8) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint8(*v) +} + +func EncUint16(v uint16) ([]byte, error) { + if v > math.MaxUint8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{byte(v)}, nil +} + +func EncUint16R(v *uint16) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint16(*v) +} + +func EncUint32(v uint32) ([]byte, error) { + if v > math.MaxUint8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{byte(v)}, nil +} + +func EncUint32R(v *uint32) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint32(*v) +} + +func EncUint64(v uint64) ([]byte, error) { + if v > math.MaxUint8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{byte(v)}, nil +} + +func EncUint64R(v *uint64) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncUint64(*v) +} + +func EncUint(v uint) ([]byte, error) { + if v > math.MaxUint8 { + return nil, errMarshal.Addf("value %#v out of range", v) + } + return []byte{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, errMarshal.Addf("value (%T)(%s) out of range", v, v.String()) + } + return EncInt64(v.Int64()) +} + +func EncBigIntR(v *big.Int) ([]byte, error) { + if v == nil { + return nil, nil + } + return EncBigInt(*v) +} + +func EncString(v string) ([]byte, error) { + if v == "" { + return nil, nil + } + + n, err := strconv.ParseInt(v, 10, 8) + if err != nil { + return nil, errMarshal.Addf("can not marshal %#v %s", v, err) + } + return []byte{byte(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.Type().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: + return EncString(v.String()) + default: + return nil, errMarshal.Addf("unsupported value type %#v", v.Interface()) + } +} + +func EncReflectR(v reflect.Value) ([]byte, error) { + if v.IsNil() { + return nil, nil + } + return EncReflect(v.Elem()) +} diff --git a/marshal/types/tinyint/unmarshal.go b/marshal/types/tinyint/unmarshal.go index d3b02dbf4..f3aa74153 100644 --- a/marshal/types/tinyint/unmarshal.go +++ b/marshal/types/tinyint/unmarshal.go @@ -1,129 +1,72 @@ package tinyint import ( - "github.com/gocql/gocql/marshal/erro" - "math" + "github.com/gocql/gocql/marshal" "math/big" "reflect" - "strconv" ) func Unmarshal(data []byte, value interface{}) error { - return unmarshalIntlike(int64(decTiny(data)), data, value) -} - -func unmarshalIntlike(int64Val int64, data []byte, value interface{}) error { switch v := value.(type) { + case marshal.Unmarshaller: + return v.UnmarshalCQLv2(data) case *int: - if ^uint(0) == math.MaxUint32 && (int64Val < math.MinInt32 || int64Val > math.MaxInt32) { - return erro.Newf("unmarshal int: value %#v out of range for %T", int64Val, *v) - } - *v = int(int64Val) - return nil + return DecInt(data, v) case *uint: - unitVal := uint64(int64Val) - *v = uint(unitVal) & 0xFF - return nil + return DecUint(data, v) case *int64: - *v = int64Val - return nil + return DecInt64(data, v) case *uint64: - *v = uint64(int64Val) & 0xFF - return nil + return DecUint64(data, v) case *int32: - if int64Val < math.MinInt32 || int64Val > math.MaxInt32 { - return erro.Newf("unmarshal int: value %#v out of range for %T", int64Val, *v) - } - *v = int32(int64Val) - return nil + return DecInt32(data, v) case *uint32: - *v = uint32(int64Val) & 0xFF - return nil + return DecUint32(data, v) case *int16: - if int64Val < math.MinInt16 || int64Val > math.MaxInt16 { - return erro.Newf("unmarshal int: value %#v out of range for %T", int64Val, *v) - } - *v = int16(int64Val) - return nil + return DecInt16(data, v) case *uint16: - *v = uint16(int64Val) & 0xFF - return nil + return DecUint16(data, v) case *int8: - if int64Val < math.MinInt8 || int64Val > math.MaxInt8 { - return erro.Newf("unmarshal int: value %#v out of range for %T", int64Val, *v) - } - *v = int8(int64Val) - return nil + return DecInt8(data, v) case *uint8: - if int64Val < 0 || int64Val > math.MaxUint8 { - return erro.Newf("unmarshal int: value %#v out of range for %T", int64Val, *v) - } - *v = uint8(int64Val) & 0xFF - return nil + return DecUint8(data, v) case *big.Int: - decBigInt2C(data, v) - return nil + return DecBigInt(data, v) case *string: - *v = strconv.FormatInt(int64Val, 10) - return nil - } - - rv := reflect.ValueOf(value) - if rv.Kind() != reflect.Ptr { - return erro.Newf("can not unmarshal into non-pointer %T", value) - } - rv = rv.Elem() - - switch rv.Type().Kind() { - case reflect.Int: - if ^uint(0) == math.MaxUint32 && (int64Val < math.MinInt32 || int64Val > math.MaxInt32) { - return erro.Newf("unmarshal int: value %#v out of range", int64Val) - } - rv.SetInt(int64Val) - return nil - case reflect.Int64: - rv.SetInt(int64Val) - return nil - case reflect.Int32: - if int64Val < math.MinInt32 || int64Val > math.MaxInt32 { - return erro.Newf("unmarshal int: value %#v out of range", int64Val) - } - rv.SetInt(int64Val) - return nil - case reflect.Int16: - if int64Val < math.MinInt16 || int64Val > math.MaxInt16 { - return erro.Newf("unmarshal int: value %#v out of range", int64Val) - } - rv.SetInt(int64Val) - return nil - case reflect.Int8: - if int64Val < math.MinInt8 || int64Val > math.MaxInt8 { - return erro.Newf("unmarshal int: value %#v out of range", int64Val) - } - rv.SetInt(int64Val) - return nil - case reflect.Uint: - unitVal := uint64(int64Val) - rv.SetUint(unitVal & 0xFF) - return nil - case reflect.Uint64: - unitVal := uint64(int64Val) - rv.SetUint(unitVal & 0xFF) - return nil - case reflect.Uint32: - unitVal := uint64(int64Val) - rv.SetUint(unitVal & 0xFF) - return nil - case reflect.Uint16: - unitVal := uint64(int64Val) - rv.SetUint(unitVal & 0xFF) - return nil - case reflect.Uint8: - if int64Val < 0 || int64Val > math.MaxUint8 { - return erro.Newf("unmarshal int: value %#v out of range for %s", int64Val, rv.Type()) + return DecString(data, v) + case **int: + return DecIntR(data, v) + case **uint: + return DecUintR(data, v) + case **int64: + return DecInt64R(data, v) + case **uint64: + return DecUint64R(data, v) + case **int32: + return DecInt32R(data, v) + case **uint32: + return DecUint32R(data, v) + case **int16: + return DecInt16R(data, v) + case **uint16: + return DecUint16R(data, v) + case **int8: + return DecInt8R(data, v) + case **uint8: + return DecUint8R(data, v) + case **big.Int: + return DecBigIntR(data, v) + case **string: + return DecStringR(data, v) + default: + rv := reflect.ValueOf(value) + rt := rv.Type() + if rt.Kind() == reflect.Ptr { + if rt.Elem().Kind() == reflect.Ptr { + return DecReflectR(data, rv) + } + return DecReflect(data, rv) } - rv.SetUint(uint64(int64Val) & 0xff) - return nil + return errUnmarshal.Addf("unsupported value type %#v", value) } - return erro.Newf("unmarshal int: can not unmarshal %#v", value) } diff --git a/marshal/types/tinyint/unmarshal_utils.go b/marshal/types/tinyint/unmarshal_utils.go new file mode 100644 index 000000000..3f0e77112 --- /dev/null +++ b/marshal/types/tinyint/unmarshal_utils.go @@ -0,0 +1,326 @@ +package tinyint + +import ( + "math/big" + "reflect" + "strconv" + + "github.com/gocql/gocql/marshal/erro" +) + +var errUnmarshal = erro.Default.Addf("unmarshal tinyint:") +var errWrongDataLen = errUnmarshal.Addf("the length of the data should be no more than 1") + +func DecInt8(p []byte, v *int8) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = int8(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecInt8R(p []byte, v **int8) error { + if p != nil { + return DecInt8(p, *v) + } + *v = nil + return nil +} + +func DecInt16(p []byte, v *int16) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = int16(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecInt16R(p []byte, v **int16) error { + if p != nil { + return DecInt16(p, *v) + } + *v = nil + return nil +} + +func DecInt32(p []byte, v *int32) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = int32(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecInt32R(p []byte, v **int32) error { + if p != nil { + return DecInt32(p, *v) + } + *v = nil + return nil +} + +func DecInt64(p []byte, v *int64) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = int64(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecInt64R(p []byte, v **int64) error { + if p != nil { + return DecInt64(p, *v) + } + *v = nil + return nil +} + +func DecInt(p []byte, v *int) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = int(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecIntR(p []byte, v **int) error { + if p != nil { + return DecInt(p, *v) + } + *v = nil + return nil +} + +func DecUint8(p []byte, v *uint8) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = p[0] + default: + return errWrongDataLen + } + return nil +} + +func DecUint8R(p []byte, v **uint8) error { + if p != nil { + return DecUint8(p, *v) + } + *v = nil + return nil +} + +func DecUint16(p []byte, v *uint16) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = uint16(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecUint16R(p []byte, v **uint16) error { + if p != nil { + return DecUint16(p, *v) + } + *v = nil + return nil +} + +func DecUint32(p []byte, v *uint32) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = uint32(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecUint32R(p []byte, v **uint32) error { + if p != nil { + return DecUint32(p, *v) + } + *v = nil + return nil +} + +func DecUint64(p []byte, v *uint64) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = uint64(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecUint64R(p []byte, v **uint64) error { + if p != nil { + return DecUint64(p, *v) + } + *v = nil + return nil +} + +func DecUint(p []byte, v *uint) error { + switch len(p) { + case 0: + *v = 0 + case 1: + *v = uint(p[0]) + default: + return errWrongDataLen + } + return nil +} + +func DecUintR(p []byte, v **uint) error { + if p != nil { + return DecUint(p, *v) + } + *v = nil + return nil +} + +func DecString(p []byte, v *string) error { + switch len(p) { + case 0: + if p != nil { + *v = "0" + } else { + *v = "" + } + case 1: + *v = strconv.FormatInt(int64(p[0]), 10) + default: + return errWrongDataLen + } + return nil +} + +func DecStringR(p []byte, v **string) error { + if p != nil { + return DecString(p, *v) + } + *v = nil + return nil +} + +func DecBigInt(p []byte, v *big.Int) error { + switch len(p) { + case 0: + v.SetInt64(0) + case 1: + v.SetInt64(int64(p[0])) + default: + return errWrongDataLen + } + return nil +} + +func DecBigIntR(p []byte, v **big.Int) error { + if p != nil { + return DecBigInt(p, *v) + } + *v = nil + return nil +} + +func DecReflect(p []byte, v reflect.Value) error { + if v.IsNil() { + return errUnmarshal.Addf("can not unmarshal into nil reference %#v", v.Interface()) + } + + switch v = v.Elem(); v.Kind() { + case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int: + return decReflectInts(p, v) + case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint: + return decReflectUints(p, v) + case reflect.String: + return decReflectString(p, v) + default: + return errUnmarshal.Addf("unsupported value type %#v", v.Interface()) + } +} + +func DecReflectR(p []byte, v reflect.Value) error { + if v.IsNil() { + return errUnmarshal.Addf("can not unmarshal into nil reference %#v", v.Interface()) + } + + if p == nil && !v.Elem().IsNil() { + nilValue := reflect.Zero(v.Elem().Type()) + v.Set(nilValue) + return nil + } + return DecReflect(p, v.Elem()) +} + +func decReflectInts(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetInt(0) + case 1: + v.SetInt(int64(p[0])) + default: + return errWrongDataLen + } + return nil +} + +func decReflectUints(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + v.SetUint(0) + case 1: + v.SetUint(uint64(p[0])) + default: + return errWrongDataLen + } + return nil +} + +func decReflectString(p []byte, v reflect.Value) error { + switch len(p) { + case 0: + if p != nil { + v.SetString("0") + } else { + v.SetString("") + } + case 1: + v.SetString(strconv.FormatInt(int64(p[0]), 10)) + default: + return errWrongDataLen + } + return nil +} diff --git a/marshal/types/tinyint/utils.go b/marshal/types/tinyint/utils.go deleted file mode 100644 index d61912b82..000000000 --- a/marshal/types/tinyint/utils.go +++ /dev/null @@ -1,25 +0,0 @@ -package tinyint - -import ( - "math/big" -) - -func decBigInt2C(data []byte, n *big.Int) *big.Int { - if n == nil { - n = new(big.Int) - } - n.SetBytes(data) - if len(data) > 0 && data[0]&0x80 > 0 { - n.Sub(n, new(big.Int).Lsh(bigOne, uint(len(data))*8)) - } - return n -} - -func decTiny(p []byte) int8 { - if len(p) != 1 { - return 0 - } - return int8(p[0]) -} - -var bigOne = big.NewInt(1)