mirror of
https://github.com/denoland/deno.git
synced 2024-12-02 17:01:14 -05:00
First pass at bufio.read tests.
This commit is contained in:
parent
c5cc695970
commit
1eb57aa394
7 changed files with 170 additions and 28 deletions
14
buffer.ts
14
buffer.ts
|
@ -4,7 +4,7 @@
|
|||
|
||||
//import * as io from "./io";
|
||||
import { Reader, Writer, ReadResult } from "deno";
|
||||
import { assert } from "./util.ts";
|
||||
import { assert, copyBytes } from "./util.ts";
|
||||
|
||||
// MIN_READ is the minimum ArrayBuffer size passed to a read call by
|
||||
// buffer.ReadFrom. As long as the Buffer has at least MIN_READ bytes beyond
|
||||
|
@ -13,18 +13,6 @@ import { assert } from "./util.ts";
|
|||
const MIN_READ = 512;
|
||||
const MAX_SIZE = 2 ** 32 - 2;
|
||||
|
||||
// `off` is the offset into `dst` where it will at which to begin writing values
|
||||
// from `src`.
|
||||
// Returns the number of bytes copied.
|
||||
function copyBytes(dst: Uint8Array, src: Uint8Array, off = 0): number {
|
||||
const r = dst.byteLength - off;
|
||||
if (src.byteLength > r) {
|
||||
src = src.subarray(0, r);
|
||||
}
|
||||
dst.set(src, off);
|
||||
return src.byteLength;
|
||||
}
|
||||
|
||||
/** A Buffer is a variable-sized buffer of bytes with read() and write()
|
||||
* methods. Based on https://golang.org/pkg/bytes/#Buffer
|
||||
*/
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
// This code has been ported almost directly from Go's src/bytes/buffer_test.go
|
||||
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
import { test, assert, assertEqual } from "./test_util.ts";
|
||||
import { Buffer } from "deno";
|
||||
import {
|
||||
test,
|
||||
assert,
|
||||
assertEqual
|
||||
} from "http://deno.land/x/testing/testing.ts";
|
||||
import { Buffer } from "./buffer.ts";
|
||||
|
||||
// N controls how many iterations of certain checks are performed.
|
||||
const N = 100;
|
||||
|
@ -13,7 +17,7 @@ function init() {
|
|||
if (testBytes == null) {
|
||||
testBytes = new Uint8Array(N);
|
||||
for (let i = 0; i < N; i++) {
|
||||
testBytes[i] = "a".charCodeAt(0) + (i % 26);
|
||||
testBytes[i] = "a".charCodeAt(0) + i % 26;
|
||||
}
|
||||
const decoder = new TextDecoder();
|
||||
testString = decoder.decode(testBytes);
|
||||
|
|
72
bufio.ts
72
bufio.ts
|
@ -1,9 +1,22 @@
|
|||
// 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 * as deno from "deno";
|
||||
import { assert, copyBytes } from "./util.ts";
|
||||
|
||||
const DEFAULT_BUF_SIZE = 4096;
|
||||
const MIN_BUF_SIZE = 16;
|
||||
const MAX_CONSECUTIVE_EMPTY_READS = 100;
|
||||
|
||||
export class ErrNegativeRead extends Error {
|
||||
constructor() {
|
||||
super("bufio: reader returned negative count from Read");
|
||||
this.name = "ErrNegativeRead";
|
||||
}
|
||||
}
|
||||
|
||||
export class Reader implements deno.Reader {
|
||||
private buf: Uint8Array;
|
||||
private rd: deno.Reader; // Reader provided by caller.
|
||||
|
@ -16,7 +29,7 @@ export class Reader implements deno.Reader {
|
|||
if (size < MIN_BUF_SIZE) {
|
||||
size = MIN_BUF_SIZE;
|
||||
}
|
||||
this._reset(new Uint8Array(size), rd)
|
||||
this._reset(new Uint8Array(size), rd);
|
||||
}
|
||||
|
||||
/** Returns the size of the underlying buffer in bytes. */
|
||||
|
@ -42,7 +55,7 @@ export class Reader implements deno.Reader {
|
|||
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) {
|
||||
throw Error("negative read");
|
||||
throw new ErrNegativeRead();
|
||||
}
|
||||
this.w += nread;
|
||||
if (eof) {
|
||||
|
@ -69,9 +82,58 @@ export class Reader implements deno.Reader {
|
|||
this.lastCharSize = -1;
|
||||
}
|
||||
|
||||
/** reads data into p.
|
||||
* It returns the number of bytes read into p.
|
||||
* The bytes are taken from at most one Read on the underlying Reader,
|
||||
* hence n may be less than len(p).
|
||||
* At EOF, the count will be zero and err will be io.EOF.
|
||||
* To read exactly len(p) bytes, use io.ReadFull(b, p).
|
||||
*/
|
||||
async read(p: ArrayBufferView): Promise<deno.ReadResult> {
|
||||
throw Error("not implemented");
|
||||
return { nread: 0, eof: false };
|
||||
let rr: deno.ReadResult = { nread: p.byteLength, eof: false };
|
||||
if (rr.nread === 0) {
|
||||
return rr;
|
||||
}
|
||||
|
||||
if (this.r === this.w) {
|
||||
/*
|
||||
if (this.err != null) {
|
||||
throw this.readErr();
|
||||
}
|
||||
*/
|
||||
if (p.byteLength >= this.buf.byteLength) {
|
||||
// Large read, empty buffer.
|
||||
// Read directly into p to avoid copy.
|
||||
rr = await this.rd.read(p);
|
||||
if (rr.nread < 0) {
|
||||
throw new ErrNegativeRead();
|
||||
}
|
||||
if (rr.nread > 0) {
|
||||
this.lastByte = p[rr.nread - 1];
|
||||
// this.lastRuneSize = -1;
|
||||
}
|
||||
return rr;
|
||||
}
|
||||
// One read.
|
||||
// Do not use this.fill, which will loop.
|
||||
this.r = 0;
|
||||
this.w = 0;
|
||||
rr = await this.rd.read(this.buf);
|
||||
if (rr.nread < 0) {
|
||||
throw new ErrNegativeRead();
|
||||
}
|
||||
if (rr.nread === 0) {
|
||||
return rr;
|
||||
}
|
||||
this.w += rr.nread;
|
||||
}
|
||||
|
||||
// copy as much as we can
|
||||
rr.nread = copyBytes(p as Uint8Array, this.buf.subarray(this.r, this.w), 0);
|
||||
this.r += rr.nread;
|
||||
this.lastByte = this.buf[this.r - 1];
|
||||
// this.lastRuneSize = -1;
|
||||
return rr;
|
||||
}
|
||||
|
||||
/** Returns the next byte [0, 255] or -1 if EOF. */
|
||||
|
@ -88,5 +150,3 @@ export class Reader implements deno.Reader {
|
|||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
// 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 * as deno from "deno";
|
||||
import { test, assertEqual } from "http://deno.land/x/testing/testing.ts";
|
||||
import * as bufio from "./bufio.ts";
|
||||
|
@ -30,3 +35,78 @@ test(async function bufioReaderSimple() {
|
|||
const s = await readBytes(b);
|
||||
assertEqual(s, data);
|
||||
});
|
||||
|
||||
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) },
|
||||
*/
|
||||
];
|
||||
|
||||
// Call read to accumulate the text of a file
|
||||
async function reads(buf: bufio.Reader, m: number): Promise<string> {
|
||||
const b = new Uint8Array(1000);
|
||||
let nb = 0;
|
||||
while (true) {
|
||||
const { nread, eof } = await buf.read(b.subarray(nb, nb + m));
|
||||
nb += nread;
|
||||
if (eof) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
const decoder = new TextDecoder();
|
||||
return decoder.decode(b.subarray(0, nb));
|
||||
}
|
||||
|
||||
type BufReader = { name: string; fn: (r: bufio.Reader) => Promise<string> };
|
||||
|
||||
const bufreaders: BufReader[] = [
|
||||
{ name: "1", fn: (b: bufio.Reader) => reads(b, 1) }
|
||||
];
|
||||
|
||||
const MIN_READ_BUFFER_SIZE = 16;
|
||||
const bufsizes: number[] = [
|
||||
0,
|
||||
MIN_READ_BUFFER_SIZE,
|
||||
23,
|
||||
32,
|
||||
46,
|
||||
64,
|
||||
93,
|
||||
128,
|
||||
1024,
|
||||
4096
|
||||
];
|
||||
|
||||
test(async function bufioReader() {
|
||||
const texts = new Array<string>(31);
|
||||
let str = "";
|
||||
let all = "";
|
||||
for (let i = 0; i < texts.length - 1; i++) {
|
||||
texts[i] = str + "\n";
|
||||
all += texts[i];
|
||||
str += String.fromCharCode(i % 26 + 97);
|
||||
}
|
||||
texts[texts.length - 1] = all;
|
||||
|
||||
for (let text of texts) {
|
||||
for (let readmaker of readMakers) {
|
||||
for (let bufreader of bufreaders) {
|
||||
for (let bufsize of bufsizes) {
|
||||
const read = readmaker.fn(stringsReader(text));
|
||||
const buf = new bufio.Reader(read, bufsize);
|
||||
const s = await bufreader.fn(buf);
|
||||
const debugStr =
|
||||
`reader=${readmaker.name} ` +
|
||||
`fn=${bufreader.name} bufsize=${bufsize} want=${text} got=${s}`;
|
||||
assertEqual(s, text, debugStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,12 +4,12 @@ import { open, cwd } from "deno";
|
|||
const addr = "0.0.0.0:4500";
|
||||
const d = cwd();
|
||||
|
||||
listenAndServe(addr, async (req) => {
|
||||
listenAndServe(addr, async req => {
|
||||
const filename = d + "/" + req.url;
|
||||
let res;
|
||||
try {
|
||||
res = { status: 200, body: open(filename) };
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
res = { status: 500, body: "bad" };
|
||||
}
|
||||
req.respond(res);
|
||||
|
|
5
http.ts
5
http.ts
|
@ -55,12 +55,12 @@ function readRequest(b: bufio.Reader): ServerRequest {
|
|||
|
||||
// First line: GET /index.html HTTP/1.0
|
||||
const s = await tp.readLine();
|
||||
const [ method, url, proto ] = parseRequestLine(s);
|
||||
const [method, url, proto] = parseRequestLine(s);
|
||||
console.log("readRequest", method, url);
|
||||
}
|
||||
|
||||
// Returns [method, url, proto]
|
||||
function parseRequestLine(line: string): [ string, string, string ] {
|
||||
function parseRequestLine(line: string): [string, string, string] {
|
||||
return line.split(" ", 3);
|
||||
}
|
||||
|
||||
|
@ -69,4 +69,3 @@ export function listen(addr: string): Server {
|
|||
const s = new Server(listener);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
13
util.ts
13
util.ts
|
@ -1,6 +1,17 @@
|
|||
|
||||
export function assert(cond: boolean, msg = "assert") {
|
||||
if (!cond) {
|
||||
throw Error(msg);
|
||||
}
|
||||
}
|
||||
|
||||
// `off` is the offset into `dst` where it will at which to begin writing values
|
||||
// from `src`.
|
||||
// Returns the number of bytes copied.
|
||||
export function copyBytes(dst: Uint8Array, src: Uint8Array, off = 0): number {
|
||||
const r = dst.byteLength - off;
|
||||
if (src.byteLength > r) {
|
||||
src = src.subarray(0, r);
|
||||
}
|
||||
dst.set(src, off);
|
||||
return src.byteLength;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue