encode method

  1. @override
Uint8List encode(
  1. dynamic obj
)
override

Encode values with ABI rules based on the ABI type schemes @return byte[] of ABI encoding @throws IllegalArgumentException if encoder cannot infer the type from obj

Implementation

@override
Uint8List encode(dynamic obj) {
  if (obj is! List) {
    throw ArgumentError(
        'cannot infer type for unify array/list-like object to object array');
  }

  if (obj.length != childTypes.length) {
    throw ArgumentError(
        'abi tuple child type size != abi tuple element value size');
  }

  final tupleValues = obj;
  final tupleTypes = List<AbiType>.from(childTypes);
  final heads =
      List<Uint8List>.filled(tupleTypes.length, Uint8List.fromList([]));
  final tails =
      List<Uint8List>.filled(tupleTypes.length, Uint8List.fromList([]));

  final dynamicIndex = <int>{};
  for (var i = 0; i < tupleTypes.length; i++) {
    var currType = tupleTypes[i];
    var currValue = tupleValues[i];
    Uint8List currHead, currTail;
    if (currType.isDynamic()) {
      currHead = Uint8List.fromList([0x00, 0x00]);
      currTail = currType.encode(currValue);
      dynamicIndex.add(i);
    } else if (currType is TypeBool) {
      var before = AbiType.findBoolLR(tupleTypes, i, -1);
      var after = AbiType.findBoolLR(tupleTypes, i, 1);
      if (before % 8 != 0) {
        throw ArgumentError('expected before has number of bool mod 8 == 0');
      }

      after = min(after, 7);
      var compressed = 0;
      for (var boolIndex = 0; boolIndex <= after; boolIndex++) {
        final result = tupleValues[i + boolIndex] as bool;
        if (result) {
          compressed |= 1 << (7 - boolIndex);
        }
      }

      currHead = Uint8List.fromList([compressed]);
      currTail = Uint8List.fromList([]);
      i += after;
    } else {
      currHead = currType.encode(currValue);
      currTail = Uint8List.fromList([]);
    }
    heads[i] = currHead;
    tails[i] = currTail;
  }

  var headLength = 0;
  for (var h in heads) {
    headLength += h.length;
  }

  var tailCurrLength = 0;
  for (var i = 0; i < heads.length; i++) {
    if (dynamicIndex.contains(i)) {
      var headValue = headLength + tailCurrLength;
      if (headValue >= (1 << 16)) {
        throw ArgumentError('encoding error: byte length >= 2^16');
      }
      heads[i] = BigIntEncoder.encodeUintToBytes(
          BigInt.from(headValue), AbiType.ABI_DYNAMIC_HEAD_BYTE_LEN);
    }
    tailCurrLength += tails[i].length;
  }

  final buffer = <int>[];
  for (var h in heads) {
    buffer.addAll(h);
  }

  for (var t in tails) {
    buffer.addAll(t);
  }

  return Uint8List.fromList(buffer);
}