Skip to content

Commit

Permalink
feat: Export msgpack ext encode/decode functions
Browse files Browse the repository at this point in the history
Fixes #420.
  • Loading branch information
rybakit committed Dec 16, 2024
1 parent 10b3c8f commit aba1b22
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 54 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Versioning](http://semver.org/spec/v2.0.0.html) except to the first release.

### Changed

- Made MessagePack extension encoding and decoding functions exportable,
allowing users to reuse the logic for custom extensions (#421).

### Fixed

## [v2.2.0] - 2024-12-16
Expand Down
18 changes: 9 additions & 9 deletions arrow/arrow.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (
"github.com/vmihailenco/msgpack/v5"
)

// Arrow MessagePack extension type.
const arrowExtId = 8
// ExtID represents the Arrow MessagePack extension type identifier.
const ExtID = 8

// Arrow struct wraps a raw arrow data buffer.
type Arrow struct {
Expand All @@ -26,31 +26,31 @@ func (a Arrow) Raw() []byte {
return a.data
}

func arrowDecoder(d *msgpack.Decoder, v reflect.Value, extLen int) error {
func DecodeExt(d *msgpack.Decoder, v reflect.Value, extLen int) error {
arrow := Arrow{
data: make([]byte, extLen),
}
n, err := d.Buffered().Read(arrow.data)
if err != nil {
return fmt.Errorf("arrowDecoder: can't read bytes on Arrow decode: %w", err)
return fmt.Errorf("decode: can't read bytes on Arrow decode: %w", err)
}
if n < extLen || n != len(arrow.data) {
return fmt.Errorf("arrowDecoder: unexpected end of stream after %d Arrow bytes", n)
return fmt.Errorf("decode: unexpected end of stream after %d Arrow bytes", n)
}

v.Set(reflect.ValueOf(arrow))
return nil
}

func arrowEncoder(e *msgpack.Encoder, v reflect.Value) ([]byte, error) {
func EncodeExt(_ *msgpack.Encoder, v reflect.Value) ([]byte, error) {
arr, ok := v.Interface().(Arrow)
if !ok {
return []byte{}, fmt.Errorf("arrowEncoder: not an Arrow type")
return []byte{}, fmt.Errorf("encode: not an Arrow type")
}
return arr.data, nil
}

func init() {
msgpack.RegisterExtDecoder(arrowExtId, Arrow{}, arrowDecoder)
msgpack.RegisterExtEncoder(arrowExtId, Arrow{}, arrowEncoder)
msgpack.RegisterExtDecoder(ExtID, Arrow{}, DecodeExt)
msgpack.RegisterExtEncoder(ExtID, Arrow{}, EncodeExt)
}
15 changes: 8 additions & 7 deletions datetime/datetime.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package with support of Tarantool's datetime data type.
// Package datetime provides support for Tarantool's datetime data type.
//
// Datetime data type supported in Tarantool since 2.10.
//
Expand Down Expand Up @@ -34,9 +34,10 @@ import (
// * [optional] all the other fields (nsec, tzoffset, tzindex) if any of them
// were having not 0 value. They are packed naturally in little-endian order;

// Datetime external type. Supported since Tarantool 2.10. See more details in
// ExtID represents the Datetime MessagePack extension type identifier.
// Supported since Tarantool 2.10. See more details in
// issue https://github.com/tarantool/tarantool/issues/5946.
const datetimeExtID = 4
const ExtID = 4

// datetime structure keeps a number of seconds and nanoseconds since Unix Epoch.
// Time is normalized by UTC, so time-zone offset is informative only.
Expand Down Expand Up @@ -242,7 +243,7 @@ func (d *Datetime) ToTime() time.Time {
return d.time
}

func datetimeEncoder(e *msgpack.Encoder, v reflect.Value) ([]byte, error) {
func EncodeExt(_ *msgpack.Encoder, v reflect.Value) ([]byte, error) {
dtime := v.Interface().(Datetime)
tm := dtime.ToTime()

Expand Down Expand Up @@ -275,7 +276,7 @@ func datetimeEncoder(e *msgpack.Encoder, v reflect.Value) ([]byte, error) {
return buf, nil
}

func datetimeDecoder(d *msgpack.Decoder, v reflect.Value, extLen int) error {
func DecodeExt(d *msgpack.Decoder, v reflect.Value, extLen int) error {
if extLen != maxSize && extLen != secondsSize {
return fmt.Errorf("invalid data length: got %d, wanted %d or %d",
extLen, secondsSize, maxSize)
Expand Down Expand Up @@ -333,6 +334,6 @@ func datetimeDecoder(d *msgpack.Decoder, v reflect.Value, extLen int) error {
}

func init() {
msgpack.RegisterExtDecoder(datetimeExtID, Datetime{}, datetimeDecoder)
msgpack.RegisterExtEncoder(datetimeExtID, Datetime{}, datetimeEncoder)
msgpack.RegisterExtDecoder(ExtID, Datetime{}, DecodeExt)
msgpack.RegisterExtEncoder(ExtID, Datetime{}, EncodeExt)
}
35 changes: 19 additions & 16 deletions datetime/interval.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import (
"github.com/vmihailenco/msgpack/v5"
)

const interval_extId = 6
// IntervalExtID represents the Interval MessagePack extension type identifier.
const IntervalExtID = 6

const (
fieldYear = 0
Expand Down Expand Up @@ -74,7 +75,7 @@ func encodeIntervalValue(e *msgpack.Encoder, typ uint64, value int64) (err error
if err == nil {
if value > 0 {
err = e.EncodeUint(uint64(value))
} else if value < 0 {
} else {
err = e.EncodeInt(value)
}
}
Expand Down Expand Up @@ -181,20 +182,22 @@ func decodeInterval(d *msgpack.Decoder, v reflect.Value) (err error) {
return nil
}

func init() {
msgpack.RegisterExtEncoder(interval_extId, Interval{},
func(e *msgpack.Encoder, v reflect.Value) (ret []byte, err error) {
var b bytes.Buffer
func EncodeIntervalExt(_ *msgpack.Encoder, v reflect.Value) (ret []byte, err error) {
var b bytes.Buffer

enc := msgpack.NewEncoder(&b)
if err = encodeInterval(enc, v); err == nil {
ret = b.Bytes()
}
enc := msgpack.NewEncoder(&b)
if err = encodeInterval(enc, v); err == nil {
ret = b.Bytes()
}

return
})
msgpack.RegisterExtDecoder(interval_extId, Interval{},
func(d *msgpack.Decoder, v reflect.Value, extLen int) error {
return decodeInterval(d, v)
})
return
}

func DecodeIntervalExt(d *msgpack.Decoder, v reflect.Value, _ int) error {
return decodeInterval(d, v)
}

func init() {
msgpack.RegisterExtEncoder(IntervalExtID, Interval{}, EncodeIntervalExt)
msgpack.RegisterExtDecoder(IntervalExtID, Interval{}, DecodeIntervalExt)
}
19 changes: 9 additions & 10 deletions decimal/decimal.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package decimal with support of Tarantool's decimal data type.
// Package decimal provides support for Tarantool's decimal data type.
//
// Decimal data type supported in Tarantool since 2.2.
//
Expand Down Expand Up @@ -37,11 +37,10 @@ import (
// - Tarantool module decimal:
// https://www.tarantool.io/en/doc/latest/reference/reference_lua/decimal/

const (
// Decimal external type.
decimalExtID = 1
decimalPrecision = 38
)
// ExtID represents the Decimal MessagePack extension type identifier.
const ExtID = 1

const decimalPrecision = 38

var (
one decimal.Decimal = decimal.NewFromInt(1)
Expand Down Expand Up @@ -71,7 +70,7 @@ func MakeDecimalFromString(src string) (Decimal, error) {
return result, nil
}

func decimalEncoder(e *msgpack.Encoder, v reflect.Value) ([]byte, error) {
func EncodeExt(_ *msgpack.Encoder, v reflect.Value) ([]byte, error) {
dec := v.Interface().(Decimal)
if dec.GreaterThan(maxSupportedDecimal) {
return nil,
Expand All @@ -94,7 +93,7 @@ func decimalEncoder(e *msgpack.Encoder, v reflect.Value) ([]byte, error) {
return bcdBuf, nil
}

func decimalDecoder(d *msgpack.Decoder, v reflect.Value, extLen int) error {
func DecodeExt(d *msgpack.Decoder, v reflect.Value, extLen int) error {
b := make([]byte, extLen)
n, err := d.Buffered().Read(b)
if err != nil {
Expand Down Expand Up @@ -131,6 +130,6 @@ func decimalDecoder(d *msgpack.Decoder, v reflect.Value, extLen int) error {
}

func init() {
msgpack.RegisterExtDecoder(decimalExtID, Decimal{}, decimalDecoder)
msgpack.RegisterExtEncoder(decimalExtID, Decimal{}, decimalEncoder)
msgpack.RegisterExtDecoder(ExtID, Decimal{}, DecodeExt)
msgpack.RegisterExtEncoder(ExtID, Decimal{}, EncodeExt)
}
26 changes: 14 additions & 12 deletions uuid/uuid.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Package with support of Tarantool's UUID data type.
// Package uuid provides support for Tarantool's UUID data type.
//
// UUID data type supported in Tarantool since 2.4.1.
//
Expand All @@ -24,8 +24,8 @@ import (
"github.com/vmihailenco/msgpack/v5"
)

// UUID external type.
const uuid_extID = 2
// ExtID represents the UUID MessagePack extension type identifier.
const ExtID = 2

func encodeUUID(e *msgpack.Encoder, v reflect.Value) error {
id := v.Interface().(uuid.UUID)
Expand Down Expand Up @@ -64,15 +64,17 @@ func decodeUUID(d *msgpack.Decoder, v reflect.Value) error {
return nil
}

func EncodeExt(_ *msgpack.Encoder, v reflect.Value) ([]byte, error) {
u := v.Interface().(uuid.UUID)
return u.MarshalBinary()
}

func DecodeExt(d *msgpack.Decoder, v reflect.Value, _ int) error {
return decodeUUID(d, v)
}

func init() {
msgpack.Register(reflect.TypeOf((*uuid.UUID)(nil)).Elem(), encodeUUID, decodeUUID)
msgpack.RegisterExtEncoder(uuid_extID, uuid.UUID{},
func(e *msgpack.Encoder, v reflect.Value) ([]byte, error) {
uuid := v.Interface().(uuid.UUID)
return uuid.MarshalBinary()
})
msgpack.RegisterExtDecoder(uuid_extID, uuid.UUID{},
func(d *msgpack.Decoder, v reflect.Value, extLen int) error {
return decodeUUID(d, v)
})
msgpack.RegisterExtEncoder(ExtID, uuid.UUID{}, EncodeExt)
msgpack.RegisterExtDecoder(ExtID, uuid.UUID{}, DecodeExt)
}

0 comments on commit aba1b22

Please sign in to comment.