Skip to content

Commit 740a0c9

Browse files
committed
Switch to MarshalMsgpack/UnmarshalMsgpack [TO SQUASH]
1 parent 317ec1f commit 740a0c9

File tree

2 files changed

+38
-55
lines changed

2 files changed

+38
-55
lines changed

decimal/decimal.go

Lines changed: 18 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ package decimal
1717

1818
import (
1919
"fmt"
20-
"reflect"
2120

2221
"github.com/shopspring/decimal"
2322
"gopkg.in/vmihailenco/msgpack.v2"
@@ -38,28 +37,30 @@ const (
3837
DecimalPrecision = 38
3938
)
4039

41-
func encodeDecimal(e *msgpack.Encoder, v reflect.Value) error {
42-
number := v.Interface().(decimal.Decimal)
40+
type DecNumber struct {
41+
decimal.Decimal
42+
}
43+
44+
var _ msgpack.Marshaler = (*DecNumber)(nil)
45+
var _ msgpack.Unmarshaler = (*DecNumber)(nil)
46+
47+
func (decNum *DecNumber) MarshalMsgpack() ([]byte, error) {
4348
one := decimal.NewFromInt(1)
4449
maxSupportedDecimal := decimal.New(1, DecimalPrecision).Sub(one) // 10^DecimalPrecision - 1
4550
minSupportedDecimal := maxSupportedDecimal.Neg().Sub(one) // -10^DecimalPrecision - 1
46-
if number.GreaterThan(maxSupportedDecimal) {
47-
return fmt.Errorf("msgpack: decimal number is bigger than maximum supported number (10^%d - 1)", DecimalPrecision)
51+
if decNum.GreaterThan(maxSupportedDecimal) {
52+
return nil, fmt.Errorf("msgpack: decimal number is bigger than maximum supported number (10^%d - 1)", DecimalPrecision)
4853
}
49-
if number.LessThan(minSupportedDecimal) {
50-
return fmt.Errorf("msgpack: decimal number is lesser than minimum supported number (-10^%d - 1)", DecimalPrecision)
54+
if decNum.LessThan(minSupportedDecimal) {
55+
return nil, fmt.Errorf("msgpack: decimal number is lesser than minimum supported number (-10^%d - 1)", DecimalPrecision)
5156
}
5257

53-
strBuf := number.String()
58+
strBuf := decNum.String()
5459
bcdBuf, err := EncodeStringToBCD(strBuf)
5560
if err != nil {
56-
return fmt.Errorf("msgpack: can't encode string (%s) to a BCD buffer: %w", strBuf, err)
61+
return nil, fmt.Errorf("msgpack: can't encode string (%s) to a BCD buffer: %w", strBuf, err)
5762
}
58-
if _, err = e.Writer().Write(bcdBuf); err != nil {
59-
return fmt.Errorf("msgpack: can't write bytes to encoder writer: %w", err)
60-
}
61-
62-
return nil
63+
return bcdBuf, nil
6364
}
6465

6566
// Decimal values can be encoded to fixext MessagePack, where buffer
@@ -70,42 +71,20 @@ func encodeDecimal(e *msgpack.Encoder, v reflect.Value) error {
7071
// +--------+-------------------+------------+===============+
7172
// | MP_EXT | length (optional) | MP_DECIMAL | PackedDecimal |
7273
// +--------+-------------------+------------+===============+
73-
//
74-
// Before reading a buffer with encoded decimal number (PackedDecimal) we need
75-
// to allocate it, but before reading we don't know it's exact size.
76-
// msgpack.Decoder in msgpack v2 package pass a buffer with PackedDecimal bytes
77-
// and there is no possibility to read length in advance. For example on
78-
// attempt to decode MessagePack buffer c7030100088c (88) msgpack pass 00088a
79-
// to decodeDecimal() and length field value (03) is unavailable nor in buffer
80-
// nor via decoder interface.
81-
//
82-
// To solve a problem we allocate a buffer with maximum size (it is 32 bytes
83-
// and it is corresponds to ext32 MessagePack), then read encoded decimal to a
84-
// buffer and finally cut off unused part.
85-
func decodeDecimal(d *msgpack.Decoder, v reflect.Value) error {
86-
var maxBytesCount int = 32
87-
b := make([]byte, maxBytesCount)
88-
89-
readBytes, err := d.Buffered().Read(b)
90-
if err != nil {
91-
return fmt.Errorf("msgpack: can't read bytes on decimal decode: %w", err)
92-
}
93-
b = b[:readBytes]
74+
func (decNum *DecNumber) UnmarshalMsgpack(b []byte) error {
9475
digits, err := DecodeStringFromBCD(b)
9576
if err != nil {
9677
return fmt.Errorf("msgpack: can't decode string from BCD buffer (%x): %w", b, err)
9778
}
9879
dec, err := decimal.NewFromString(digits)
80+
*decNum = DecNumber{dec}
9981
if err != nil {
10082
return fmt.Errorf("msgpack: can't encode string (%s) to a decimal number: %w", digits, err)
10183
}
10284

103-
v.Set(reflect.ValueOf(dec))
104-
10585
return nil
10686
}
10787

10888
func init() {
109-
msgpack.Register(reflect.TypeOf((*decimal.Decimal)(nil)).Elem(), encodeDecimal, decodeDecimal)
110-
msgpack.RegisterExt(decimalExtID, (*decimal.Decimal)(nil))
89+
msgpack.RegisterExt(decimalExtID, &DecNumber{})
11190
}

decimal/decimal_test.go

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ var space = "testDecimal"
4040
var index = "primary"
4141

4242
type TupleDecimal struct {
43-
number decimal.Decimal
43+
number DecNumber
4444
}
4545

4646
func (t *TupleDecimal) EncodeMsgpack(e *msgpack.Encoder) error {
4747
if err := e.EncodeSliceLen(1); err != nil {
4848
return err
4949
}
50-
return e.EncodeValue(reflect.ValueOf(t.number))
50+
return e.EncodeValue(reflect.ValueOf(&t.number))
5151
}
5252

5353
func (t *TupleDecimal) DecodeMsgpack(d *msgpack.Decoder) error {
@@ -64,7 +64,7 @@ func (t *TupleDecimal) DecodeMsgpack(d *msgpack.Decoder) error {
6464
if err != nil {
6565
return err
6666
}
67-
t.number = res.(decimal.Decimal)
67+
t.number = res.(DecNumber)
6868

6969
return nil
7070
}
@@ -134,15 +134,17 @@ func TestMPEncodeDecode(t *testing.T) {
134134
t.Fatal(err)
135135
}
136136
var buf []byte
137-
tuple := TupleDecimal{number: decNum}
137+
tuple := TupleDecimal{number: DecNumber{decNum}}
138138
if buf, err = msgpack.Marshal(&tuple); err != nil {
139139
t.Fatalf("Failed to encode decimal number '%s' to a MessagePack buffer: %s", testcase.numString, err)
140140
}
141141
var v TupleDecimal
142142
if err = msgpack.Unmarshal(buf, &v); err != nil {
143143
t.Fatalf("Failed to decode MessagePack buffer '%x' to a decimal number: %s", buf, err)
144144
}
145-
if !decNum.Equal(v.number) {
145+
if !decNum.Equal(v.number.Decimal) {
146+
fmt.Println(decNum)
147+
fmt.Println(v.number)
146148
t.Fatal("Decimal numbers are not equal")
147149
}
148150
})
@@ -235,7 +237,7 @@ func TestEncodeStringToBCDIncorrectNumber(t *testing.T) {
235237
func TestEncodeMaxNumber(t *testing.T) {
236238
referenceErrMsg := "msgpack: decimal number is bigger than maximum supported number (10^38 - 1)"
237239
decNum := decimal.New(1, DecimalPrecision) // // 10^DecimalPrecision
238-
tuple := TupleDecimal{number: decNum}
240+
tuple := TupleDecimal{number: DecNumber{decNum}}
239241
_, err := msgpack.Marshal(&tuple)
240242
if err == nil {
241243
t.Fatalf("It is possible to encode a number unsupported by Tarantool")
@@ -249,12 +251,14 @@ func TestEncodeMinNumber(t *testing.T) {
249251
referenceErrMsg := "msgpack: decimal number is lesser than minimum supported number (-10^38 - 1)"
250252
two := decimal.NewFromInt(2)
251253
decNum := decimal.New(1, DecimalPrecision).Neg().Sub(two) // -10^DecimalPrecision - 2
252-
tuple := TupleDecimal{number: decNum}
254+
tuple := TupleDecimal{number: DecNumber{decNum}}
253255
_, err := msgpack.Marshal(&tuple)
254256
if err == nil {
255257
t.Fatalf("It is possible to encode a number unsupported by Tarantool")
256258
}
257259
if err.Error() != referenceErrMsg {
260+
fmt.Println("Actual message: ", err.Error())
261+
fmt.Println("Expected message: ", referenceErrMsg)
258262
t.Fatalf("Incorrect error message on attempt to encode number unsupported by Tarantool")
259263
}
260264
}
@@ -266,7 +270,7 @@ func benchmarkMPEncodeDecode(b *testing.B, src decimal.Decimal, dst interface{})
266270
var buf []byte
267271
var err error
268272
for i := 0; i < b.N; i++ {
269-
tuple := TupleDecimal{number: src}
273+
tuple := TupleDecimal{number: DecNumber{src}}
270274
if buf, err = msgpack.Marshal(&tuple); err != nil {
271275
b.Fatal(err)
272276
}
@@ -348,7 +352,7 @@ func tupleValueIsDecimal(t *testing.T, tuples []interface{}, number decimal.Deci
348352
if len(tpl) != 1 {
349353
t.Fatalf("Unexpected return value body (tuple len)")
350354
}
351-
if val, ok := tpl[0].(decimal.Decimal); !ok || !val.Equal(number) {
355+
if val, ok := tpl[0].(DecNumber); !ok || !val.Equal(number) {
352356
t.Fatalf("Unexpected return value body (tuple 0 field)")
353357
}
354358
}
@@ -441,7 +445,7 @@ func TestSelect(t *testing.T) {
441445
t.Fatalf("Failed to prepare test decimal: %s", err)
442446
}
443447

444-
resp, err := conn.Insert(space, []interface{}{number})
448+
resp, err := conn.Insert(space, []interface{}{&DecNumber{number}})
445449
if err != nil {
446450
t.Fatalf("Decimal insert failed: %s", err)
447451
}
@@ -452,7 +456,7 @@ func TestSelect(t *testing.T) {
452456

453457
var offset uint32 = 0
454458
var limit uint32 = 1
455-
resp, err = conn.Select(space, index, offset, limit, IterEq, []interface{}{number})
459+
resp, err = conn.Select(space, index, offset, limit, IterEq, []interface{}{&DecNumber{number}})
456460
if err != nil {
457461
t.Fatalf("Decimal select failed: %s", err.Error())
458462
}
@@ -461,7 +465,7 @@ func TestSelect(t *testing.T) {
461465
}
462466
tupleValueIsDecimal(t, resp.Data, number)
463467

464-
resp, err = conn.Delete(space, index, []interface{}{number})
468+
resp, err = conn.Delete(space, index, []interface{}{&DecNumber{number}})
465469
if err != nil {
466470
t.Fatalf("Decimal delete failed: %s", err)
467471
}
@@ -474,7 +478,7 @@ func assertInsert(t *testing.T, conn *Connection, numString string) {
474478
t.Fatalf("Failed to prepare test decimal: %s", err)
475479
}
476480

477-
resp, err := conn.Insert(space, []interface{}{number})
481+
resp, err := conn.Insert(space, []interface{}{&DecNumber{number}})
478482
if err != nil {
479483
t.Fatalf("Decimal insert failed: %s", err)
480484
}
@@ -483,7 +487,7 @@ func assertInsert(t *testing.T, conn *Connection, numString string) {
483487
}
484488
tupleValueIsDecimal(t, resp.Data, number)
485489

486-
resp, err = conn.Delete(space, index, []interface{}{number})
490+
resp, err = conn.Delete(space, index, []interface{}{&DecNumber{number}})
487491
if err != nil {
488492
t.Fatalf("Decimal delete failed: %s", err)
489493
}
@@ -515,7 +519,7 @@ func TestReplace(t *testing.T) {
515519
t.Fatalf("Failed to prepare test decimal: %s", err)
516520
}
517521

518-
respRep, errRep := conn.Replace(space, []interface{}{number})
522+
respRep, errRep := conn.Replace(space, []interface{}{&DecNumber{number}})
519523
if errRep != nil {
520524
t.Fatalf("Decimal replace failed: %s", errRep)
521525
}
@@ -524,7 +528,7 @@ func TestReplace(t *testing.T) {
524528
}
525529
tupleValueIsDecimal(t, respRep.Data, number)
526530

527-
respSel, errSel := conn.Select(space, index, 0, 1, IterEq, []interface{}{number})
531+
respSel, errSel := conn.Select(space, index, 0, 1, IterEq, []interface{}{&DecNumber{number}})
528532
if errSel != nil {
529533
t.Fatalf("Decimal select failed: %s", errSel)
530534
}

0 commit comments

Comments
 (0)