diff --git a/decimal_gen.go b/decimal_gen.go index 1e07ee4..117bf0e 100644 --- a/decimal_gen.go +++ b/decimal_gen.go @@ -1,35 +1,250 @@ package decimal -// Code generated by github.com/tinylib/msgp DO NOT EDIT. - import ( - "github.com/tinylib/msgp/msgp" + "errors" ) +// const ( +// first3 = 0xe0 +// last5 = 0x1f +// +// mfixstr uint8 = 0xa0 +// mstr8 uint8 = 0xd9 +// mstr16 uint8 = 0xda +// mstr32 uint8 = 0xdb +// +// stringPrefixSize = 5 +// ) + +var ( + errShortBytes = errors.New("msgp: too few bytes left to read object") + //bigEndian = binary.BigEndian +) + + // MarshalMsg implements msgp.Marshaler func (z Decimal) MarshalMsg(b []byte) (o []byte, err error) { - o = msgp.Require(b, z.Msgsize()) - o = msgp.AppendFloat64(o, z.InexactFloat64()) - return + o = require(b, z.Msgsize()) + str := z.String() + sz := len(str) + if sz > 30 { + sz = 30 + if str[29] == '.' { + sz = 29 + } + + str = str[:sz] + } + + o, n := ensure(b, 1+sz) + o[n] = byte(0xa0 | sz) + n++ + + return o[:n+copy(o[n:], str)], nil } // UnmarshalMsg implements msgp.Unmarshaler -func (z *Decimal) UnmarshalMsg(bts []byte) (o []byte, err error) { - { - var zb0001 float64 - zb0001, bts, err = msgp.ReadFloat64Bytes(bts) - if err != nil { - err = msgp.WrapError(err) - return - } - (*z) = NewFromFloat(zb0001) +func (z *Decimal) UnmarshalMsg(b []byte) (o []byte, err error) { + l := len(b) + if l < 1 { + return nil, errShortBytes + } + + sz := int(b[0] & 0x1f) + if len(b[1:]) < sz { + err = errShortBytes + return + } + if *z, err = NewFromString(string(b[1 : sz+1])); err == nil { + o = b[sz:] } - o = bts return } // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message -func (z Decimal) Msgsize() (s int) { - s = msgp.Float64Size - return +func (z Decimal) Msgsize() int { + return 31 } +// +// // MarshalMsg implements msgp.Marshaler +// func (z Decimal) MarshalMsg(b []byte) (o []byte, err error) { +// o = require(b, z.Msgsize()) +// o = appendString(o, z.String()) +// return +// } +// +// // UnmarshalMsg implements msgp.Unmarshaler +// func (z *Decimal) UnmarshalMsg(b []byte) (o []byte, err error) { +// v, bts, err := readString(b) +// if err != nil { +// return +// } +// d, err := NewFromString(string(v)) +// if err == nil { +// *z = d +// o = bts +// } +// +// return +// } +// +// // Msgsize returns an upper bound estimate of the number of bytes occupied by the serialized message +// func (z Decimal) Msgsize() (s int) { +// s = stringPrefixSize + len(z.String()) +// return +// } + +// Require ensures that cap(old)-len(old) >= extra. +func require(old []byte, extra int) []byte { + l := len(old) + c := cap(old) + r := l + extra + if c >= r { + return old + } else if l == 0 { + return make([]byte, 0, extra) + } + // the new size is the greater + // of double the old capacity + // and the sum of the old length + // and the number of new bytes + // necessary. + c <<= 1 + if c < r { + c = r + } + n := make([]byte, l, c) + copy(n, old) + return n +} + +// ensure 'sz' extra bytes in 'b' btw len(b) and cap(b) +func ensure(b []byte, sz int) ([]byte, int) { + l := len(b) + c := cap(b) + if c-l < sz { + o := make([]byte, (2*c)+sz) // exponential growth + n := copy(o, b) + return o[:n+sz], n + } + return b[:l+sz], l +} + +// // AppendString appends a string as a MessagePack 'str' to the slice +// func appendString(b []byte, s string) []byte { +// sz := len(s) +// var n int +// var o []byte +// switch { +// case sz <= 31: +// o, n = ensure(b, 1+sz) +// o[n] = wfixstr(uint8(sz)) +// n++ +// case sz <= math.MaxUint8: +// o, n = ensure(b, 2+sz) +// prefixu8(o[n:], mstr8, uint8(sz)) +// n += 2 +// case sz <= math.MaxUint16: +// o, n = ensure(b, 3+sz) +// prefixu16(o[n:], mstr16, uint16(sz)) +// n += 3 +// default: +// o, n = ensure(b, 5+sz) +// prefixu32(o[n:], mstr32, uint32(sz)) +// n += 5 +// } +// return o[:n+copy(o[n:], s)] +// } +// +// func wfixstr(u uint8) byte { +// return (u & last5) | mfixstr +// } +// +// // write prefix and uint8 +// func prefixu8(b []byte, pre byte, sz uint8) { +// b[0] = pre +// b[1] = sz +// } +// +// // write prefix and big-endian uint16 +// func prefixu16(b []byte, pre byte, sz uint16) { +// b[0] = pre +// b[1] = byte(sz >> 8) +// b[2] = byte(sz) +// } +// +// // write prefix and big-endian uint32 +// func prefixu32(b []byte, pre byte, sz uint32) { +// b[0] = pre +// b[1] = byte(sz >> 24) +// b[2] = byte(sz >> 16) +// b[3] = byte(sz >> 8) +// b[4] = byte(sz) +// } +// +// // readString reads a messagepack string field +// // without copying. The returned []byte points +// // to the same memory as the input slice. +// // Possible errors: +// // - ErrShortBytes (b not long enough) +// func readString(b []byte) (v []byte, o []byte, err error) { +// l := len(b) +// if l < 1 { +// return nil, nil, ErrShortBytes +// } +// +// lead := b[0] +// var read int +// +// if isfixstr(lead) { +// read = int(rfixstr(lead)) +// b = b[1:] +// } else { +// switch lead { +// case mstr8: +// if l < 2 { +// err = ErrShortBytes +// return +// } +// read = int(b[1]) +// b = b[2:] +// +// case mstr16: +// if l < 3 { +// err = ErrShortBytes +// return +// } +// read = int(bigEndian.Uint16(b[1:])) +// b = b[3:] +// +// case mstr32: +// if l < 5 { +// err = ErrShortBytes +// return +// } +// read = int(bigEndian.Uint32(b[1:])) +// b = b[5:] +// +// default: +// err = fmt.Errorf(`msgp: attempted to decode type 'str' with method for %d`, lead) +// return +// } +// } +// +// if len(b) < read { +// err = ErrShortBytes +// return +// } +// +// v = b[0:read] +// o = b[read:] +// return +// } +// +// func isfixstr(b byte) bool { +// return b&first3 == mfixstr +// } +// +// func rfixstr(b byte) uint8 { +// return b & last5 +// } diff --git a/decimal_test.go b/decimal_test.go index b53b68b..0573369 100644 --- a/decimal_test.go +++ b/decimal_test.go @@ -2,6 +2,7 @@ package decimal import ( "database/sql/driver" + "encoding/base64" "encoding/json" "encoding/xml" "fmt" @@ -3316,3 +3317,18 @@ func ExampleNewFromFloat() { //0.123123123123123 //-10000000000000 } + +func TestMsgPack(t *testing.T) { + d, _ := NewFromString("79228162514264337593543950334.123222") + out, err := d.MarshalMsg(nil) + if err != nil { + t.Fatal(err) + } + t.Log(base64.StdEncoding.EncodeToString(out)) + + var d2 = Decimal{} + if _, err = d2.UnmarshalMsg(out); err != nil { + t.Fatal(err) + } + t.Log(d2.String()) +} diff --git a/go.mod b/go.mod index 96cfa8d..bead680 100644 --- a/go.mod +++ b/go.mod @@ -1,5 +1,3 @@ module github.com/piyongcai/decimal go 1.13 - -require github.com/tinylib/msgp v1.1.6