read method
Decrypts [start, end) of the plaintext, touching only the chunks that overlap it.
Implementation
Stream<Uint8List> read(String path, {int start = 0, int? end}) async* {
final UVaultHeader header = await readHeader(path);
final UAead aead = await openFile(header);
final int fileLength = await _backend.length(path) ?? header.length;
final int plain = header.plainLength(fileLength);
final int stop = end == null || end > plain ? plain : end;
if (start >= stop) return;
final int body = fileLength - header.length;
final int chunkCount = body <= 0 ? 0 : (body + header.sealedChunkSize - 1) ~/ header.sealedChunkSize;
for (int index = start ~/ header.chunkSize; index < chunkCount; index++) {
final int plainStart = index * header.chunkSize;
if (plainStart >= stop) break;
final int sealedStart = header.length + index * header.sealedChunkSize;
final int sealedEnd = min(sealedStart + header.sealedChunkSize, fileLength);
final BytesBuilder sealed = BytesBuilder(copy: false);
await for (final Uint8List bytes in _backend.read(path, start: sealedStart, end: sealedEnd)) {
sealed.add(bytes);
}
final Uint8List chunk = await aead.open(header.nonce(index, last: index == chunkCount - 1), sealed.takeBytes());
final int from = max(0, start - plainStart);
final int to = min(chunk.length, stop - plainStart);
if (to > from) yield Uint8List.sublistView(chunk, from, to);
}
}