decodeFramesIntoBorrowed method
Future<void>
decodeFramesIntoBorrowed(
- BorrowedBytesCodec codec,
- void onFrame(
- FrameBorrowedView frame
- int capacity = 64 * 1024,
- bool allowTrailingBytesAtEof = false,
- bool cancelOnError = false,
Decode frames and deliver them to onFrame as a short-lived
FrameBorrowedView.
This is an opt-in, extremely high-throughput integration point:
it avoids allocating a fresh Uint8List per frame when the codec can
expose bytes directly from the ring buffer.
NOTE: borrowed views are only valid during the callback. If you need to retain bytes, call FrameBorrowedView.toOwnedBytes.
The library fails fast with a StateError if you use the FrameBorrowedView object after the callback returns.
Note: if you store Uint8List views derived from the frame (e.g.
frame.first), that retention generally cannot be detected and may
observe mutated bytes later.
Implementation
Future<void> decodeFramesIntoBorrowed(
BorrowedBytesCodec codec,
void Function(FrameBorrowedView frame) onFrame, {
int capacity = 64 * 1024,
bool allowTrailingBytesAtEof = false,
bool cancelOnError = false,
}) {
final completer = Completer<void>();
final framer = FramerBorrowedBytes(
codec,
capacity: capacity,
);
StreamSubscription<List<int>>? sub;
void finishError(Object error, [StackTrace? st]) {
if (completer.isCompleted) return;
completer.completeError(error, st);
sub?.cancel();
}
sub = listen(
(chunk) {
if (completer.isCompleted) return;
try {
framer.add(chunk, onFrame);
} catch (e, st) {
finishError(e, st);
}
},
onError: (Object e, StackTrace st) {
finishError(e, st);
},
onDone: () {
if (completer.isCompleted) return;
try {
framer.close(
onFrame,
allowTrailingBytesAtEof: allowTrailingBytesAtEof,
);
completer.complete();
} catch (e, st) {
finishError(e, st);
}
},
cancelOnError: cancelOnError,
);
return completer.future;
}