convertDecimalToBinary static method

BsonBinary convertDecimalToBinary(
  1. Decimal? decimal
)

Implementation

static BsonBinary convertDecimalToBinary(Decimal? decimal) {
  if (decimal == null) {
    // Decimal does not manage NaN
    return BsonBinary.fromHexString('0000000000000000000000000000007c');
  } else if (decimal == infinityValue) {
    // Decimal does not manage infinity, this is a conventional value
    return BsonBinary.fromHexString('00000000000000000000000000000078');
  } else if (decimal == -infinityValue) {
    // Decimal does not manage -infinity, this is a conventional value
    return BsonBinary.fromHexString('000000000000000000000000000000f8');
  } else if (decimal == Decimal.zero) {
    return BsonBinary.fromHexString('00000000000000000000000000004030');
  } else if (decimal.hasFinitePrecision &&
      // if bigger than one (i.e at least one integer digit)
      // we could have a lot of unnecessary trailing zeros calculated
      // in the precision.
      decimal < _d1 &&
      decimal.significandLength > 34) {
    // Return zero
    return BsonBinary.fromHexString('00000000000000000000000000004030');
  }

  String res;
  if (decimal.hasFinitePrecision) {
    res = decimal.toStringAsFixed(decimal.scaleExt);
  } else {
    res = decimal.toStringAsPrecisionFast(34);
  }
  var exponent = extractExponent(res);
  var significand = extractSignificand(res);

  // Significand greater or equal to 10^34 - 1 must be considered as 0
  if (significand > maxSignificand) {
    significand = Decimal.zero;
  }

  // The exponent calculated implies that the significand is of the form
  // i.ddddddd, but our significand must be an integer.
  // plus 6176 (exp 0, lower is negative)
  var biasedExponent = exponent + 6176;

  // encoding as case 1 number (first bit of the combination field not '11')
  // because the minimum value of the case 2 (2^114) is higher than
  // the max allowed value (10^34-1)
  var highSignificand = Decimal.fromBigInt(significand ~/ maxUInt64);
  var lowSignificand = significand - (highSignificand * maxUInt64);
  // Needed because we are using Int instead of UInt
  if (lowSignificand >= maxInt64) {
    lowSignificand -= maxUInt64;
  }

  var lowInt = Int64.parseRadix(lowSignificand.toString(), 10);
  var highInt = Int64.parseRadix(highSignificand.toString(), 10);
  highInt += (Int64(biasedExponent) << 49);
  if (decimal.isNegative) {
    highInt |= signMask;
  }
  return BsonBinary(16)
    ..writeFixInt64(lowInt)
    ..writeFixInt64(highInt);
}