- From: Mattias Buelens <notifications@github.com>
- Date: Mon, 12 Jul 2021 15:15:44 -0700
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1143@github.com>
As suggested in [#1019 (comment)](https://github.com/whatwg/streams/issues/1019#issuecomment-565499158), developers may want to read into a BYOB buffer until it is *completely filled* (instead of only *partially* filling it with however many bytes the underlying source provides). We already have [an example for this](https://streams.spec.whatwg.org/commit-snapshots/cada8129edcc4803b2878a7a3f5e1d8325dc0c23/#example-manual-read-bytes) with a `readInto()` helper function, but it may be worth integrating this into the standard itself for better ergonomics and/or optimization opportunities.
Concretely, I suggest we extend `ReadableStreamBYOBReader`:
```
interface ReadableStreamBYOBReader {
Promise<ReadableStreamBYOBReadResult> readFully(ArrayBufferView view);
};
```
This method performs a BYOB read into `view`:
* If the underlying source responds with `n` bytes where `n < view.byteLength`, then the stream will immediately start pulling again with the "remainder" of `view` (i.e. `view.subarray(n)`, assuming `view` is a `Uint8Array`).
* If the underlying source responds with `n` bytes where `n === view.byteLength`, then the method fulfills with `{ done: false, value }` where `value` is the completely filled view.
* If the underlying source closes before the view is completely filled, then the method fulfills with `{ done: true, value }` where `value` is the (partially) filled view.
* If the underlying source cancels, then the method returns with `{ done: true, value: undefined }`, like with regular BYOB reads.
Some remarks:
* We can't return a `Promise<ArrayBufferView>`, because then you wouldn't know if the stream is closed. Also, this wouldn't work if the stream is cancelled... unless we're okay with returning `Promise<undefined>` in that case (which I personally don't find very pretty).
* We have to be very careful with how we create a pull-into descriptor for the remainder. There may already be *other* pull-into descriptors into the queue, for example a user could do this:
```javascript
let pullCount = 0;
const rs = new ReadableStream({
type: 'bytes',
pull(c) {
++pullCount;
c.byobRequest.view[0] = pullCount;
c.byobRequest.respond(1);
}
});
const reader = rs.getReader({ mode: 'byob' });
const read1 = reader.readFully(new Uint8Array(3));
const read2 = reader.read(new Uint8Array(1));
await read1; // should be [1, 2, 3], NOT [1, 3, 4]
await read2; // should be [4], NOT [2]
```
One solution would be to have a "special type" for `readFully()` pull-into descriptors. Or another (simpler?) solution might be to always put the pull-into descriptor for the remainder *at the front of the `[[pendingPullIntos]]` queue* (rather than at the back).
* Should we also have a shorthand `ReadableStream.readFully(view)`? Would it have the same signature, i.e. returning `Promise<ReadableStreamBYOBReadResult>`?
--
You are receiving this because you are subscribed to this thread.
Reply to this email directly or view it on GitHub:
https://github.com/whatwg/streams/issues/1143
Received on Monday, 12 July 2021 22:15:58 UTC