mirror of
https://github.com/denoland/deno.git
synced 2024-12-02 17:01:14 -05:00
Add bufio tests.
This commit is contained in:
parent
be1eb62bdc
commit
aa9e3df0d2
3 changed files with 132 additions and 18 deletions
55
bufio.ts
55
bufio.ts
|
@ -24,6 +24,7 @@ export class Reader implements deno.Reader {
|
|||
private w = 0; // buf write position.
|
||||
private lastByte: number;
|
||||
private lastCharSize: number;
|
||||
private err: null | Error;
|
||||
|
||||
constructor(rd: deno.Reader, size = DEFAULT_BUF_SIZE) {
|
||||
if (size < MIN_BUF_SIZE) {
|
||||
|
@ -37,9 +38,15 @@ export class Reader implements deno.Reader {
|
|||
return this.buf.byteLength;
|
||||
}
|
||||
|
||||
private _readErr(): Error {
|
||||
const err = this.err;
|
||||
this.err = null;
|
||||
return err;
|
||||
}
|
||||
|
||||
// Reads a new chunk into the buffer.
|
||||
// Returns true if EOF, false on successful read.
|
||||
async _fill(): Promise<boolean> {
|
||||
private async _fill(): Promise<boolean> {
|
||||
// Slide existing data to beginning.
|
||||
if (this.r > 0) {
|
||||
this.buf.copyWithin(0, this.r, this.w);
|
||||
|
@ -53,15 +60,21 @@ export class Reader implements deno.Reader {
|
|||
|
||||
// Read new data: try a limited number of times.
|
||||
for (let i = MAX_CONSECUTIVE_EMPTY_READS; i > 0; i--) {
|
||||
const { nread, eof } = await this.rd.read(this.buf.subarray(this.w));
|
||||
if (nread < 0) {
|
||||
let rr: deno.ReadResult;
|
||||
try {
|
||||
rr = await this.rd.read(this.buf.subarray(this.w));
|
||||
} catch (e) {
|
||||
this.err = e;
|
||||
return false;
|
||||
}
|
||||
if (rr.nread < 0) {
|
||||
throw new ErrNegativeRead();
|
||||
}
|
||||
this.w += nread;
|
||||
if (eof) {
|
||||
this.w += rr.nread;
|
||||
if (rr.eof) {
|
||||
return true;
|
||||
}
|
||||
if (nread > 0) {
|
||||
if (rr.nread > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -92,15 +105,16 @@ export class Reader implements deno.Reader {
|
|||
async read(p: ArrayBufferView): Promise<deno.ReadResult> {
|
||||
let rr: deno.ReadResult = { nread: p.byteLength, eof: false };
|
||||
if (rr.nread === 0) {
|
||||
if (this.err) {
|
||||
throw this._readErr();
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
|
||||
if (this.r === this.w) {
|
||||
/*
|
||||
if (this.err != null) {
|
||||
throw this.readErr();
|
||||
if (this.err) {
|
||||
throw this._readErr();
|
||||
}
|
||||
*/
|
||||
if (p.byteLength >= this.buf.byteLength) {
|
||||
// Large read, empty buffer.
|
||||
// Read directly into p to avoid copy.
|
||||
|
@ -112,6 +126,9 @@ export class Reader implements deno.Reader {
|
|||
this.lastByte = p[rr.nread - 1];
|
||||
// this.lastRuneSize = -1;
|
||||
}
|
||||
if (this.err) {
|
||||
throw this._readErr();
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
// One read.
|
||||
|
@ -123,6 +140,9 @@ export class Reader implements deno.Reader {
|
|||
throw new ErrNegativeRead();
|
||||
}
|
||||
if (rr.nread === 0) {
|
||||
if (this.err) {
|
||||
throw this._readErr();
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
this.w += rr.nread;
|
||||
|
@ -140,6 +160,9 @@ export class Reader implements deno.Reader {
|
|||
async readByte(): Promise<number> {
|
||||
while (this.r === this.w) {
|
||||
const eof = await this._fill(); // buffer is empty.
|
||||
if (this.err != null) {
|
||||
throw this._readErr();
|
||||
}
|
||||
if (eof) {
|
||||
return -1;
|
||||
}
|
||||
|
@ -149,4 +172,16 @@ export class Reader implements deno.Reader {
|
|||
this.lastByte = c;
|
||||
return c;
|
||||
}
|
||||
|
||||
/** readString() reads until the first occurrence of delim in the input,
|
||||
* returning a string containing the data up to and including the delimiter.
|
||||
* If ReadString encounters an error before finding a delimiter,
|
||||
* it returns the data read before the error and the error itself (often io.EOF).
|
||||
* ReadString returns err != nil if and only if the returned data does not end in
|
||||
* delim.
|
||||
* For simple uses, a Scanner may be more convenient.
|
||||
*/
|
||||
async readString(delim: string): Promise<string> {
|
||||
throw new Error("Not implemented");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import * as deno from "deno";
|
|||
import { test, assertEqual } from "http://deno.land/x/testing/testing.ts";
|
||||
import * as bufio from "./bufio.ts";
|
||||
import { Buffer } from "./buffer.ts";
|
||||
import * as iotest from "./iotest.ts";
|
||||
|
||||
async function readBytes(buf: bufio.Reader): Promise<string> {
|
||||
const b = new Uint8Array(1000);
|
||||
|
@ -39,15 +40,25 @@ test(async function bufioReaderSimple() {
|
|||
type ReadMaker = { name: string; fn: (r: deno.Reader) => deno.Reader };
|
||||
|
||||
const readMakers: ReadMaker[] = [
|
||||
{ name: "full", fn: r => r }
|
||||
/*
|
||||
{ name: "byte", fn(r) => new iotest.OneByteReader(r) },
|
||||
{ name: "half", fn(r) => new iotest.HalfReader(r) },
|
||||
{ name: "data+err", r => new iotest.DataErrReader(r) },
|
||||
{ name: "timeout", r => new iotest.TimeoutReader(r) },
|
||||
*/
|
||||
{ name: "full", fn: r => r },
|
||||
{ name: "byte", fn: r => new iotest.OneByteReader(r) },
|
||||
{ name: "half", fn: r => new iotest.HalfReader(r) }
|
||||
// TODO { name: "data+err", r => new iotest.DataErrReader(r) },
|
||||
// { name: "timeout", fn: r => new iotest.TimeoutReader(r) },
|
||||
];
|
||||
|
||||
function readLines(b: bufio.Reader): string {
|
||||
let s = "";
|
||||
while (true) {
|
||||
let s1 = b.readString("\n");
|
||||
if (s1 == null) {
|
||||
break; // EOF
|
||||
}
|
||||
s += s1;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
// Call read to accumulate the text of a file
|
||||
async function reads(buf: bufio.Reader, m: number): Promise<string> {
|
||||
const b = new Uint8Array(1000);
|
||||
|
@ -66,7 +77,14 @@ async function reads(buf: bufio.Reader, m: number): Promise<string> {
|
|||
type BufReader = { name: string; fn: (r: bufio.Reader) => Promise<string> };
|
||||
|
||||
const bufreaders: BufReader[] = [
|
||||
{ name: "1", fn: (b: bufio.Reader) => reads(b, 1) }
|
||||
{ name: "1", fn: (b: bufio.Reader) => reads(b, 1) },
|
||||
{ name: "2", fn: (b: bufio.Reader) => reads(b, 2) },
|
||||
{ name: "3", fn: (b: bufio.Reader) => reads(b, 3) },
|
||||
{ name: "4", fn: (b: bufio.Reader) => reads(b, 4) },
|
||||
{ name: "5", fn: (b: bufio.Reader) => reads(b, 5) },
|
||||
{ name: "7", fn: (b: bufio.Reader) => reads(b, 7) },
|
||||
{ name: "bytes", fn: readBytes }
|
||||
// { name: "lines", fn: readLines },
|
||||
];
|
||||
|
||||
const MIN_READ_BUFFER_SIZE = 16;
|
||||
|
|
61
iotest.ts
Normal file
61
iotest.ts
Normal file
|
@ -0,0 +1,61 @@
|
|||
// Ported to Deno from
|
||||
// Copyright 2009 The Go Authors. All rights reserved.
|
||||
// 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";
|
||||
|
||||
/** OneByteReader returns a Reader that implements
|
||||
* each non-empty Read by reading one byte from r.
|
||||
*/
|
||||
export class OneByteReader implements Reader {
|
||||
constructor(readonly r: Reader) {}
|
||||
|
||||
async read(p: ArrayBufferView): Promise<ReadResult> {
|
||||
if (p.byteLength === 0) {
|
||||
return { nread: 0, eof: false };
|
||||
}
|
||||
if (!(p instanceof Uint8Array)) {
|
||||
throw Error("expected Uint8Array");
|
||||
}
|
||||
return this.r.read(p.subarray(0, 1));
|
||||
}
|
||||
}
|
||||
|
||||
/** HalfReader returns a Reader that implements Read
|
||||
* by reading half as many requested bytes from r.
|
||||
*/
|
||||
export class HalfReader implements Reader {
|
||||
constructor(readonly r: Reader) {}
|
||||
|
||||
async read(p: ArrayBufferView): Promise<ReadResult> {
|
||||
if (!(p instanceof Uint8Array)) {
|
||||
throw Error("expected Uint8Array");
|
||||
}
|
||||
const half = Math.floor((p.byteLength + 1) / 2);
|
||||
return this.r.read(p.subarray(0, half));
|
||||
}
|
||||
}
|
||||
|
||||
export class ErrTimeout extends Error {
|
||||
constructor() {
|
||||
super("timeout");
|
||||
this.name = "ErrTimeout";
|
||||
}
|
||||
}
|
||||
|
||||
/** TimeoutReader returns ErrTimeout on the second read
|
||||
* with no data. Subsequent calls to read succeed.
|
||||
*/
|
||||
export class TimeoutReader implements Reader {
|
||||
count = 0;
|
||||
constructor(readonly r: Reader) {}
|
||||
|
||||
async read(p: ArrayBufferView): Promise<ReadResult> {
|
||||
this.count++;
|
||||
if (this.count === 2) {
|
||||
throw new ErrTimeout();
|
||||
}
|
||||
return this.r.read(p);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue