summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--README.md9
-rw-r--r--bufio.ts37
-rw-r--r--bufio_test.ts77
4 files changed, 120 insertions, 5 deletions
diff --git a/Makefile b/Makefile
index 4b8488093..ca2135445 100644
--- a/Makefile
+++ b/Makefile
@@ -2,6 +2,6 @@ test:
deno test.ts
fmt:
- prettier *.ts --write
+ prettier *.md *.ts --write
.PHONY: test fmt
diff --git a/README.md b/README.md
index f27d51a8b..614e53087 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,12 @@
[![Build Status](https://travis-ci.com/denoland/net.svg?branch=master)](https://travis-ci.com/denoland/net)
-
Usage:
+
```typescript
-import { Reader } from "https://deno.land/x/net/bufio.ts";
-// TODO Example.
+import { serve } from "https://deno.land/x/net/http.ts";
+const s = serve("0.0.0.0:8000");
+for await (const req of s) {
+ req.respond({ body: "Hello World\n" });
+}
```
diff --git a/bufio.ts b/bufio.ts
index 3480047e9..d736e1fc4 100644
--- a/bufio.ts
+++ b/bufio.ts
@@ -47,7 +47,6 @@ export class BufReader implements Reader {
}
// Reads a new chunk into the buffer.
- // Returns true if EOF, false on successful read.
private async _fill(): Promise<void> {
// Slide existing data to beginning.
if (this.r > 0) {
@@ -287,4 +286,40 @@ export class BufReader implements Reader {
return [line, err];
}
+
+ /** Peek returns the next n bytes without advancing the reader. The bytes stop
+ * being valid at the next read call. If Peek returns fewer than n bytes, it
+ * also returns an error explaining why the read is short. The error is
+ * ErrBufferFull if n is larger than b's buffer size.
+ */
+ async peek(n: number): Promise<[Uint8Array, BufState]> {
+ if (n < 0) {
+ throw Error("negative count");
+ }
+
+ while (
+ this.w - this.r < n &&
+ this.w - this.r < this.buf.byteLength &&
+ this.err == null
+ ) {
+ await this._fill(); // this.w - this.r < len(this.buf) => buffer is not full
+ }
+
+ if (n > this.buf.byteLength) {
+ return [this.buf.subarray(this.r, this.w), "BufferFull"];
+ }
+
+ // 0 <= n <= len(this.buf)
+ let err: BufState;
+ let avail = this.w - this.r;
+ if (avail < n) {
+ // not enough data in buffer
+ n = avail;
+ err = this._readErr();
+ if (!err) {
+ err = "BufferFull";
+ }
+ }
+ return [this.buf.subarray(this.r, this.r + n), err];
+ }
}
diff --git a/bufio_test.ts b/bufio_test.ts
index 4319a337d..80068f2d3 100644
--- a/bufio_test.ts
+++ b/bufio_test.ts
@@ -217,3 +217,80 @@ test(async function bufioReadLine() {
await testReadLine(testInput);
await testReadLine(testInputrn);
});
+
+test(async function bufioPeek() {
+ const decoder = new TextDecoder();
+ let p = new Uint8Array(10);
+ // string is 16 (minReadBufferSize) long.
+ let buf = new BufReader(
+ stringsReader("abcdefghijklmnop"),
+ MIN_READ_BUFFER_SIZE
+ );
+
+ let [actual, err] = await buf.peek(1);
+ assertEqual(decoder.decode(actual), "a");
+ assert(err == null);
+
+ [actual, err] = await buf.peek(4);
+ assertEqual(decoder.decode(actual), "abcd");
+ assert(err == null);
+
+ [actual, err] = await buf.peek(32);
+ assertEqual(decoder.decode(actual), "abcdefghijklmnop");
+ assertEqual(err, "BufferFull");
+
+ await buf.read(p.subarray(0, 3));
+ assertEqual(decoder.decode(p.subarray(0, 3)), "abc");
+
+ [actual, err] = await buf.peek(1);
+ assertEqual(decoder.decode(actual), "d");
+ assert(err == null);
+
+ [actual, err] = await buf.peek(1);
+ assertEqual(decoder.decode(actual), "d");
+ assert(err == null);
+
+ [actual, err] = await buf.peek(1);
+ assertEqual(decoder.decode(actual), "d");
+ assert(err == null);
+
+ [actual, err] = await buf.peek(2);
+ assertEqual(decoder.decode(actual), "de");
+ assert(err == null);
+
+ let { eof } = await buf.read(p.subarray(0, 3));
+ assertEqual(decoder.decode(p.subarray(0, 3)), "def");
+ assert(!eof);
+ assert(err == null);
+
+ [actual, err] = await buf.peek(4);
+ assertEqual(decoder.decode(actual), "ghij");
+ assert(err == null);
+
+ await buf.read(p);
+ assertEqual(decoder.decode(p), "ghijklmnop");
+
+ [actual, err] = await buf.peek(0);
+ assertEqual(decoder.decode(actual), "");
+ assert(err == null);
+
+ [actual, err] = await buf.peek(1);
+ assertEqual(decoder.decode(actual), "");
+ assert(err == "EOF");
+ /* TODO
+ // Test for issue 3022, not exposing a reader's error on a successful Peek.
+ buf = NewReaderSize(dataAndEOFReader("abcd"), 32)
+ if s, err := buf.Peek(2); string(s) != "ab" || err != nil {
+ t.Errorf(`Peek(2) on "abcd", EOF = %q, %v; want "ab", nil`, string(s), err)
+ }
+ if s, err := buf.Peek(4); string(s) != "abcd" || err != nil {
+ t.Errorf(`Peek(4) on "abcd", EOF = %q, %v; want "abcd", nil`, string(s), err)
+ }
+ if n, err := buf.Read(p[0:5]); string(p[0:n]) != "abcd" || err != nil {
+ t.Fatalf("Read after peek = %q, %v; want abcd, EOF", p[0:n], err)
+ }
+ if n, err := buf.Read(p[0:1]); string(p[0:n]) != "" || err != io.EOF {
+ t.Fatalf(`second Read after peek = %q, %v; want "", EOF`, p[0:n], err)
+ }
+ */
+});