1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-26 16:09:27 -05:00

First pass at BufWriter

Original: 9329cd76bd
This commit is contained in:
Ryan Dahl 2018-11-09 13:25:30 -05:00
parent 9b78509ceb
commit 5880827f33
3 changed files with 136 additions and 4 deletions

104
bufio.ts
View file

@ -3,7 +3,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
import { Reader, ReadResult } from "deno";
import { Reader, ReadResult, Writer } from "deno";
import { assert, charCode, copyBytes } from "./util.ts";
const DEFAULT_BUF_SIZE = 4096;
@ -32,7 +32,7 @@ export class BufReader implements Reader {
}
/** Returns the size of the underlying buffer in bytes. */
get byteLength(): number {
size(): number {
return this.buf.byteLength;
}
@ -332,4 +332,104 @@ export class BufReader implements Reader {
* the underlying deno.Writer.
*/
export class BufWriter implements Writer {
buf: Uint8Array;
n: number = 0;
err: null | Error = null;
constructor(private wr: Writer, size = DEFAULT_BUF_SIZE) {
if (size <= 0) {
size = DEFAULT_BUF_SIZE;
}
this.buf = new Uint8Array(size);
}
/** Size returns the size of the underlying buffer in bytes. */
size(): number {
return this.buf.byteLength;
}
/** Discards any unflushed buffered data, clears any error, and
* resets b to write its output to w.
*/
reset(w: Writer): void {
this.err = null;
this.n = 0;
this.wr = w;
}
/** Flush writes any buffered data to the underlying io.Writer. */
async flush(): Promise<void> {
if (this.err != null) {
throw this.err;
}
if (this.n == 0) {
return;
}
let n: number;
let err: Error = null;
try {
n = await this.wr.write(this.buf.subarray(0, this.n));
} catch (e) {
err = e;
}
if (n < this.n && err == null) {
err = new Error("ShortWrite");
}
if (err != null) {
if (n > 0 && n < this.n) {
this.buf.copyWithin(0, n, this.n);
}
this.n -= n;
this.err = err;
return;
}
this.n = 0;
}
/** Returns how many bytes are unused in the buffer. */
available(): number {
return this.buf.byteLength - this.n;
}
/** buffered returns the number of bytes that have been written into the
* current buffer.
*/
buffered(): number {
return this.n;
}
/** Writes the contents of p into the buffer.
* Returns the number of bytes written.
*/
async write(p: Uint8Array): Promise<number> {
let nn = 0;
let n: number;
while (p.byteLength > this.available() && !this.err) {
if (this.buffered() == 0) {
// Large write, empty buffer.
// Write directly from p to avoid copy.
try {
n = await this.wr.write(p);
} catch (e) {
this.err = e;
}
} else {
n = copyBytes(this.buf, p, this.n);
this.n += n;
this.flush();
}
nn += n;
p = p.subarray(n);
}
if (this.err) {
throw this.err;
}
n = copyBytes(this.buf, p, this.n);
this.n += n;
nn += n;
return nn;
}
}

View file

@ -9,7 +9,7 @@ import {
assert,
assertEqual
} from "https://deno.land/x/testing/testing.ts";
import { BufReader, BufState } from "./bufio.ts";
import { BufReader, BufState, BufWriter } from "./bufio.ts";
import { Buffer, stringsReader } from "./buffer.ts";
import * as iotest from "./iotest.ts";
import { charCode, copyBytes } from "./util.ts";
@ -289,3 +289,36 @@ test(async function bufioPeek() {
}
*/
});
test(async function bufioWriter() {
const data = new Uint8Array(8192);
for (let i = 0; i < data.byteLength; i++) {
data[i] = charCode(" ") + i % (charCode("~") - charCode(" "));
}
const w = new Buffer();
for (let nwrite of bufsizes) {
for (let bs of bufsizes) {
// Write nwrite bytes using buffer size bs.
// Check that the right amount makes it out
// and that the data is correct.
w.reset();
const buf = new BufWriter(w, bs);
const context = `nwrite=${nwrite} bufsize=${bs}`;
const n = await buf.write(data.subarray(0, nwrite));
assertEqual(n, nwrite, context);
await buf.flush();
const written = w.bytes();
assertEqual(written.byteLength, nwrite);
for (let l = 0; l < written.byteLength; l++) {
assertEqual(written[l], data[l]);
}
}
}
});

View file

@ -55,4 +55,3 @@ async function readRequest(b: BufReader): Promise<ServerRequest> {
return req;
}