readKeyframeDeltaChain function
Future<KeyframeDeltaState>
readKeyframeDeltaChain(
- FourdgsReadable source,
- List<
FourdgsChunkIndexEntry> index, - FourdgsChunkIndexEntry entry, {
- Map<
int, FourdgsChunkIndexEntry> ? byOffset,
The same chain, fetched by byte range instead of from a resident file.
For the caller that has a FourdgsReadable and no reason to hold the file: a chain is a handful of records, and reading each one as the walk reaches it keeps a chunk resident rather than a scene (AGENTS.md §1). The states this composes are identical to composeKeyframeDeltaChain's — same records, same order, same refusals — so the two are interchangeable and a caller picks by what it already holds.
Implementation
Future<KeyframeDeltaState> readKeyframeDeltaChain(
FourdgsReadable source,
List<FourdgsChunkIndexEntry> index,
FourdgsChunkIndexEntry entry, {
Map<int, FourdgsChunkIndexEntry>? byOffset,
}) async {
final chain = chainFrom(index, entry, byOffset: byOffset);
final int size = await source.size();
KeyframeDeltaState? state;
int? referenceLevel;
for (final link in chain) {
final int expectedOpcode = _stateOpcode(link);
if (link.chunkOffset < 0 ||
link.chunkLength < recordHeaderBytes ||
link.chunkOffset + link.chunkLength > size) {
throw FourdgsMalformedFile(
'the chunk at ${link.chunkOffset} declares a ${link.chunkLength}-byte '
'range outside the $size-byte resource',
);
}
final Uint8List header;
try {
header = await source.read(link.chunkOffset, recordHeaderBytes);
} on RangeError catch (error) {
throw FourdgsMalformedFile(
'the state record at ${link.chunkOffset} could not be read as a '
'$recordHeaderBytes-byte framing header: $error',
);
}
// Price the indexed range only after its fixed-size framing proves it is
// exactly one state record. Otherwise a forged chunk_length can make this
// public range API allocate nearly the whole file before noticing that the
// first record in it was small.
_checkStateRecordHeader(
header,
fileOffset: link.chunkOffset,
rangeLength: link.chunkLength,
expectedOpcode: expectedOpcode,
);
final Uint8List blob;
try {
blob = await source.read(link.chunkOffset, link.chunkLength);
} on RangeError catch (error) {
throw FourdgsMalformedFile(
'the chunk at ${link.chunkOffset} could not be read as its declared '
'${link.chunkLength}-byte range: $error',
);
}
final composed = _composeLink(
state,
_recordContent(
blob,
0,
link.chunkLength,
expectedOpcode: expectedOpcode,
fileOffset: link.chunkOffset,
),
link,
referenceLevel: referenceLevel,
);
state = composed.state;
referenceLevel = composed.level;
}
return _composed(state);
}