1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-26 09:10:40 -05:00

Move collectUint8Arrays() to util/async.ts, clean up, fix bugs, add tests

This commit is contained in:
Bert Belder 2019-05-20 17:08:05 -07:00
parent d1971241d9
commit dcad420b92
No known key found for this signature in database
GPG key ID: 7A77887B2E2ED461
3 changed files with 73 additions and 26 deletions

View file

@ -8,7 +8,12 @@ import { BufReader, BufState, BufWriter } from "../io/bufio.ts";
import { TextProtoReader } from "../textproto/mod.ts"; import { TextProtoReader } from "../textproto/mod.ts";
import { STATUS_TEXT } from "./http_status.ts"; import { STATUS_TEXT } from "./http_status.ts";
import { assert, fail } from "../testing/asserts.ts"; import { assert, fail } from "../testing/asserts.ts";
import { deferred, Deferred, MuxAsyncIterator } from "../util/async.ts"; import {
collectUint8Arrays,
deferred,
Deferred,
MuxAsyncIterator
} from "../util/async.ts";
function bufWriter(w: Writer): BufWriter { function bufWriter(w: Writer): BufWriter {
if (w instanceof BufWriter) { if (w instanceof BufWriter) {
@ -94,28 +99,6 @@ export async function writeResponse(w: Writer, r: Response): Promise<void> {
await writer.flush(); await writer.flush();
} }
async function readAllIterator(
it: AsyncIterableIterator<Uint8Array>
): Promise<Uint8Array> {
const chunks = [];
let len = 0;
for await (const chunk of it) {
chunks.push(chunk);
len += chunk.length;
}
if (chunks.length === 0) {
// No need for copy
return chunks[0];
}
const collected = new Uint8Array(len);
let offset = 0;
for (let chunk of chunks) {
collected.set(chunk, offset);
offset += chunk.length;
}
return collected;
}
export class ServerRequest { export class ServerRequest {
url: string; url: string;
method: string; method: string;
@ -203,7 +186,7 @@ export class ServerRequest {
// Read the body of the request into a single Uint8Array // Read the body of the request into a single Uint8Array
public async body(): Promise<Uint8Array> { public async body(): Promise<Uint8Array> {
return readAllIterator(this.bodyStream()); return collectUint8Arrays(this.bodyStream());
} }
async respond(r: Response): Promise<void> { async respond(r: Response): Promise<void> {

View file

@ -83,3 +83,28 @@ export class MuxAsyncIterator<T> implements AsyncIterable<T> {
return this.iterate(); return this.iterate();
} }
} }
/** Collects all Uint8Arrays from an AsyncIterable and retuns a single
* Uint8Array with the concatenated contents of all the collected arrays.
*/
export async function collectUint8Arrays(
it: AsyncIterable<Uint8Array>
): Promise<Uint8Array> {
const chunks = [];
let length = 0;
for await (const chunk of it) {
chunks.push(chunk);
length += chunk.length;
}
if (chunks.length === 1) {
// No need to copy.
return chunks[0];
}
const collected = new Uint8Array(length);
let offset = 0;
for (let chunk of chunks) {
collected.set(chunk, offset);
offset += chunk.length;
}
return collected;
}

View file

@ -1,7 +1,7 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license. // Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
import { test, runIfMain } from "../testing/mod.ts"; import { test, runIfMain } from "../testing/mod.ts";
import { assertEquals } from "../testing/asserts.ts"; import { assert, assertEquals, assertStrictEq } from "../testing/asserts.ts";
import { MuxAsyncIterator, deferred } from "./async.ts"; import { collectUint8Arrays, deferred, MuxAsyncIterator } from "./async.ts";
test(async function asyncDeferred(): Promise<void> { test(async function asyncDeferred(): Promise<void> {
const d = deferred<number>(); const d = deferred<number>();
@ -31,4 +31,43 @@ test(async function asyncMuxAsyncIterator(): Promise<void> {
assertEquals(results.size, 6); assertEquals(results.size, 6);
}); });
test(async function collectUint8Arrays0(): Promise<void> {
async function* gen(): AsyncIterableIterator<Uint8Array> {}
const result = await collectUint8Arrays(gen());
assert(result instanceof Uint8Array);
assertEquals(result.length, 0);
});
test(async function collectUint8Arrays0(): Promise<void> {
async function* gen(): AsyncIterableIterator<Uint8Array> {}
const result = await collectUint8Arrays(gen());
assert(result instanceof Uint8Array);
assertStrictEq(result.length, 0);
});
test(async function collectUint8Arrays1(): Promise<void> {
const buf = new Uint8Array([1, 2, 3]);
async function* gen(): AsyncIterableIterator<Uint8Array> {
yield buf;
}
const result = await collectUint8Arrays(gen());
assertStrictEq(result, buf);
assertStrictEq(result.length, 3);
});
test(async function collectUint8Arrays4(): Promise<void> {
async function* gen(): AsyncIterableIterator<Uint8Array> {
yield new Uint8Array([1, 2, 3]);
yield new Uint8Array([]);
yield new Uint8Array([4, 5]);
yield new Uint8Array([6]);
}
const result = await collectUint8Arrays(gen());
assert(result instanceof Uint8Array);
assertStrictEq(result.length, 6);
for (let i = 0; i < 6; i++) {
assertStrictEq(result[i], i + 1);
}
});
runIfMain(import.meta); runIfMain(import.meta);