length method
Returns data length from metadata if available, or calculated from reading the bytes otherwise.
This value must be treated as a hint, as it might not reflect the actual bytes length. To get the real length, you need to read the whole resource.
Implementation
@override
Future<ResourceTry<int>> length() async {
if (_length != null) {
return _length!;
}
_length = await resource
.length()
.then((res) => res.flatMapWaitResource((length) async {
if (length < 2 * aesBlockSize) {
throw Exception("Invalid CBC-encrypted stream");
}
int readOffset = length - (2 * aesBlockSize);
return await resource
.read(range: IntRange(readOffset, length))
.then((res) => res.mapWait((bytes) async {
ByteData decryptedBytes = (await license.decrypt(bytes))
.getOrElse((failure) => throw Exception(
"Can't decrypt trailing size of CBC-encrypted stream $failure"));
return length -
aesBlockSize - // Minus IV or previous block
(aesBlockSize - decryptedBytes.lengthInBytes) %
aesBlockSize; // Minus padding part
}));
}));
return _length!;
}