summaryrefslogtreecommitdiff
path: root/cli/js
diff options
context:
space:
mode:
Diffstat (limited to 'cli/js')
-rw-r--r--cli/js/deno.ts3
-rw-r--r--cli/js/io.ts47
-rw-r--r--cli/js/lib.deno.ns.d.ts54
-rw-r--r--cli/js/tests/files_test.ts91
-rw-r--r--cli/js/web/fetch.ts2
5 files changed, 169 insertions, 28 deletions
diff --git a/cli/js/deno.ts b/cli/js/deno.ts
index e35e8c161..b75df4a9d 100644
--- a/cli/js/deno.ts
+++ b/cli/js/deno.ts
@@ -42,7 +42,8 @@ export { FsEvent, fsEvents } from "./ops/fs_events.ts";
export {
EOF,
copy,
- toAsyncIterator,
+ iter,
+ iterSync,
SeekMode,
Reader,
SyncReader,
diff --git a/cli/js/io.ts b/cli/js/io.ts
index b5af34224..023718100 100644
--- a/cli/js/io.ts
+++ b/cli/js/io.ts
@@ -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;
- },
-
- 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,
- };
- },
- };
+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;
+ }
+
+ 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);
+ }
}
diff --git a/cli/js/lib.deno.ns.d.ts b/cli/js/lib.deno.ns.d.ts
index 9f2c854d9..ed2e40f84 100644
--- a/cli/js/lib.deno.ns.d.ts
+++ b/cli/js/lib.deno.ns.d.ts
@@ -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.
+ *
+ * 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.
*
- * for await (const chunk of toAsyncIterator(reader)) {
+ * 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 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 toAsyncIterator(r: Reader): AsyncIterableIterator<Uint8Array>;
+ 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`
diff --git a/cli/js/tests/files_test.ts b/cli/js/tests/files_test.ts
index 1f7352afc..f68e5def4 100644
--- a/cli/js/tests/files_test.ts
+++ b/cli/js/tests/files_test.ts
@@ -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({ 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 readerToAsyncIterator(): Promise<void> {
+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;
}
diff --git a/cli/js/web/fetch.ts b/cli/js/web/fetch.ts
index 2c16d5fb0..abb5f2aa2 100644
--- a/cli/js/web/fetch.ts
+++ b/cli/js/web/fetch.ts
@@ -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 {