func decode()

in dax/internal/cbor/lexdecimal.go [223:336]


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
}