func testFrac(c *C, v mysql.Decimal) { b := EncodeDecimal([]byte{}, v) _, d, err := DecodeDecimal(b) c.Assert(err, IsNil) c.Assert(v.Equals(d), IsTrue) c.Assert(v.FracDigits(), Equals, d.FracDigits()) c.Assert(v.String(), Equals, d.String()) }
// DecodeDecimal decodes bytes to decimal. // DecodeFloat decodes a float from a byte slice // Decimal decoding: // Byte -> value sign // DecodeInt -> exp value // DecodeBytes -> abs value bytes func DecodeDecimal(b []byte) ([]byte, mysql.Decimal, error) { var ( r = b d mysql.Decimal err error ) // Decode value sign. valSign := int64(r[0]) r = r[1:] if valSign == zeroSign { d, err = mysql.ParseDecimal("0") return r, d, errors.Trace(err) } // Decode exp value. expVal := int64(0) r, expVal, err = DecodeInt(r) if err != nil { return r, d, errors.Trace(err) } // Decode abs value bytes. value := []byte{} if valSign == negativeSign { expVal = -expVal r, value, err = DecodeBytesDesc(r) } else { r, value, err = DecodeBytes(r) } if err != nil { return r, d, errors.Trace(err) } // Set decimal sign and point to value. if valSign == negativeSign { value = append([]byte("-0."), value...) } else { value = append([]byte("0."), value...) } numberDecimal, err := mysql.ParseDecimal(string(value)) if err != nil { return r, d, errors.Trace(err) } expDecimal := mysql.NewDecimalFromInt(1, int32(expVal)) d = numberDecimal.Mul(expDecimal) if expDecimal.Exponent() > 0 { // For int64(3), it will be converted to value=0.3 and exp=1 when doing encode. // Its frac will be changed after we run d = numberDecimal.Mul(expDecimal). // So we try to get frac to the original one. d.SetFracDigits(d.FracDigits() - expDecimal.Exponent()) } return r, d, nil }