// makeDecimalFromMandE reconstructs the decimal from the mantissa M and // exponent E. func makeDecimalFromMandE(negative bool, e int, m []byte, tmp []byte) decimal.Decimal { // ±dddd. b := tmp[:0] if n := len(m)*2 + 1; cap(b) < n { b = make([]byte, 0, n) } if negative { b = append(b, '-') } for i, v := range m { t := int(v) if i == len(m) { t-- } t /= 2 b = append(b, byte(t/10)+'0', byte(t%10)+'0') } // We unsafely convert the []byte to a string to avoid the usual allocation // when converting to a string. bi := new(big.Int) bi, ok := bi.SetString(*(*string)(unsafe.Pointer(&b)), 10) if !ok { panic("could not set big.Int's string value") } exp := 2*e - len(b) if negative { exp++ } return decimal.NewFromBigInt(bi, int32(exp)) }
// GetDecimal decodes a decimal value from the bytes of the receiver. If the // tag is not DECIMAL an error will be returned. func (v Value) GetDecimal() (decimal.Decimal, error) { if tag := v.GetTag(); tag != ValueType_DECIMAL { return decimal.Decimal{}, fmt.Errorf("value type is not %s: %s", ValueType_DECIMAL, tag) } data := v.dataBytes() i, n := binary.Varint(data) if n <= 0 { return decimal.Decimal{}, fmt.Errorf("int64 varint decoding failed: %d", n) } bi := new(big.Int) err := bi.GobDecode(data[n:]) if err != nil { return decimal.Decimal{}, err } return decimal.NewFromBigInt(bi, int32(i)), nil }