toBytes static method

List<int> toBytes(
  1. BigInt val, {
  2. int? length,
  3. Endian byteOrder = Endian.big,
  4. bool sign = false,
})

Converts a BigInt to a byte list with the given length and byte order. Pass sign = true to encode negative values as two's complement.

Implementation

static List<int> toBytes(
  BigInt val, {
  int? length,
  Endian byteOrder = Endian.big,
  bool sign = false,
}) {
  if (val.isNegative && !sign) {
    throw ArgumentException.invalidOperationArguments(
      'toBytes',
      name: 'val',
      reason: 'Negative value requires sign: true.',
    );
  }

  // Size against the magnitude, but with the same `sign` convention
  // that will actually be used to encode — this is the fix.
  length ??= bitlengthInBytes(
    val.isNegative ? (-val - BigInt.one) : val,
    sign: sign,
  );

  BigInt unsigned = val;
  if (val.isNegative) {
    // Two's complement over `length` bytes: (2^(8*length) + val).
    unsigned = (BigInt.one << (length * 8)) + val;
  }

  if (unsigned.bitLength > length * 8) {
    throw ArgumentException.invalidOperationArguments(
      'toBytes',
      name: 'length',
      reason: 'Value does not fit in $length byte(s).',
    );
  }

  final byteList = List<int>.filled(length, 0);
  for (var i = 0; i < length; i++) {
    byteList[length - i - 1] = (unsigned & BinaryOps.maskBig8).toInt();
    unsigned >>= 8;
  }

  return byteOrder == Endian.little ? byteList.reversed.toList() : byteList;
}