func encode()

in dax/internal/cbor/lexdecimal.go [65:186]


func encode(decimal *Decimal, writer BytesWriter, xormask int) (int, error) {
	if decimal.Unscaled().Sign() == 0 {
		if err := writer.WriteByte(byte(0x80 ^ xormask)); err != nil {
			return 0, err
		}
		return 1, nil
	}

	len := 0
	precision := precision(decimal)
	exponent := precision - int(decimal.scale)
	val := decimal.Unscaled()

	if val.Sign() < 0 {
		if exponent >= -0x3e && exponent < 0x3e {
			if err := writer.WriteByte(byte((0x3f - exponent) ^ xormask)); err != nil {
				return 0, err
			}
			len++
		} else {
			if exponent < 0 {
				if err := writer.WriteByte(byte(0x7e ^ xormask)); err != nil {
					return 0, err
				}
			} else {
				if err := writer.WriteByte(byte(1 ^ xormask)); err != nil {
					return 0, err
				}
			}
			if err := encodeInt32BE(exponent^xormask^0x7fffffff, writer); err != nil {
				return 0, err
			}
			len += 5
		}
	} else {
		if exponent >= -0x3e && exponent < 0x3e {
			if err := writer.WriteByte(byte((exponent + 0xc0) ^ xormask)); err != nil {
				return 0, err
			}
			len++
		} else {
			if exponent < 0 {
				if err := writer.WriteByte(byte(0x81 ^ xormask)); err != nil {
					return 0, err
				}
			} else {
				if err := writer.WriteByte(byte(0xfe ^ xormask)); err != nil {
					return 0, err
				}
			}
			if err := encodeInt32BE(exponent^xormask^0x80000000, writer); err != nil {
				return 0, err
			}
			len += 5
		}
	}

	var terminator int
	switch precision % 3 {
	case 0:
		terminator = 2
	case 1:
		terminator = 0
		val = val.Mul(val, hundred)
	case 2:
		terminator = 1
		val = val.Mul(val, ten)
	default:
		terminator = 2
	}

	var digitAdjust int
	if val.Sign() >= 0 {
		digitAdjust = 12
	} else {
		digitAdjust = 999 + 12
		terminator = 1023 - terminator
	}

	pos := ((val.BitLen() + 9) / 10) + 1
	digits := make([]int, pos)
	pos--
	digits[pos] = terminator

	var rem big.Int
	for val.Sign() != 0 {
		val.QuoRem(val, thousand, &rem)

		pos--
		v := int(rem.Int64()) + digitAdjust
		if pos < 0 {
			digits = append([]int{v}, digits...)
		} else {
			digits[pos] = v
		}
	}

	accum := 0
	var bits uint = 0
	for _, v := range digits {
		accum = accum<<10 | v
		bits += 10
		for {
			bits -= 8
			if err := writer.WriteByte(byte((accum >> bits) ^ xormask)); err != nil {
				return 0, err
			}
			len++
			if bits < 8 {
				break
			}
		}
	}

	if bits != 0 {
		if err := writer.WriteByte(byte((accum << uint(8-bits)) ^ xormask)); err != nil {
			return 0, err
		}
		len++
	}
	return len, nil
}