Skip to content

Commit

Permalink
resolve conversations
Browse files Browse the repository at this point in the history
  • Loading branch information
illia-li committed Sep 25, 2024
1 parent f43a435 commit 3fd0269
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 119 deletions.
79 changes: 40 additions & 39 deletions marshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import (
"errors"
"fmt"
"github.com/gocql/gocql/marshal"
"github.com/gocql/gocql/marshal/erro"
"github.com/gocql/gocql/marshal/types/tinyint"
"github.com/gocql/gocql/marshal/tinyint"
"math"
"math/big"
"math/bits"
Expand All @@ -33,14 +32,32 @@ var (
ErrorUDTUnavailable = errors.New("UDT are not available on protocols less than 3, please update config")
)

// Marshaler is the interface implemented by objects that can marshal
// themselves into values understood by Cassandra.
// Marshaler is an interface for marshalling objects according to the CQL binary protocol.
// Initially, each value of the 'CQL binary protocol' consist of <value_len> and <value_data>.
// <value_len> can be 'unset'(-2), 'nil'(-1), 'zero'(0) or any value up to 2147483647.
// In 'unset', 'nil' and 'zero' cases <value_data> is not present.
// Basically, 'unset' is applicable only to columns, but there may be exceptions.
// The current version of 'gocql' writes <value_len> 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 Marshaler interface {
MarshalCQL(info TypeInfo) ([]byte, error)
}

