Skip to content

Commit

Permalink
feat(io): ReadableStream from AsyncIterator & WritableStream from Wri…
Browse files Browse the repository at this point in the history
  • Loading branch information
crowlKats authored and denobot committed Feb 1, 2021
1 parent d3de4cc commit 82dbe19
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 9 deletions.
36 changes: 32 additions & 4 deletions io/streams.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.

/** Create a `Writer` from a `WritablseStreamDefaultReader`. */
export function fromStreamWriter(
/** Create a `Writer` from a `WritableStreamDefaultReader`. */
export function writerFromStreamWriter(
streamWriter: WritableStreamDefaultWriter<Uint8Array>,
): Deno.Writer {
return {
Expand All @@ -13,8 +13,8 @@ export function fromStreamWriter(
};
}

/** Create a `Reader` from a `ReadableSteramDefaultReader`. */
export function fromStreamReader(
/** Create a `Reader` from a `ReadableStreamDefaultReader`. */
export function readerFromStreamReader(
streamReader: ReadableStreamDefaultReader<Uint8Array>,
): Deno.Reader {
const buffer = new Deno.Buffer();
Expand All @@ -34,3 +34,31 @@ export function fromStreamReader(
},
};
}

/** Create a `WritableStream` from a `Writer`. */
export function writableStreamFromWriter(
writer: Deno.Writer,
): WritableStream<Uint8Array> {
return new WritableStream({
async write(chunk) {
await Deno.writeAll(writer, chunk);
},
});
}

/** Create a `ReadableStream` from an `AsyncIterator`. */
export function readableStreamFromAsyncIterator<T>(
iterator: AsyncIterableIterator<T>,
): ReadableStream<T> {
return new ReadableStream({
async pull(controller) {
const { value, done } = await iterator.next();

if (done) {
controller.close();
} else {
controller.enqueue(value);
}
},
});
}
63 changes: 58 additions & 5 deletions io/streams_test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.

import { assert, assertEquals } from "../testing/asserts.ts";
import { fromStreamReader, fromStreamWriter } from "./streams.ts";
import {
readableStreamFromAsyncIterator,
readerFromStreamReader,
writableStreamFromWriter,
writerFromStreamWriter,
} from "./streams.ts";

function repeat(c: string, bytes: number): Uint8Array {
assertEquals(c.length, 1);
Expand All @@ -21,7 +26,7 @@ Deno.test("toWriterCheck", async function (): Promise<void> {
});

const encoder = new TextEncoder();
const writer = fromStreamWriter(writableStream.getWriter());
const writer = writerFromStreamWriter(writableStream.getWriter());

for (const chunk of chunks) {
const n = await writer.write(encoder.encode(chunk));
Expand All @@ -46,7 +51,7 @@ Deno.test("toReaderCheck", async function (): Promise<void> {
});

const decoder = new TextDecoder();
const reader = fromStreamReader(readableStream.getReader());
const reader = readerFromStreamReader(readableStream.getReader());

let i = 0;

Expand Down Expand Up @@ -91,7 +96,7 @@ Deno.test("toReaderBigChunksCheck", async function (): Promise<void> {
},
});

const reader = fromStreamReader(readableStream.getReader());
const reader = readerFromStreamReader(readableStream.getReader());
const n = await Deno.copy(reader, writer, { bufSize });

const expectedWritten = chunkSize * expected.length;
Expand Down Expand Up @@ -126,9 +131,57 @@ Deno.test("toReaderBigIrregularChunksCheck", async function (): Promise<void> {
},
});

const reader = fromStreamReader(readableStream.getReader());
const reader = readerFromStreamReader(readableStream.getReader());

const n = await Deno.copy(reader, writer, { bufSize });
assertEquals(n, expected.length);
assertEquals(expected, writer.bytes());
});

Deno.test("toWritableCheck", async function (): Promise<void> {
const written: string[] = [];
const chunks: string[] = ["hello", "deno", "land"];
const decoder = new TextDecoder();

async function write(p: Uint8Array): Promise<number> {
written.push(decoder.decode(p));
return p.length;
}

const writableStream = writableStreamFromWriter({ write });

const encoder = new TextEncoder();
const streamWriter = writableStream.getWriter();
for (const chunk of chunks) {
await streamWriter.write(encoder.encode(chunk));
}

assertEquals(written, chunks);
});

Deno.test("toReadableCheck", async function (): Promise<void> {
const chunks: string[] = ["hello", "deno", "land"];
const expected = chunks.slice();
const readChunks: string[] = [];
const encoder = new TextEncoder();

async function read(p: Uint8Array): Promise<number | null> {
const chunk = chunks.shift();
if (chunk === undefined) {
return null;
} else {
const encoded = encoder.encode(chunk);
p.set(encoded);
return encoded.length;
}
}
const iter = Deno.iter({ read });
const writableStream = readableStreamFromAsyncIterator(iter);

const decoder = new TextDecoder();
for await (const chunk of writableStream.getIterator()) {
readChunks.push(decoder.decode(chunk));
}

assertEquals(expected, readChunks);
});

0 comments on commit 82dbe19

Please sign in to comment.