decode method
Decode ABI encoded byte array to dart values from ABI type schemes @param encoded byte array of ABI encoding @throws IllegalArgumentException if encoded byte array cannot match with ABI encoding rules
Implementation
@override
Object decode(Uint8List encoded) {
final dynamicSeg = <int>[];
final valuePartition = <Uint8List>[];
var iterIndex = 0;
for (var i = 0; i < childTypes.length; i++) {
if (childTypes[i].isDynamic()) {
if (iterIndex + AbiType.ABI_DYNAMIC_HEAD_BYTE_LEN > encoded.length) {
throw ArgumentError(
'ill formed tuple dynamic typed element encoding: not enough bytes for index');
}
final encodedIndex = Uint8List(AbiType.ABI_DYNAMIC_HEAD_BYTE_LEN);
Array.copy(encoded, iterIndex, encodedIndex, 0,
AbiType.ABI_DYNAMIC_HEAD_BYTE_LEN);
final index = BigIntEncoder.decodeBytesToUint(encodedIndex).toInt();
dynamicSeg.add(index);
valuePartition.add(Uint8List.fromList([]));
iterIndex += AbiType.ABI_DYNAMIC_HEAD_BYTE_LEN;
} else if (childTypes[i] is TypeBool) {
final childTypeArr = List<AbiType>.from(childTypes);
var before = AbiType.findBoolLR(childTypeArr, i, -1);
var after = AbiType.findBoolLR(childTypeArr, i, 1);
if (before % 8 != 0) {
throw ArgumentError('expected bool number mod 8 == 0');
}
after = min(after, 7);
for (var boolIndex = 0; boolIndex <= after; boolIndex++) {
var boolMask = (0x80 >> boolIndex);
var append = ((encoded[iterIndex] & boolMask) != 0) ? 0x80 : 0x00;
valuePartition.add(Uint8List.fromList([append]));
}
i += after;
iterIndex++;
} else {
var expectedLen = childTypes[i].byteLength();
if (iterIndex + expectedLen > encoded.length) {
throw ArgumentError(
'ill formed tuple static typed element encoding: not enough bytes');
}
final partition = Uint8List(expectedLen);
Array.copy(encoded, iterIndex, partition, 0, expectedLen);
valuePartition.add(partition);
iterIndex += expectedLen;
}
if (i != childTypes.length - 1 && iterIndex >= encoded.length) {
throw ArgumentError('input bytes not enough to decode');
}
}
if (dynamicSeg.isNotEmpty) {
dynamicSeg.add(encoded.length);
iterIndex = encoded.length;
}
if (iterIndex < encoded.length) {
throw ArgumentError('input bytes not fully consumed');
}
var indexTemp = -1;
for (var v in dynamicSeg) {
if (v >= indexTemp) {
indexTemp = v;
} else {
throw ArgumentError(
'dynamic segments should display a [l, r] scope where l <= r');
}
}
var segIndex = 0;
for (var i = 0; i < childTypes.length; i++) {
if (childTypes[i].isDynamic()) {
final length = dynamicSeg[segIndex + 1] - dynamicSeg[segIndex];
final partition = Uint8List(length);
Array.copy(encoded, dynamicSeg[segIndex], partition, 0, length);
valuePartition[i] = partition;
segIndex++;
}
}
final values =
List<Object?>.filled(childTypes.length, null, growable: false);
for (var i = 0; i < childTypes.length; i++) {
values[i] = childTypes[i].decode(valuePartition[i]);
}
return values.whereNotNull().toList();
}