// Unmarshaler is the interface implemented by objects that can unmarshal
// a Cassandra specific description of themselves.
// Unmarshaler is an interface for unmarshalling objects according to the CQL binary protocol.
// Initially, each value of the 'CQL binary protocol' consist of <value_len> and <value_data>.
// <value_len> can be 'nil'(-1), 'zero'(0) or any value up to 2147483647.
// In 'nil' and 'zero' cases <value_data> is not present.
// The current version of 'gocql' reads <value_len> 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 Unmarshaler interface {
UnmarshalCQL(info TypeInfo, data []byte) error
}
Expand Down Expand Up @@ -121,7 +138,7 @@ func Marshal(info TypeInfo, value interface{}) ([]byte, error) {
case TypeBoolean:
return marshalBool(info, value)
case TypeTinyInt:
return mutateMarshal(info, value, tinyint.Marshal)
return marshalTinyInt(value)
case TypeSmallInt:
return marshalSmallInt(info, value)
case TypeInt:
Expand Down Expand Up @@ -234,7 +251,7 @@ func Unmarshal(info TypeInfo, data []byte, value interface{}) error {
case TypeSmallInt:
return unmarshalSmallInt(info, data, value)
case TypeTinyInt:
return mutateUnmarshal(info, data, value, tinyint.Unmarshal)
return unmarshalTinyInt(data, value)
case TypeFloat:
return unmarshalFloat(info, data, value)
case TypeDouble:
Expand Down Expand Up @@ -447,6 +464,14 @@ func marshalSmallInt(info TypeInfo, value interface{}) ([]byte, error) {
return nil, marshalErrorf("can not marshal %T into %s", value, info)
}

func marshalTinyInt(value interface{}) ([]byte, error) {
data, err := tinyint.Marshal(value)
if err != nil {
return nil, MarshalError(err.(Error).Error())
}
return data, nil
}

func marshalInt(info TypeInfo, value interface{}) ([]byte, error) {
switch v := value.(type) {
case Marshaler:
Expand Down Expand Up @@ -633,6 +658,13 @@ func unmarshalSmallInt(info TypeInfo, data []byte, value interface{}) error {
return unmarshalIntlike(info, int64(decShort(data)), data, value)
}

func unmarshalTinyInt(data []byte, value interface{}) error {
if err := tinyint.Unmarshal(data, value); err != nil {
return UnmarshalError(err.(Error).Error())
}
return nil
}

func unmarshalVarint(info TypeInfo, data []byte, value interface{}) error {
switch v := value.(type) {
case *big.Int:
Expand Down Expand Up @@ -2645,34 +2677,3 @@ func (m UnmarshalError) Error() string {
func unmarshalErrorf(format string, args ...interface{}) UnmarshalError {
return UnmarshalError(fmt.Sprintf(format, args...))
}

func mutateMarshal(info TypeInfo, value interface{}, f func(interface{}) ([]byte, error)) ([]byte, error) {
switch v := value.(type) {
case nil, unsetColumn:
return nil, nil
case Marshaler:
return v.MarshalCQL(info)
case marshal.Marshaller:
return v.MarshalCQLv2()
default:
data, err := f(value)
if err != nil {
return nil, MarshalError(err.(erro.Error))
}
return data, nil
}
}

func mutateUnmarshal(info TypeInfo, data []byte, value interface{}, f func([]byte, interface{}) error) error {
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))
}
}
return nil
}
19 changes: 0 additions & 19 deletions marshal/erro/error.go

This file was deleted.

7 changes: 7 additions & 0 deletions marshal/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package marshal

import "errors"

var ErrorGOCQL = errors.New("gocql error")
var ErrorMarshal = errors.Join(ErrorGOCQL, errors.New("marshal error"))
var ErrorUnmarshal = errors.Join(ErrorGOCQL, errors.New("unmarshal error"))
31 changes: 0 additions & 31 deletions marshal/interface.go

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,12 @@ package tinyint
import (
"math/big"
"reflect"

"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 EncInt8(v)
case int32:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
package tinyint

import (
"errors"
"fmt"
"github.com/gocql/gocql/marshal"
"math"
"math/big"
"reflect"
"strconv"

"github.com/gocql/gocql/marshal/erro"
)

var (
errMarshal = erro.Default.Addf("marshal tinyint:")
errMarshal = errors.Join(marshal.ErrorMarshal, errors.New("tinyint"))

maxBigInt = big.NewInt(math.MaxInt64)
minBigInt = big.NewInt(math.MaxInt64)
Expand All @@ -29,7 +30,7 @@ func EncInt8R(v *int8) ([]byte, error) {

func EncInt16(v int16) ([]byte, error) {
if v > math.MaxInt8 || v < math.MinInt8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -43,7 +44,7 @@ func EncInt16R(v *int16) ([]byte, error) {

func EncInt32(v int32) ([]byte, error) {
if v > math.MaxInt8 || v < math.MinInt8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -57,7 +58,7 @@ func EncInt32R(v *int32) ([]byte, error) {

func EncInt64(v int64) ([]byte, error) {
if v > math.MaxInt8 || v < math.MinInt8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -71,7 +72,7 @@ func EncInt64R(v *int64) ([]byte, error) {

func EncInt(v int) ([]byte, error) {
if v > math.MaxInt8 || v < math.MinInt8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -96,7 +97,7 @@ func EncUint8R(v *uint8) ([]byte, error) {

func EncUint16(v uint16) ([]byte, error) {
if v > math.MaxUint8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -110,7 +111,7 @@ func EncUint16R(v *uint16) ([]byte, error) {

func EncUint32(v uint32) ([]byte, error) {
if v > math.MaxUint8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -124,7 +125,7 @@ func EncUint32R(v *uint32) ([]byte, error) {

func EncUint64(v uint64) ([]byte, error) {
if v > math.MaxUint8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -138,7 +139,7 @@ func EncUint64R(v *uint64) ([]byte, error) {

func EncUint(v uint) ([]byte, error) {
if v > math.MaxUint8 {
return nil, errMarshal.Addf("value %#v out of range", v)
return nil, errors.Join(errMarshal, fmt.Errorf("value %#v out of range", v))
}
return []byte{byte(v)}, nil
}
Expand All @@ -152,7 +153,7 @@ func EncUintR(v *uint) ([]byte, error) {

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 nil, errors.Join(errMarshal, fmt.Errorf("value (%T)(%s) out of range", v, v.String()))
}
return EncInt64(v.Int64())
}
Expand All @@ -171,7 +172,7 @@ func EncString(v string) ([]byte, error) {

n, err := strconv.ParseInt(v, 10, 8)
if err != nil {
return nil, errMarshal.Addf("can not marshal %#v %s", v, err)
return nil, errors.Join(errMarshal, fmt.Errorf("can not marshal %#v %s", v, err))
}
return []byte{byte(n)}, nil
}
Expand All @@ -192,7 +193,7 @@ func EncReflect(v reflect.Value) ([]byte, error) {
case reflect.String:
return EncString(v.String())
default:
return nil, errMarshal.Addf("unsupported value type (%T)(%#[1]v)", v.Interface())
return nil, errors.Join(errMarshal, fmt.Errorf("unsupported value type (%T)(%#[1]v)", v.Interface()))
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package tinyint

import (
"github.com/gocql/gocql/marshal"
"errors"
"fmt"
"math/big"
"reflect"
)

func Unmarshal(data []byte, value interface{}) error {
switch v := value.(type) {
case marshal.Unmarshaller:
return v.UnmarshalCQLv2(data)
case nil:
return nil
case *int:
return DecInt(data, v)
case *uint:
Expand Down Expand Up @@ -62,7 +63,7 @@ func Unmarshal(data []byte, value interface{}) error {
rv := reflect.ValueOf(value)
rt := rv.Type()
if rt.Kind() != reflect.Ptr {
return errUnmarshal.Addf("unsupported value type (%T)(%#[1]v)", value)
return errors.Join(errUnmarshal, fmt.Errorf("unsupported value type (%T)(%#[1]v)", value))
}
if rt.Elem().Kind() != reflect.Ptr {
return DecReflect(data, rv)
Expand Down
Loading

0 comments on commit 3fd0269

Please sign in to comment.