in dax/internal/cbor/lexdecimal.go [222:335]
func decode(reader BytesReader, xormask int) (*Decimal, error) {
b, err := reader.ReadByte()
if err != nil {
return nil, err
}
header := (int(b) ^ xormask) & 0xff
var digitAdjust int
var exponent int
switch header {
case nullHigh & 0xff, nullLow & 0xff:
return nil, nil
case 0x7f, 0x80:
d0 := NewDecimal(big.NewInt(0), 0)
return d0, nil
case 1, 0x7e:
digitAdjust = 999 + 12
v, err := decodeInt32BE(reader)
if err != nil {
return nil, err
}
exponent = v ^ xormask ^ 0x7fffffff
case 0x81, 0xfe:
digitAdjust = 12
v, err := decodeInt32BE(reader)
if err != nil {
return nil, err
}
exponent = v ^ xormask ^ 0x80000000
default:
exponent = (int(b) ^ xormask) & 0xff
if exponent >= 0x82 {
digitAdjust = 12
exponent -= 0xc0
} else {
digitAdjust = 999 + 12
exponent = 0x3f - exponent
}
}
precision := 0
accum := 0
var bits uint = 0
var lastDigit *big.Int
var unscaledValue *big.Int
done := false
for !done {
b, err := reader.ReadByte()
if err != nil {
return nil, err
}
accum = (accum << 8) | ((int(b) ^ xormask) & 0xff)
bits += 8
if bits >= 10 {
digit := (accum >> (bits - 10)) & 0x3ff
switch digit {
case 0, 1023:
lastDigit = lastDigit.Quo(lastDigit, hundred)
if unscaledValue == nil {
unscaledValue = lastDigit
} else {
unscaledValue = unscaledValue.Mul(unscaledValue, ten)
unscaledValue = unscaledValue.Add(unscaledValue, lastDigit)
}
precision += 1
done = true
case 1, 1022:
lastDigit = lastDigit.Quo(lastDigit, ten)
if unscaledValue == nil {
unscaledValue = lastDigit
} else {
unscaledValue = unscaledValue.Mul(unscaledValue, hundred)
unscaledValue = unscaledValue.Add(unscaledValue, lastDigit)
}
precision += 2
done = true
case 2, 1021:
if unscaledValue == nil {
unscaledValue = lastDigit
} else {
unscaledValue = unscaledValue.Mul(unscaledValue, thousand)
unscaledValue = unscaledValue.Add(unscaledValue, lastDigit)
}
precision += 3
done = true
default:
if unscaledValue == nil {
unscaledValue = lastDigit
if unscaledValue != nil {
precision += 3
}
} else {
unscaledValue = unscaledValue.Mul(unscaledValue, thousand)
unscaledValue = unscaledValue.Add(unscaledValue, lastDigit)
precision += 3
}
bits -= 10
lastDigit = big.NewInt(int64(digit - digitAdjust))
}
}
}
scale := precision - exponent
dec := new(Decimal)
dec.SetIntScale(unscaledValue, scale)
return dec, nil
}