forked from scylladb/gocql
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request scylladb#370 from illia-li/il/fix/marshal/cqltime
Fix `time` marshal, unmarshall functions
- Loading branch information
Showing
8 changed files
with
489 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
package cqltime | ||
|
||
import ( | ||
"reflect" | ||
"time" | ||
) | ||
|
||
func Marshal(value interface{}) ([]byte, error) { | ||
switch v := value.(type) { | ||
case nil: | ||
return nil, nil | ||
case int64: | ||
return EncInt64(v) | ||
case *int64: | ||
return EncInt64R(v) | ||
case time.Duration: | ||
return EncDuration(v) | ||
case *time.Duration: | ||
return EncDurationR(v) | ||
|
||
default: | ||
// Custom types (type MyTime int64) 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)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package cqltime | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"time" | ||
) | ||
|
||
const ( | ||
maxValInt64 int64 = 86399999999999 | ||
minValInt64 int64 = 0 | ||
maxValDur time.Duration = 86399999999999 | ||
minValDur time.Duration = 0 | ||
) | ||
|
||
var ( | ||
errOutRangeInt64 = fmt.Errorf("failed to marshal time: the (int64) should be in the range 0 to 86399999999999") | ||
errOutRangeDur = fmt.Errorf("failed to marshal time: the (time.Duration) should be in the range 0 to 86399999999999") | ||
) | ||
|
||
func EncInt64(v int64) ([]byte, error) { | ||
if v > maxValInt64 || v < minValInt64 { | ||
return nil, errOutRangeInt64 | ||
} | ||
return encInt64(v), nil | ||
} | ||
|
||
func EncInt64R(v *int64) ([]byte, error) { | ||
if v == nil { | ||
return nil, nil | ||
} | ||
return EncInt64(*v) | ||
} | ||
|
||
func EncDuration(v time.Duration) ([]byte, error) { | ||
if v > maxValDur || v < minValDur { | ||
return nil, errOutRangeDur | ||
} | ||
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 EncDurationR(v *time.Duration) ([]byte, error) { | ||
if v == nil { | ||
return nil, nil | ||
} | ||
return EncDuration(*v) | ||
} | ||
|
||
func EncReflect(v reflect.Value) ([]byte, error) { | ||
switch v.Kind() { | ||
case reflect.Int64: | ||
val := v.Int() | ||
if val > maxValInt64 || val < minValInt64 { | ||
return nil, fmt.Errorf("failed to marshal time: the (%T) should be in the range 0 to 86399999999999", v.Interface()) | ||
} | ||
return encInt64(val), nil | ||
case reflect.Struct: | ||
if v.Type().String() == "gocql.unsetColumn" { | ||
return nil, nil | ||
} | ||
return nil, fmt.Errorf("failed to marshal time: unsupported value type (%T)(%[1]v)", v.Interface()) | ||
default: | ||
return nil, fmt.Errorf("failed to marshal time: 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)} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package cqltime | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"time" | ||
) | ||
|
||
func Unmarshal(data []byte, value interface{}) error { | ||
switch v := value.(type) { | ||
case nil: | ||
return nil | ||
|
||
case *int64: | ||
return DecInt64(data, v) | ||
case **int64: | ||
return DecInt64R(data, v) | ||
case *time.Duration: | ||
return DecDuration(data, v) | ||
case **time.Duration: | ||
return DecDurationR(data, v) | ||
default: | ||
|
||
// Custom types (type MyTime int64) 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 time: unsupported value type (%T)(%[1]v)", value) | ||
} | ||
if rt.Elem().Kind() != reflect.Ptr { | ||
return DecReflect(data, rv) | ||
} | ||
return DecReflectR(data, rv) | ||
} | ||
} |
Oops, something went wrong.