0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-03 09:31:22 -05:00

BREAKING CHANGE: rename Deno.toAsyncIterator() to Deno.iter() (#4848)

* rename Deno.toAsyncIterator() to Deno.iter()
* adds sync version Deno.iterSync()
* adds optional second argument for buffer size
This commit is contained in:
Bartek Iwańczuk 2020-04-22 21:30:45 +02:00 committed by GitHub
parent da6819a14c
commit 68d287eed5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 169 additions and 28 deletions

View file

@ -42,7 +42,8 @@ export { FsEvent, fsEvents } from "./ops/fs_events.ts";
export {
EOF,
copy,
toAsyncIterator,
iter,
iterSync,
SeekMode,
Reader,
SyncReader,

View file

@ -84,23 +84,32 @@ export async function copy(dst: Writer, src: Reader): Promise<number> {
return n;
}
export function toAsyncIterator(r: Reader): AsyncIterableIterator<Uint8Array> {
const b = new Uint8Array(1024);
return {
[Symbol.asyncIterator](): AsyncIterableIterator<Uint8Array> {
return this;
},
export async function* iter(
r: Reader,
bufSize?: number
): AsyncIterableIterator<Uint8Array> {
const b = new Uint8Array(bufSize ?? 1024);
while (true) {
const result = await r.read(b);
if (result === EOF) {
break;
}
async next(): Promise<IteratorResult<Uint8Array>> {
const result = await r.read(b);
if (result === EOF) {
return { value: new Uint8Array(), done: true };
}
return {
value: b.subarray(0, result),
done: false,
};
},
};
yield b.subarray(0, result);
}
}
export function* iterSync(
r: SyncReader,
bufSize?: number
): IterableIterator<Uint8Array> {
const b = new Uint8Array(bufSize ?? 1024);
while (true) {
const result = r.readSync(b);
if (result === EOF) {
break;
}
yield b.subarray(0, result);
}
}

View file

@ -573,13 +573,61 @@ declare namespace Deno {
*/
export function copy(dst: Writer, src: Reader): Promise<number>;
/** Turns a Reader, `r`, into an async iterator.
/** **UNSTABLE**: new API, yet to be vetted
* Turns a Reader, `r`, into an async iterator.
*
* for await (const chunk of toAsyncIterator(reader)) {
* let f = await open("/etc/passwd");
* for await (const chunk of iter(f)) {
* console.log(chunk);
* }
* f.close();
*
* Second argument can be used to tune size of a buffer.
* Default size of the buffer is 1024 bytes.
*
* let f = await open("/etc/passwd");
* for await (const chunk of iter(f, 1024 * 1024)) {
* console.log(chunk);
* }
* f.close();
*
* Iterator uses internal buffer of fixed size for efficiency returning
* a view on that buffer on each iteration. It it therefore callers
* responsibility to copy contents of the buffer if needed; otherwise
* next iteration will overwrite contents of previously returned chunk.
*/
export function toAsyncIterator(r: Reader): AsyncIterableIterator<Uint8Array>;
export function iter(
r: Reader,
bufSize?: number
): AsyncIterableIterator<Uint8Array>;
/** **UNSTABLE**: new API, yet to be vetted
* Turns a SyncReader, `r`, into an iterator.
*
* let f = await open("/etc/passwd");
* for (const chunk of iterSync(reader)) {
* console.log(chunk);
* }
* f.close();
*
* Second argument can be used to tune size of a buffer.
* Default size of the buffer is 1024 bytes.
*
* let f = await open("/etc/passwd");
* for (const chunk of iterSync(reader, 1024 * 1024)) {
* console.log(chunk);
* }
* f.close()
*
* Iterator uses internal buffer of fixed size for efficiency returning
* a view on that buffer on each iteration. It it therefore callers
* responsibility to copy contents of the buffer if needed; otherwise
* next iteration will overwrite contents of previously returned chunk.
*/
export function iterSync(
r: SyncReader,
bufSize?: number
): IterableIterator<Uint8Array>;
/** Synchronously open a file and return an instance of `Deno.File`. The
* file does not need to previously exist if using the `create` or `createNew`

View file

@ -25,23 +25,71 @@ unitTest({ perms: { read: true } }, async function filesCopyToStdout(): Promise<
file.close();
});
unitTest({ perms: { read: true } }, async function filesIter(): Promise<void> {
const filename = "cli/tests/hello.txt";
const file = await Deno.open(filename);
let totalSize = 0;
for await (const buf of Deno.iter(file)) {
totalSize += buf.byteLength;
}
assertEquals(totalSize, 12);
file.close();
});
unitTest(
{ perms: { read: true } },
async function filesToAsyncIterator(): Promise<void> {
async function filesIterCustomBufSize(): Promise<void> {
const filename = "cli/tests/hello.txt";
const file = await Deno.open(filename);
let totalSize = 0;
for await (const buf of Deno.toAsyncIterator(file)) {
let iterations = 0;
for await (const buf of Deno.iter(file, 6)) {
totalSize += buf.byteLength;
iterations += 1;
}
assertEquals(totalSize, 12);
assertEquals(iterations, 2);
file.close();
}
);
unitTest(async function readerToAsyncIterator(): Promise<void> {
unitTest({ perms: { read: true } }, function filesIterSync(): void {
const filename = "cli/tests/hello.txt";
const file = Deno.openSync(filename);
let totalSize = 0;
for (const buf of Deno.iterSync(file)) {
totalSize += buf.byteLength;
}
assertEquals(totalSize, 12);
file.close();
});
unitTest(
{ perms: { read: true } },
function filesIterSyncCustomBufSize(): void {
const filename = "cli/tests/hello.txt";
const file = Deno.openSync(filename);
let totalSize = 0;
let iterations = 0;
for (const buf of Deno.iterSync(file, 6)) {
totalSize += buf.byteLength;
iterations += 1;
}
assertEquals(totalSize, 12);
assertEquals(iterations, 2);
file.close();
}
);
unitTest(async function readerIter(): Promise<void> {
// ref: https://github.com/denoland/deno/issues/2330
const encoder = new TextEncoder();
@ -69,7 +117,42 @@ unitTest(async function readerToAsyncIterator(): Promise<void> {
const reader = new TestReader("hello world!");
let totalSize = 0;
for await (const buf of Deno.toAsyncIterator(reader)) {
for await (const buf of Deno.iter(reader)) {
totalSize += buf.byteLength;
}
assertEquals(totalSize, 12);
});
unitTest(async function readerIterSync(): Promise<void> {
// ref: https://github.com/denoland/deno/issues/2330
const encoder = new TextEncoder();
class TestReader implements Deno.SyncReader {
#offset = 0;
#buf: Uint8Array;
constructor(s: string) {
this.#buf = new Uint8Array(encoder.encode(s));
}
readSync(p: Uint8Array): number | Deno.EOF {
const n = Math.min(p.byteLength, this.#buf.byteLength - this.#offset);
p.set(this.#buf.slice(this.#offset, this.#offset + n));
this.#offset += n;
if (n === 0) {
return Deno.EOF;
}
return n;
}
}
const reader = new TestReader("hello world!");
let totalSize = 0;
for await (const buf of Deno.iterSync(reader)) {
totalSize += buf.byteLength;
}

View file

@ -248,7 +248,7 @@ class Body implements domTypes.Body, ReadableStream<Uint8Array>, io.ReadCloser {
}
[Symbol.asyncIterator](): AsyncIterableIterator<Uint8Array> {
return io.toAsyncIterator(this);
return io.iter(this);
}
get bodyUsed(): boolean {

View file

@ -164,7 +164,7 @@ export async function writeChunkedBody(
r: Deno.Reader
): Promise<void> {
const writer = BufWriter.create(w);
for await (const chunk of Deno.toAsyncIterator(r)) {
for await (const chunk of Deno.iter(r)) {
if (chunk.byteLength <= 0) continue;
const start = encoder.encode(`${chunk.byteLength.toString(16)}\r\n`);
const end = encoder.encode("\r\n");