length method

  1. @override
Future<ResourceTry<int>> length()

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!;
}