mirror of
https://github.com/denoland/deno.git
synced 2025-01-12 00:54:02 -05:00
BREAKING: Remove Deno.EOF, use null instead (#4953)
This commit is contained in:
parent
47c2f034e9
commit
678313b176
46 changed files with 329 additions and 325 deletions
|
@ -4,7 +4,7 @@
|
|||
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
import { Reader, Writer, EOF, ReaderSync, WriterSync } from "./io.ts";
|
||||
import { Reader, Writer, ReaderSync, WriterSync } from "./io.ts";
|
||||
import { assert } from "./util.ts";
|
||||
import { TextDecoder } from "./web/text_encoding.ts";
|
||||
|
||||
|
@ -91,7 +91,7 @@ export class Buffer implements Reader, ReaderSync, Writer, WriterSync {
|
|||
this.#buf = new Uint8Array(this.#buf.buffer, 0, len);
|
||||
};
|
||||
|
||||
readSync(p: Uint8Array): number | EOF {
|
||||
readSync(p: Uint8Array): number | null {
|
||||
if (this.empty()) {
|
||||
// Buffer is empty, reset to recover space.
|
||||
this.reset();
|
||||
|
@ -99,14 +99,14 @@ export class Buffer implements Reader, ReaderSync, Writer, WriterSync {
|
|||
// this edge case is tested in 'bufferReadEmptyAtEOF' test
|
||||
return 0;
|
||||
}
|
||||
return EOF;
|
||||
return null;
|
||||
}
|
||||
const nread = copyBytes(p, this.#buf.subarray(this.#off));
|
||||
this.#off += nread;
|
||||
return nread;
|
||||
}
|
||||
|
||||
read(p: Uint8Array): Promise<number | EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
const rr = this.readSync(p);
|
||||
return Promise.resolve(rr);
|
||||
}
|
||||
|
@ -169,7 +169,7 @@ export class Buffer implements Reader, ReaderSync, Writer, WriterSync {
|
|||
this.#reslice(i);
|
||||
const fub = new Uint8Array(this.#buf.buffer, i);
|
||||
const nread = await r.read(fub);
|
||||
if (nread === EOF) {
|
||||
if (nread === null) {
|
||||
return n;
|
||||
}
|
||||
this.#reslice(i + nread);
|
||||
|
@ -188,7 +188,7 @@ export class Buffer implements Reader, ReaderSync, Writer, WriterSync {
|
|||
this.#reslice(i);
|
||||
const fub = new Uint8Array(this.#buf.buffer, i);
|
||||
const nread = r.readSync(fub);
|
||||
if (nread === EOF) {
|
||||
if (nread === null) {
|
||||
return n;
|
||||
}
|
||||
this.#reslice(i + nread);
|
||||
|
|
|
@ -40,7 +40,6 @@ export { read, readSync, write, writeSync } from "./ops/io.ts";
|
|||
export { FsEvent, watchFs } from "./ops/fs_events.ts";
|
||||
export { internalSymbol as internal } from "./internals.ts";
|
||||
export {
|
||||
EOF,
|
||||
copy,
|
||||
iter,
|
||||
iterSync,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import {
|
||||
EOF,
|
||||
Reader,
|
||||
Writer,
|
||||
Seeker,
|
||||
|
@ -76,11 +75,11 @@ export class File
|
|||
return writeSync(this.rid, p);
|
||||
}
|
||||
|
||||
read(p: Uint8Array): Promise<number | EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
return read(this.rid, p);
|
||||
}
|
||||
|
||||
readSync(p: Uint8Array): number | EOF {
|
||||
readSync(p: Uint8Array): number | null {
|
||||
return readSync(this.rid, p);
|
||||
}
|
||||
|
||||
|
@ -103,11 +102,11 @@ class Stdin implements Reader, ReaderSync, Closer {
|
|||
this.rid = 0;
|
||||
}
|
||||
|
||||
read(p: Uint8Array): Promise<number | EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
return read(this.rid, p);
|
||||
}
|
||||
|
||||
readSync(p: Uint8Array): number | EOF {
|
||||
readSync(p: Uint8Array): number | null {
|
||||
return readSync(this.rid, p);
|
||||
}
|
||||
|
||||
|
|
13
cli/js/io.ts
13
cli/js/io.ts
|
@ -3,9 +3,6 @@
|
|||
// Documentation liberally lifted from them too.
|
||||
// Thank you! We love Go!
|
||||
|
||||
export const EOF: unique symbol = Symbol("EOF");
|
||||
export type EOF = typeof EOF;
|
||||
|
||||
const DEFAULT_BUFFER_SIZE = 32 * 1024;
|
||||
|
||||
// Seek whence values.
|
||||
|
@ -19,11 +16,11 @@ export enum SeekMode {
|
|||
// Reader is the interface that wraps the basic read() method.
|
||||
// https://golang.org/pkg/io/#Reader
|
||||
export interface Reader {
|
||||
read(p: Uint8Array): Promise<number | EOF>;
|
||||
read(p: Uint8Array): Promise<number | null>;
|
||||
}
|
||||
|
||||
export interface ReaderSync {
|
||||
readSync(p: Uint8Array): number | EOF;
|
||||
readSync(p: Uint8Array): number | null;
|
||||
}
|
||||
|
||||
// Writer is the interface that wraps the basic write() method.
|
||||
|
@ -65,7 +62,7 @@ export async function copy(
|
|||
let gotEOF = false;
|
||||
while (gotEOF === false) {
|
||||
const result = await src.read(b);
|
||||
if (result === EOF) {
|
||||
if (result === null) {
|
||||
gotEOF = true;
|
||||
} else {
|
||||
n += await dst.write(b.subarray(0, result));
|
||||
|
@ -84,7 +81,7 @@ export async function* iter(
|
|||
const b = new Uint8Array(bufSize);
|
||||
while (true) {
|
||||
const result = await r.read(b);
|
||||
if (result === EOF) {
|
||||
if (result === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -102,7 +99,7 @@ export function* iterSync(
|
|||
const b = new Uint8Array(bufSize);
|
||||
while (true) {
|
||||
const result = r.readSync(b);
|
||||
if (result === EOF) {
|
||||
if (result === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
76
cli/js/lib.deno.ns.d.ts
vendored
76
cli/js/lib.deno.ns.d.ts
vendored
|
@ -361,10 +361,6 @@ declare namespace Deno {
|
|||
*/
|
||||
export function umask(mask?: number): number;
|
||||
|
||||
/** **UNSTABLE**: might be removed in favor of `null` (#3932). */
|
||||
export const EOF: unique symbol;
|
||||
export type EOF = typeof EOF;
|
||||
|
||||
export enum SeekMode {
|
||||
Start = 0,
|
||||
Current = 1,
|
||||
|
@ -379,20 +375,21 @@ declare namespace Deno {
|
|||
* available but not `p.byteLength` bytes, `read()` conventionally resolves
|
||||
* to what is available instead of waiting for more.
|
||||
*
|
||||
* When `read()` encounters end-of-file condition, it resolves to
|
||||
* `Deno.EOF` symbol.
|
||||
* When `read()` encounters end-of-file condition, it resolves to EOF
|
||||
* (`null`).
|
||||
*
|
||||
* When `read()` encounters an error, it rejects with an error.
|
||||
*
|
||||
* Callers should always process the `n` > `0` bytes returned before
|
||||
* considering the `EOF`. Doing so correctly handles I/O errors that happen
|
||||
* after reading some bytes and also both of the allowed EOF behaviors.
|
||||
* considering the EOF (`null`). Doing so correctly handles I/O errors that
|
||||
* happen after reading some bytes and also both of the allowed EOF
|
||||
* behaviors.
|
||||
*
|
||||
* Implementations should not retain a reference to `p`.
|
||||
*
|
||||
* Use Deno.iter() to turn a Reader into an AsyncIterator.
|
||||
*/
|
||||
read(p: Uint8Array): Promise<number | EOF>;
|
||||
read(p: Uint8Array): Promise<number | null>;
|
||||
}
|
||||
|
||||
export interface ReaderSync {
|
||||
|
@ -403,20 +400,20 @@ declare namespace Deno {
|
|||
* but not `p.byteLength` bytes, `read()` conventionally returns what is
|
||||
* available instead of waiting for more.
|
||||
*
|
||||
* When `readSync()` encounters end-of-file condition, it returns `Deno.EOF`
|
||||
* symbol.
|
||||
* When `readSync()` encounters end-of-file condition, it returns EOF
|
||||
* (`null`).
|
||||
*
|
||||
* When `readSync()` encounters an error, it throws with an error.
|
||||
*
|
||||
* Callers should always process the `n` > `0` bytes returned before
|
||||
* considering the `EOF`. Doing so correctly handles I/O errors that happen
|
||||
* considering the EOF (`null`). Doing so correctly handles I/O errors that happen
|
||||
* after reading some bytes and also both of the allowed EOF behaviors.
|
||||
*
|
||||
* Implementations should not retain a reference to `p`.
|
||||
*
|
||||
* Use Deno.iterSync() to turn a ReaderSync into an Iterator.
|
||||
*/
|
||||
readSync(p: Uint8Array): number | EOF;
|
||||
readSync(p: Uint8Array): number | null;
|
||||
}
|
||||
|
||||
export interface Writer {
|
||||
|
@ -477,8 +474,8 @@ declare namespace Deno {
|
|||
seekSync(offset: number, whence: SeekMode): number;
|
||||
}
|
||||
|
||||
/** Copies from `src` to `dst` until either `EOF` is reached on `src` or an
|
||||
* error occurs. It resolves to the number of bytes copied or rejects with
|
||||
/** Copies from `src` to `dst` until either EOF (`null`) is read from `src` or
|
||||
* an error occurs. It resolves to the number of bytes copied or rejects with
|
||||
* the first error encountered while copying.
|
||||
*
|
||||
* const source = await Deno.open("my_file.txt");
|
||||
|
@ -486,9 +483,6 @@ declare namespace Deno {
|
|||
* const bytesCopied1 = await Deno.copy(source, Deno.stdout);
|
||||
* const bytesCopied2 = await Deno.copy(source, buffer);
|
||||
*
|
||||
* Because `copy()` is defined to read from `src` until `EOF`, it does not
|
||||
* treat an `EOF` from `read()` as an error to be reported.
|
||||
*
|
||||
* @param src The source to copy from
|
||||
* @param dst The destination to copy to
|
||||
* @param options Can be used to tune size of the buffer. Default size is 32kB
|
||||
|
@ -611,8 +605,11 @@ declare namespace Deno {
|
|||
|
||||
/** Synchronously read from a resource ID (`rid`) into an array buffer (`buffer`).
|
||||
*
|
||||
* Returns either the number of bytes read during the operation or End Of File
|
||||
* (`Symbol(EOF)`) if there was nothing to read.
|
||||
* Returns either the number of bytes read during the operation or EOF
|
||||
* (`null`) if there was nothing more to read.
|
||||
*
|
||||
* It is possible for a read to successfully return with `0` bytes. This does
|
||||
* not indicate EOF.
|
||||
*
|
||||
* // if "/foo/bar.txt" contains the text "hello world":
|
||||
* const file = Deno.openSync("/foo/bar.txt");
|
||||
|
@ -621,12 +618,15 @@ declare namespace Deno {
|
|||
* const text = new TextDecoder().decode(buf); // "hello world"
|
||||
* Deno.close(file.rid);
|
||||
*/
|
||||
export function readSync(rid: number, buffer: Uint8Array): number | EOF;
|
||||
export function readSync(rid: number, buffer: Uint8Array): number | null;
|
||||
|
||||
/** Read from a resource ID (`rid`) into an array buffer (`buffer`).
|
||||
*
|
||||
* Resolves to either the number of bytes read during the operation or End Of
|
||||
* File (`Symbol(EOF)`) if there was nothing to read.
|
||||
* Resolves to either the number of bytes read during the operation or EOF
|
||||
* (`null`) if there was nothing more to read.
|
||||
*
|
||||
* It is possible for a read to successfully return with `0` bytes. This does
|
||||
* not indicate EOF.
|
||||
*
|
||||
* // if "/foo/bar.txt" contains the text "hello world":
|
||||
* const file = await Deno.open("/foo/bar.txt");
|
||||
|
@ -635,7 +635,7 @@ declare namespace Deno {
|
|||
* const text = new TextDecoder().decode(buf); // "hello world"
|
||||
* Deno.close(file.rid);
|
||||
*/
|
||||
export function read(rid: number, buffer: Uint8Array): Promise<number | EOF>;
|
||||
export function read(rid: number, buffer: Uint8Array): Promise<number | null>;
|
||||
|
||||
/** Synchronously write to the resource ID (`rid`) the contents of the array
|
||||
* buffer (`data`).
|
||||
|
@ -743,8 +743,8 @@ declare namespace Deno {
|
|||
constructor(rid: number);
|
||||
write(p: Uint8Array): Promise<number>;
|
||||
writeSync(p: Uint8Array): number;
|
||||
read(p: Uint8Array): Promise<number | EOF>;
|
||||
readSync(p: Uint8Array): number | EOF;
|
||||
read(p: Uint8Array): Promise<number | null>;
|
||||
readSync(p: Uint8Array): number | null;
|
||||
seek(offset: number, whence: SeekMode): Promise<number>;
|
||||
seekSync(offset: number, whence: SeekMode): number;
|
||||
close(): void;
|
||||
|
@ -863,12 +863,12 @@ declare namespace Deno {
|
|||
reset(): void;
|
||||
/** Reads the next `p.length` bytes from the buffer or until the buffer is
|
||||
* drained. Returns the number of bytes read. If the buffer has no data to
|
||||
* return, the return is `Deno.EOF`. */
|
||||
readSync(p: Uint8Array): number | EOF;
|
||||
* return, the return is EOF (`null`). */
|
||||
readSync(p: Uint8Array): number | null;
|
||||
/** Reads the next `p.length` bytes from the buffer or until the buffer is
|
||||
* drained. Resolves to the number of bytes read. If the buffer has no
|
||||
* data to return, resolves to `Deno.EOF`. */
|
||||
read(p: Uint8Array): Promise<number | EOF>;
|
||||
* data to return, resolves to EOF (`null`). */
|
||||
read(p: Uint8Array): Promise<number | null>;
|
||||
writeSync(p: Uint8Array): number;
|
||||
write(p: Uint8Array): Promise<number>;
|
||||
/** Grows the buffer's capacity, if necessary, to guarantee space for
|
||||
|
@ -879,14 +879,14 @@ declare namespace Deno {
|
|||
* Based on Go Lang's
|
||||
* [Buffer.Grow](https://golang.org/pkg/bytes/#Buffer.Grow). */
|
||||
grow(n: number): void;
|
||||
/** Reads data from `r` until `Deno.EOF` and appends it to the buffer,
|
||||
/** Reads data from `r` until EOF (`null`) and appends it to the buffer,
|
||||
* growing the buffer as needed. It resolves to the number of bytes read.
|
||||
* If the buffer becomes too large, `.readFrom()` will reject with an error.
|
||||
*
|
||||
* Based on Go Lang's
|
||||
* [Buffer.ReadFrom](https://golang.org/pkg/bytes/#Buffer.ReadFrom). */
|
||||
readFrom(r: Reader): Promise<number>;
|
||||
/** Reads data from `r` until `Deno.EOF` and appends it to the buffer,
|
||||
/** Reads data from `r` until EOF (`null`) and appends it to the buffer,
|
||||
* growing the buffer as needed. It returns the number of bytes read. If the
|
||||
* buffer becomes too large, `.readFromSync()` will throw an error.
|
||||
*
|
||||
|
@ -895,8 +895,8 @@ declare namespace Deno {
|
|||
readFromSync(r: ReaderSync): number;
|
||||
}
|
||||
|
||||
/** Read Reader `r` until end of file (`Deno.EOF`) and resolve to the content
|
||||
* as `Uint8Array`.
|
||||
/** Read Reader `r` until EOF (`null`) and resolve to the content as
|
||||
* Uint8Array`.
|
||||
*
|
||||
* // Example from stdin
|
||||
* const stdinContent = await Deno.readAll(Deno.stdin);
|
||||
|
@ -914,8 +914,8 @@ declare namespace Deno {
|
|||
*/
|
||||
export function readAll(r: Reader): Promise<Uint8Array>;
|
||||
|
||||
/** Synchronously reads Reader `r` until end of file (`Deno.EOF`) and returns
|
||||
* the content as `Uint8Array`.
|
||||
/** Synchronously reads Reader `r` until EOF (`null`) and returns the content
|
||||
* as `Uint8Array`.
|
||||
*
|
||||
* // Example from stdin
|
||||
* const stdinContent = Deno.readAllSync(Deno.stdin);
|
||||
|
@ -2183,13 +2183,13 @@ declare namespace Deno {
|
|||
readonly stderr?: Reader & Closer;
|
||||
/** Resolves to the current status of the process. */
|
||||
status(): Promise<ProcessStatus>;
|
||||
/** Buffer the stdout and return it as `Uint8Array` after `Deno.EOF`.
|
||||
/** Buffer the stdout until EOF and return it as `Uint8Array`.
|
||||
*
|
||||
* You must set stdout to `"piped"` when creating the process.
|
||||
*
|
||||
* This calls `close()` on stdout after its done. */
|
||||
output(): Promise<Uint8Array>;
|
||||
/** Buffer the stderr and return it as `Uint8Array` after `Deno.EOF`.
|
||||
/** Buffer the stderr until EOF and return it as `Uint8Array`.
|
||||
*
|
||||
* You must set stderr to `"piped"` when creating the process.
|
||||
*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { errors } from "./errors.ts";
|
||||
import { EOF, Reader, Writer, Closer } from "./io.ts";
|
||||
import { Reader, Writer, Closer } from "./io.ts";
|
||||
import { read, write } from "./ops/io.ts";
|
||||
import { close } from "./ops/resources.ts";
|
||||
import * as netOps from "./ops/net.ts";
|
||||
|
@ -40,7 +40,7 @@ export class ConnImpl implements Conn {
|
|||
return write(this.rid, p);
|
||||
}
|
||||
|
||||
read(p: Uint8Array): Promise<number | EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
return read(this.rid, p);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
import { sendAsyncMinimal, sendSyncMinimal } from "./dispatch_minimal.ts";
|
||||
import { EOF } from "../io.ts";
|
||||
// TODO(bartlomieju): remove this import and maybe lazy-initialize
|
||||
// OPS_CACHE that belongs only to this module
|
||||
import { OPS_CACHE } from "../runtime.ts";
|
||||
|
@ -10,7 +9,7 @@ import { OPS_CACHE } from "../runtime.ts";
|
|||
let OP_READ = -1;
|
||||
let OP_WRITE = -1;
|
||||
|
||||
export function readSync(rid: number, buffer: Uint8Array): number | EOF {
|
||||
export function readSync(rid: number, buffer: Uint8Array): number | null {
|
||||
if (buffer.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -21,7 +20,7 @@ export function readSync(rid: number, buffer: Uint8Array): number | EOF {
|
|||
if (nread < 0) {
|
||||
throw new Error("read error");
|
||||
} else if (nread == 0) {
|
||||
return EOF;
|
||||
return null;
|
||||
} else {
|
||||
return nread;
|
||||
}
|
||||
|
@ -30,7 +29,7 @@ export function readSync(rid: number, buffer: Uint8Array): number | EOF {
|
|||
export async function read(
|
||||
rid: number,
|
||||
buffer: Uint8Array
|
||||
): Promise<number | EOF> {
|
||||
): Promise<number | null> {
|
||||
if (buffer.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,7 +40,7 @@ export async function read(
|
|||
if (nread < 0) {
|
||||
throw new Error("read error");
|
||||
} else if (nread == 0) {
|
||||
return EOF;
|
||||
return null;
|
||||
} else {
|
||||
return nread;
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ async function empty(buf: Buffer, s: string, fub: Uint8Array): Promise<void> {
|
|||
check(buf, s);
|
||||
while (true) {
|
||||
const r = await buf.read(fub);
|
||||
if (r === Deno.EOF) {
|
||||
if (r === null) {
|
||||
break;
|
||||
}
|
||||
s = s.slice(r);
|
||||
|
@ -231,8 +231,7 @@ unitTest(async function bufferTestGrow(): Promise<void> {
|
|||
for (const growLen of [0, 100, 1000, 10000, 100000]) {
|
||||
const buf = new Buffer(xBytes.buffer as ArrayBuffer);
|
||||
// If we read, this affects buf.off, which is good to test.
|
||||
const result = await buf.read(tmp);
|
||||
const nread = result === Deno.EOF ? 0 : result;
|
||||
const nread = (await buf.read(tmp)) ?? 0;
|
||||
buf.grow(growLen);
|
||||
const yBytes = repeat("y", growLen);
|
||||
await buf.write(yBytes);
|
||||
|
|
|
@ -101,13 +101,13 @@ unitTest(async function readerIter(): Promise<void> {
|
|||
this.#buf = new Uint8Array(encoder.encode(s));
|
||||
}
|
||||
|
||||
read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
const n = Math.min(p.byteLength, this.#buf.byteLength - this.#offset);
|
||||
p.set(this.#buf.slice(this.#offset, this.#offset + n));
|
||||
this.#offset += n;
|
||||
|
||||
if (n === 0) {
|
||||
return Promise.resolve(Deno.EOF);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
return Promise.resolve(n);
|
||||
|
@ -136,13 +136,13 @@ unitTest(async function readerIterSync(): Promise<void> {
|
|||
this.#buf = new Uint8Array(encoder.encode(s));
|
||||
}
|
||||
|
||||
readSync(p: Uint8Array): number | Deno.EOF {
|
||||
readSync(p: Uint8Array): number | null {
|
||||
const n = Math.min(p.byteLength, this.#buf.byteLength - this.#offset);
|
||||
p.set(this.#buf.slice(this.#offset, this.#offset + n));
|
||||
this.#offset += n;
|
||||
|
||||
if (n === 0) {
|
||||
return Deno.EOF;
|
||||
return null;
|
||||
}
|
||||
|
||||
return n;
|
||||
|
|
|
@ -19,7 +19,7 @@ function spyRead(obj: Deno.Buffer): Spy {
|
|||
|
||||
const orig = obj.read.bind(obj);
|
||||
|
||||
obj.read = (p: Uint8Array): Promise<number | Deno.EOF> => {
|
||||
obj.read = (p: Uint8Array): Promise<number | null> => {
|
||||
spy.calls++;
|
||||
return orig(p);
|
||||
};
|
||||
|
|
|
@ -179,10 +179,10 @@ unitTest({ perms: { net: true } }, async function netTcpDialListen(): Promise<
|
|||
assertEquals(3, buf[2]);
|
||||
assert(conn.rid > 0);
|
||||
|
||||
assert(readResult !== Deno.EOF);
|
||||
assert(readResult !== null);
|
||||
|
||||
const readResult2 = await conn.read(buf);
|
||||
assertEquals(Deno.EOF, readResult2);
|
||||
assertEquals(readResult2, null);
|
||||
|
||||
listener.close();
|
||||
conn.close();
|
||||
|
@ -214,10 +214,10 @@ unitTest(
|
|||
assertEquals(3, buf[2]);
|
||||
assert(conn.rid > 0);
|
||||
|
||||
assert(readResult !== Deno.EOF);
|
||||
assert(readResult !== null);
|
||||
|
||||
const readResult2 = await conn.read(buf);
|
||||
assertEquals(Deno.EOF, readResult2);
|
||||
assertEquals(readResult2, null);
|
||||
|
||||
listener.close();
|
||||
conn.close();
|
||||
|
@ -358,10 +358,10 @@ unitTest(
|
|||
assertEquals(3, buf[2]);
|
||||
assert(conn.rid > 0);
|
||||
|
||||
assert(readResult !== Deno.EOF);
|
||||
assert(readResult !== null);
|
||||
|
||||
const readResult2 = await conn.read(buf);
|
||||
assertEquals(Deno.EOF, readResult2);
|
||||
assertEquals(readResult2, null);
|
||||
|
||||
listener.close();
|
||||
conn.close();
|
||||
|
@ -396,7 +396,7 @@ unitTest(
|
|||
closeReadDeferred.resolve();
|
||||
const buf = new Uint8Array(1024);
|
||||
const readResult = await conn.read(buf);
|
||||
assertEquals(Deno.EOF, readResult); // with immediate EOF
|
||||
assertEquals(readResult, null); // with immediate EOF
|
||||
// Ensure closeRead does not impact write
|
||||
await conn.write(new Uint8Array([4, 5, 6]));
|
||||
await closeDeferred;
|
||||
|
@ -523,7 +523,7 @@ unitTest(
|
|||
try {
|
||||
while (true) {
|
||||
const nread = await conn.read(p);
|
||||
if (nread === Deno.EOF) {
|
||||
if (nread === null) {
|
||||
break;
|
||||
}
|
||||
await conn.write(new Uint8Array([1, 2, 3]));
|
||||
|
|
|
@ -154,14 +154,14 @@ unitTest({ perms: { run: true } }, async function runStdoutPiped(): Promise<
|
|||
|
||||
const data = new Uint8Array(10);
|
||||
let r = await p.stdout!.read(data);
|
||||
if (r === Deno.EOF) {
|
||||
throw new Error("p.stdout.read(...) should not be EOF");
|
||||
if (r === null) {
|
||||
throw new Error("p.stdout.read(...) should not be null");
|
||||
}
|
||||
assertEquals(r, 5);
|
||||
const s = new TextDecoder().decode(data.subarray(0, r));
|
||||
assertEquals(s, "hello");
|
||||
r = await p.stdout!.read(data);
|
||||
assertEquals(r, Deno.EOF);
|
||||
assertEquals(r, null);
|
||||
p.stdout!.close();
|
||||
|
||||
const status = await p.status();
|
||||
|
@ -183,14 +183,14 @@ unitTest({ perms: { run: true } }, async function runStderrPiped(): Promise<
|
|||
|
||||
const data = new Uint8Array(10);
|
||||
let r = await p.stderr!.read(data);
|
||||
if (r === Deno.EOF) {
|
||||
throw new Error("p.stderr.read should not return EOF here");
|
||||
if (r === null) {
|
||||
throw new Error("p.stderr.read should not return null here");
|
||||
}
|
||||
assertEquals(r, 5);
|
||||
const s = new TextDecoder().decode(data.subarray(0, r));
|
||||
assertEquals(s, "hello");
|
||||
r = await p.stderr!.read(data);
|
||||
assertEquals(r, Deno.EOF);
|
||||
assertEquals(r, null);
|
||||
p.stderr!.close();
|
||||
|
||||
const status = await p.status();
|
||||
|
@ -313,7 +313,7 @@ unitTest({ perms: { run: true } }, async function runClose(): Promise<void> {
|
|||
|
||||
const data = new Uint8Array(10);
|
||||
const r = await p.stderr!.read(data);
|
||||
assertEquals(r, Deno.EOF);
|
||||
assertEquals(r, null);
|
||||
p.stderr!.close();
|
||||
});
|
||||
|
||||
|
|
|
@ -191,7 +191,7 @@ unitTest(
|
|||
await w.flush();
|
||||
const tpr = new TextProtoReader(r);
|
||||
const statusLine = await tpr.readLine();
|
||||
assert(statusLine !== Deno.EOF, `line must be read: ${String(statusLine)}`);
|
||||
assert(statusLine !== null, `line must be read: ${String(statusLine)}`);
|
||||
const m = statusLine.match(/^(.+?) (.+?) (.+?)$/);
|
||||
assert(m !== null, "must be matched");
|
||||
const [_, proto, status, ok] = m;
|
||||
|
@ -199,7 +199,7 @@ unitTest(
|
|||
assertEquals(status, "200");
|
||||
assertEquals(ok, "OK");
|
||||
const headers = await tpr.readMIMEHeader();
|
||||
assert(headers !== Deno.EOF);
|
||||
assert(headers !== null);
|
||||
const contentLength = parseInt(headers.get("content-length")!);
|
||||
const bodyBuf = new Uint8Array(contentLength);
|
||||
await r.readFull(bodyBuf);
|
||||
|
@ -225,7 +225,7 @@ unitTest(
|
|||
let writer = new BufWriter(conn);
|
||||
let reader = new TextProtoReader(new BufReader(conn));
|
||||
|
||||
let line: string | Deno.EOF = (await reader.readLine()) as string;
|
||||
let line: string | null = (await reader.readLine()) as string;
|
||||
assert(line.startsWith("220"));
|
||||
|
||||
await writer.write(encoder.encode(`EHLO ${hostname}\r\n`));
|
||||
|
|
|
@ -220,7 +220,7 @@ class Body
|
|||
return decoder.decode(ab);
|
||||
}
|
||||
|
||||
read(p: Uint8Array): Promise<number | io.EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
this.#bodyUsed = true;
|
||||
return read(this.#rid, p);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ Deno.stdout.writeSync(new TextEncoder().encode("S"));
|
|||
const buf = new Uint8Array(3);
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const nread = await Deno.stdin.read(buf);
|
||||
if (nread === Deno.EOF) {
|
||||
if (nread === null) {
|
||||
break;
|
||||
} else {
|
||||
const data = new TextDecoder().decode(buf.subarray(0, nread));
|
||||
|
|
|
@ -41,12 +41,12 @@ class FileReader implements Deno.Reader {
|
|||
|
||||
constructor(private filePath: string) {}
|
||||
|
||||
public async read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
public async read(p: Uint8Array): Promise<number | null> {
|
||||
if (!this.file) {
|
||||
this.file = await Deno.open(this.filePath, { read: true });
|
||||
}
|
||||
const res = await Deno.read(this.file.rid, p);
|
||||
if (res === Deno.EOF) {
|
||||
if (res === null) {
|
||||
Deno.close(this.file.rid);
|
||||
this.file = undefined;
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ Available Functions:
|
|||
```typescript
|
||||
sizeof(dataType: RawTypes): number
|
||||
getNBytes(r: Deno.Reader, n: number): Promise<Uint8Array>
|
||||
varnum(b: Uint8Array, o: VarnumOptions = {}): number | Deno.EOF
|
||||
varbig(b: Uint8Array, o: VarbigOptions = {}): bigint | Deno.EOF
|
||||
varnum(b: Uint8Array, o: VarnumOptions = {}): number | null
|
||||
varbig(b: Uint8Array, o: VarbigOptions = {}): bigint | null
|
||||
putVarnum(b: Uint8Array, x: number, o: VarnumOptions = {}): number
|
||||
putVarbig(b: Uint8Array, x: bigint, o: VarbigOptions = {}): number
|
||||
readVarnum(r: Deno.Reader, o: VarnumOptions = {}): Promise<number>
|
||||
|
|
|
@ -51,19 +51,16 @@ export async function getNBytes(
|
|||
): Promise<Uint8Array> {
|
||||
const scratch = new Uint8Array(n);
|
||||
const nRead = await r.read(scratch);
|
||||
if (nRead === Deno.EOF || nRead < n) throw new Deno.errors.UnexpectedEof();
|
||||
if (nRead === null || nRead < n) throw new Deno.errors.UnexpectedEof();
|
||||
return scratch;
|
||||
}
|
||||
|
||||
/** Decode a number from `b`, and return it as a `number`. Data-type defaults to `int32`.
|
||||
* Returns `EOF` if `b` is too short for the data-type given in `o`. */
|
||||
export function varnum(
|
||||
b: Uint8Array,
|
||||
o: VarnumOptions = {}
|
||||
): number | Deno.EOF {
|
||||
* Returns `null` if `b` is too short for the data-type given in `o`. */
|
||||
export function varnum(b: Uint8Array, o: VarnumOptions = {}): number | null {
|
||||
o.dataType = o.dataType ?? "int32";
|
||||
const littleEndian = (o.endian ?? "big") === "little" ? true : false;
|
||||
if (b.length < sizeof(o.dataType)) return Deno.EOF;
|
||||
if (b.length < sizeof(o.dataType)) return null;
|
||||
const view = new DataView(b.buffer);
|
||||
switch (o.dataType) {
|
||||
case "int8":
|
||||
|
@ -86,14 +83,11 @@ export function varnum(
|
|||
}
|
||||
|
||||
/** Decode an integer from `b`, and return it as a `bigint`. Data-type defaults to `int64`.
|
||||
* Returns `EOF` if `b` is too short for the data-type given in `o`. */
|
||||
export function varbig(
|
||||
b: Uint8Array,
|
||||
o: VarbigOptions = {}
|
||||
): bigint | Deno.EOF {
|
||||
* Returns `null` if `b` is too short for the data-type given in `o`. */
|
||||
export function varbig(b: Uint8Array, o: VarbigOptions = {}): bigint | null {
|
||||
o.dataType = o.dataType ?? "int64";
|
||||
const littleEndian = (o.endian ?? "big") === "little" ? true : false;
|
||||
if (b.length < sizeof(o.dataType)) return Deno.EOF;
|
||||
if (b.length < sizeof(o.dataType)) return null;
|
||||
const view = new DataView(b.buffer);
|
||||
switch (o.dataType) {
|
||||
case "int8":
|
||||
|
|
|
@ -64,12 +64,12 @@ async function readRecord(
|
|||
Startline: number,
|
||||
reader: BufReader,
|
||||
opt: ReadOptions = { comma: ",", trimLeadingSpace: false }
|
||||
): Promise<string[] | Deno.EOF> {
|
||||
): Promise<string[] | null> {
|
||||
const tp = new TextProtoReader(reader);
|
||||
const lineIndex = Startline;
|
||||
let line = await readLine(tp);
|
||||
|
||||
if (line === Deno.EOF) return Deno.EOF;
|
||||
if (line === null) return null;
|
||||
if (line.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
@ -147,7 +147,7 @@ async function readRecord(
|
|||
// Hit end of line (copy all data so far).
|
||||
recordBuffer += line;
|
||||
const r = await readLine(tp);
|
||||
if (r === Deno.EOF) {
|
||||
if (r === null) {
|
||||
if (!opt.lazyQuotes) {
|
||||
quoteError = ERR_QUOTE;
|
||||
break parseField;
|
||||
|
@ -182,13 +182,13 @@ async function readRecord(
|
|||
}
|
||||
|
||||
async function isEOF(tp: TextProtoReader): Promise<boolean> {
|
||||
return (await tp.r.peek(0)) === Deno.EOF;
|
||||
return (await tp.r.peek(0)) === null;
|
||||
}
|
||||
|
||||
async function readLine(tp: TextProtoReader): Promise<string | Deno.EOF> {
|
||||
async function readLine(tp: TextProtoReader): Promise<string | null> {
|
||||
let line: string;
|
||||
const r = await tp.readLine();
|
||||
if (r === Deno.EOF) return Deno.EOF;
|
||||
if (r === null) return null;
|
||||
line = r;
|
||||
|
||||
// For backwards compatibility, drop trailing \r before EOF.
|
||||
|
@ -226,7 +226,7 @@ export async function readMatrix(
|
|||
|
||||
for (;;) {
|
||||
const r = await readRecord(lineIndex, reader, opt);
|
||||
if (r === Deno.EOF) break;
|
||||
if (r === null) break;
|
||||
lineResult = r;
|
||||
lineIndex++;
|
||||
// If fieldsPerRecord is 0, Read sets it to
|
||||
|
|
|
@ -17,7 +17,7 @@ async function startServer(): Promise<Deno.Process> {
|
|||
assert(server.stdout != null);
|
||||
const r = new TextProtoReader(new BufReader(server.stdout));
|
||||
const s = await r.readLine();
|
||||
assert(s !== Deno.EOF && s.includes("chat server starting"));
|
||||
assert(s !== null && s.includes("chat server starting"));
|
||||
} catch (err) {
|
||||
server.stdout!.close();
|
||||
server.close();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/env -S deno --allow-net --allow-env
|
||||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { parse } from "https://deno.land/std/flags/mod.ts";
|
||||
import { parse } from "../flags/mod.ts";
|
||||
|
||||
function pathBase(p: string): string {
|
||||
const parts = p.split("/");
|
||||
|
|
|
@ -16,7 +16,7 @@ Deno.test("[examples/echo_server]", async () => {
|
|||
const processReader = new BufReader(process.stdout!);
|
||||
const message = await processReader.readLine();
|
||||
|
||||
assertNotEquals(message, Deno.EOF);
|
||||
assertNotEquals(message, null);
|
||||
assertStrictEq(
|
||||
decoder.decode((message as ReadLineResult).line).trim(),
|
||||
"Listening on 0.0.0.0:8080"
|
||||
|
@ -28,7 +28,7 @@ Deno.test("[examples/echo_server]", async () => {
|
|||
await conn.write(encoder.encode("Hello echo_server\n"));
|
||||
const result = await connReader.readLine();
|
||||
|
||||
assertNotEquals(result, Deno.EOF);
|
||||
assertNotEquals(result, null);
|
||||
|
||||
const actualResponse = decoder
|
||||
.decode((result as ReadLineResult).line)
|
||||
|
|
|
@ -25,7 +25,7 @@ async function startFileServer(): Promise<void> {
|
|||
assert(fileServer.stdout != null);
|
||||
const r = new TextProtoReader(new BufReader(fileServer.stdout));
|
||||
const s = await r.readLine();
|
||||
assert(s !== Deno.EOF && s.includes("server listening"));
|
||||
assert(s !== null && s.includes("server listening"));
|
||||
}
|
||||
|
||||
function killFileServer(): void {
|
||||
|
@ -114,7 +114,7 @@ test("servePermissionDenied", async function (): Promise<void> {
|
|||
assert(deniedServer.stderr != null);
|
||||
const errReader = new TextProtoReader(new BufReader(deniedServer.stderr));
|
||||
const s = await reader.readLine();
|
||||
assert(s !== Deno.EOF && s.includes("server listening"));
|
||||
assert(s !== null && s.includes("server listening"));
|
||||
|
||||
try {
|
||||
const res = await fetch("http://localhost:4500/");
|
||||
|
@ -138,7 +138,7 @@ test("printHelp", async function (): Promise<void> {
|
|||
assert(helpProcess.stdout != null);
|
||||
const r = new TextProtoReader(new BufReader(helpProcess.stdout));
|
||||
const s = await r.readLine();
|
||||
assert(s !== Deno.EOF && s.includes("Deno File Server"));
|
||||
assert(s !== null && s.includes("Deno File Server"));
|
||||
helpProcess.close();
|
||||
helpProcess.stdout.close();
|
||||
});
|
||||
|
|
|
@ -7,8 +7,8 @@ import { STATUS_TEXT } from "./http_status.ts";
|
|||
|
||||
export function emptyReader(): Deno.Reader {
|
||||
return {
|
||||
read(_: Uint8Array): Promise<number | Deno.EOF> {
|
||||
return Promise.resolve(Deno.EOF);
|
||||
read(_: Uint8Array): Promise<number | null> {
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -16,9 +16,9 @@ export function emptyReader(): Deno.Reader {
|
|||
export function bodyReader(contentLength: number, r: BufReader): Deno.Reader {
|
||||
let totalRead = 0;
|
||||
let finished = false;
|
||||
async function read(buf: Uint8Array): Promise<number | Deno.EOF> {
|
||||
if (finished) return Deno.EOF;
|
||||
let result: number | Deno.EOF;
|
||||
async function read(buf: Uint8Array): Promise<number | null> {
|
||||
if (finished) return null;
|
||||
let result: number | null;
|
||||
const remaining = contentLength - totalRead;
|
||||
if (remaining >= buf.byteLength) {
|
||||
result = await r.read(buf);
|
||||
|
@ -26,7 +26,7 @@ export function bodyReader(contentLength: number, r: BufReader): Deno.Reader {
|
|||
const readBuf = buf.subarray(0, remaining);
|
||||
result = await r.read(readBuf);
|
||||
}
|
||||
if (result !== Deno.EOF) {
|
||||
if (result !== null) {
|
||||
totalRead += result;
|
||||
}
|
||||
finished = totalRead === contentLength;
|
||||
|
@ -43,8 +43,8 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
|||
offset: number;
|
||||
data: Uint8Array;
|
||||
}> = [];
|
||||
async function read(buf: Uint8Array): Promise<number | Deno.EOF> {
|
||||
if (finished) return Deno.EOF;
|
||||
async function read(buf: Uint8Array): Promise<number | null> {
|
||||
if (finished) return null;
|
||||
const [chunk] = chunks;
|
||||
if (chunk) {
|
||||
const chunkRemaining = chunk.data.byteLength - chunk.offset;
|
||||
|
@ -56,14 +56,14 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
|||
if (chunk.offset === chunk.data.byteLength) {
|
||||
chunks.shift();
|
||||
// Consume \r\n;
|
||||
if ((await tp.readLine()) === Deno.EOF) {
|
||||
if ((await tp.readLine()) === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
}
|
||||
return readLength;
|
||||
}
|
||||
const line = await tp.readLine();
|
||||
if (line === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||
if (line === null) throw new Deno.errors.UnexpectedEof();
|
||||
// TODO: handle chunk extension
|
||||
const [chunkSizeString] = line.split(";");
|
||||
const chunkSize = parseInt(chunkSizeString, 16);
|
||||
|
@ -73,12 +73,12 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
|||
if (chunkSize > 0) {
|
||||
if (chunkSize > buf.byteLength) {
|
||||
let eof = await r.readFull(buf);
|
||||
if (eof === Deno.EOF) {
|
||||
if (eof === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
const restChunk = new Uint8Array(chunkSize - buf.byteLength);
|
||||
eof = await r.readFull(restChunk);
|
||||
if (eof === Deno.EOF) {
|
||||
if (eof === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
} else {
|
||||
chunks.push({
|
||||
|
@ -90,11 +90,11 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
|||
} else {
|
||||
const bufToFill = buf.subarray(0, chunkSize);
|
||||
const eof = await r.readFull(bufToFill);
|
||||
if (eof === Deno.EOF) {
|
||||
if (eof === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
// Consume \r\n
|
||||
if ((await tp.readLine()) === Deno.EOF) {
|
||||
if ((await tp.readLine()) === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
return chunkSize;
|
||||
|
@ -102,12 +102,12 @@ export function chunkedBodyReader(h: Headers, r: BufReader): Deno.Reader {
|
|||
} else {
|
||||
assert(chunkSize === 0);
|
||||
// Consume \r\n
|
||||
if ((await r.readLine()) === Deno.EOF) {
|
||||
if ((await r.readLine()) === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
await readTrailers(h, r);
|
||||
finished = true;
|
||||
return Deno.EOF;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return { read };
|
||||
|
@ -131,7 +131,7 @@ export async function readTrailers(
|
|||
if (!keys) return;
|
||||
const tp = new TextProtoReader(r);
|
||||
const result = await tp.readMIMEHeader();
|
||||
assert(result != Deno.EOF, "trailer must be set");
|
||||
assert(result !== null, "trailer must be set");
|
||||
for (const [k, v] of result) {
|
||||
if (!keys.has(k)) {
|
||||
throw new Error("Undeclared trailer field");
|
||||
|
@ -332,12 +332,12 @@ export function parseHTTPVersion(vers: string): [number, number] {
|
|||
export async function readRequest(
|
||||
conn: Deno.Conn,
|
||||
bufr: BufReader
|
||||
): Promise<ServerRequest | Deno.EOF> {
|
||||
): Promise<ServerRequest | null> {
|
||||
const tp = new TextProtoReader(bufr);
|
||||
const firstLine = await tp.readLine(); // e.g. GET /index.html HTTP/1.0
|
||||
if (firstLine === Deno.EOF) return Deno.EOF;
|
||||
if (firstLine === null) return null;
|
||||
const headers = await tp.readMIMEHeader();
|
||||
if (headers === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||
if (headers === null) throw new Deno.errors.UnexpectedEof();
|
||||
|
||||
const req = new ServerRequest();
|
||||
req.conn = conn;
|
||||
|
|
|
@ -3,7 +3,6 @@ import {
|
|||
assertThrowsAsync,
|
||||
assertEquals,
|
||||
assert,
|
||||
assertNotEOF,
|
||||
assertNotEquals,
|
||||
} from "../testing/asserts.ts";
|
||||
import {
|
||||
|
@ -43,11 +42,11 @@ test("chunkedBodyReader", async () => {
|
|||
].join("");
|
||||
const h = new Headers();
|
||||
const r = chunkedBodyReader(h, new BufReader(new Buffer(encode(body))));
|
||||
let result: number | Deno.EOF;
|
||||
let result: number | null;
|
||||
// Use small buffer as some chunks exceed buffer size
|
||||
const buf = new Uint8Array(5);
|
||||
const dest = new Buffer();
|
||||
while ((result = await r.read(buf)) !== Deno.EOF) {
|
||||
while ((result = await r.read(buf)) !== null) {
|
||||
const len = Math.min(buf.byteLength, result);
|
||||
await dest.write(buf.subarray(0, len));
|
||||
}
|
||||
|
@ -223,25 +222,28 @@ test("writeUint8ArrayResponse", async function (): Promise<void> {
|
|||
const decoder = new TextDecoder("utf-8");
|
||||
const reader = new BufReader(buf);
|
||||
|
||||
let r: ReadLineResult;
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
let r: ReadLineResult | null = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), "HTTP/1.1 200 OK");
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), `content-length: ${shortText.length}`);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(r.line.byteLength, 0);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), shortText);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
const eof = await reader.readLine();
|
||||
assertEquals(eof, Deno.EOF);
|
||||
assertEquals(eof, null);
|
||||
});
|
||||
|
||||
test("writeStringResponse", async function (): Promise<void> {
|
||||
|
@ -255,25 +257,28 @@ test("writeStringResponse", async function (): Promise<void> {
|
|||
const decoder = new TextDecoder("utf-8");
|
||||
const reader = new BufReader(buf);
|
||||
|
||||
let r: ReadLineResult;
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
let r: ReadLineResult | null = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), "HTTP/1.1 200 OK");
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), `content-length: ${body.length}`);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(r.line.byteLength, 0);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), body);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
const eof = await reader.readLine();
|
||||
assertEquals(eof, Deno.EOF);
|
||||
assertEquals(eof, null);
|
||||
});
|
||||
|
||||
test("writeStringReaderResponse", async function (): Promise<void> {
|
||||
|
@ -288,28 +293,33 @@ test("writeStringReaderResponse", async function (): Promise<void> {
|
|||
const decoder = new TextDecoder("utf-8");
|
||||
const reader = new BufReader(buf);
|
||||
|
||||
let r: ReadLineResult;
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
let r: ReadLineResult | null = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), "HTTP/1.1 200 OK");
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), "transfer-encoding: chunked");
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(r.line.byteLength, 0);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), shortText.length.toString());
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), shortText);
|
||||
assertEquals(r.more, false);
|
||||
|
||||
r = assertNotEOF(await reader.readLine());
|
||||
r = await reader.readLine();
|
||||
assert(r !== null);
|
||||
assertEquals(decoder.decode(r.line), "0");
|
||||
assertEquals(r.more, false);
|
||||
});
|
||||
|
@ -372,7 +382,7 @@ test("testReadRequestError", async function (): Promise<void> {
|
|||
in: "GET / HTTP/1.1\r\nheader:foo\r\n",
|
||||
err: Deno.errors.UnexpectedEof,
|
||||
},
|
||||
{ in: "", err: Deno.EOF },
|
||||
{ in: "", eof: true },
|
||||
{
|
||||
in: "HEAD / HTTP/1.1\r\nContent-Length:4\r\n\r\n",
|
||||
err: "http: method cannot contain a Content-Length",
|
||||
|
@ -427,14 +437,14 @@ test("testReadRequestError", async function (): Promise<void> {
|
|||
for (const test of testCases) {
|
||||
const reader = new BufReader(new StringReader(test.in));
|
||||
let err;
|
||||
let req: ServerRequest | Deno.EOF | undefined;
|
||||
let req: ServerRequest | null = null;
|
||||
try {
|
||||
req = await readRequest(mockConn(), reader);
|
||||
} catch (e) {
|
||||
err = e;
|
||||
}
|
||||
if (test.err === Deno.EOF) {
|
||||
assertEquals(req, Deno.EOF);
|
||||
if (test.eof) {
|
||||
assertEquals(req, null);
|
||||
} else if (typeof test.err === "string") {
|
||||
assertEquals(err.message, test.err);
|
||||
} else if (test.err) {
|
||||
|
@ -443,7 +453,7 @@ test("testReadRequestError", async function (): Promise<void> {
|
|||
assert(req instanceof ServerRequest);
|
||||
assert(test.headers);
|
||||
assertEquals(err, undefined);
|
||||
assertNotEquals(req, Deno.EOF);
|
||||
assertNotEquals(req, null);
|
||||
for (const h of test.headers) {
|
||||
assertEquals(req.headers.get(h.key), h.value);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ export function mockConn(base: Partial<Deno.Conn> = {}): Deno.Conn {
|
|||
rid: -1,
|
||||
closeRead: (): void => {},
|
||||
closeWrite: (): void => {},
|
||||
read: (): Promise<number | Deno.EOF> => {
|
||||
read: (): Promise<number | null> => {
|
||||
return Promise.resolve(0);
|
||||
},
|
||||
write: (): Promise<number> => {
|
||||
|
|
|
@ -13,7 +13,7 @@ async function startServer(): Promise<void> {
|
|||
assert(server.stdout != null);
|
||||
const r = new TextProtoReader(new BufReader(server.stdout));
|
||||
const s = await r.readLine();
|
||||
assert(s !== Deno.EOF && s.includes("Racing server listening..."));
|
||||
assert(s !== null && s.includes("Racing server listening..."));
|
||||
}
|
||||
function killServer(): void {
|
||||
server.close();
|
||||
|
|
|
@ -60,7 +60,7 @@ export class ServerRequest {
|
|||
* let totRead = 0;
|
||||
* while (true) {
|
||||
* const nread = await req.body.read(bufSlice);
|
||||
* if (nread === Deno.EOF) break;
|
||||
* if (nread === null) break;
|
||||
* totRead += nread;
|
||||
* if (totRead >= req.contentLength) break;
|
||||
* bufSlice = bufSlice.subarray(nread);
|
||||
|
@ -117,7 +117,7 @@ export class ServerRequest {
|
|||
// Consume unread body
|
||||
const body = this.body;
|
||||
const buf = new Uint8Array(1024);
|
||||
while ((await body.read(buf)) !== Deno.EOF) {}
|
||||
while ((await body.read(buf)) !== null) {}
|
||||
this.finalized = true;
|
||||
}
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ export class Server implements AsyncIterable<ServerRequest> {
|
|||
const writer = new BufWriter(conn);
|
||||
|
||||
while (!this.closing) {
|
||||
let request: ServerRequest | Deno.EOF;
|
||||
let request: ServerRequest | null;
|
||||
try {
|
||||
request = await readRequest(conn, reader);
|
||||
} catch (error) {
|
||||
|
@ -167,7 +167,7 @@ export class Server implements AsyncIterable<ServerRequest> {
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (request == Deno.EOF) {
|
||||
if (request === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,6 @@ import {
|
|||
assert,
|
||||
assertEquals,
|
||||
assertMatch,
|
||||
assertNotEOF,
|
||||
assertStrContains,
|
||||
assertThrowsAsync,
|
||||
} from "../testing/asserts.ts";
|
||||
|
@ -108,7 +107,7 @@ interface TotalReader extends Deno.Reader {
|
|||
}
|
||||
function totalReader(r: Deno.Reader): TotalReader {
|
||||
let _total = 0;
|
||||
async function read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
async function read(p: Uint8Array): Promise<number | null> {
|
||||
const result = await r.read(p);
|
||||
if (typeof result === "number") {
|
||||
_total += result;
|
||||
|
@ -252,13 +251,13 @@ test("requestBodyReaderWithContentLength", async function (): Promise<void> {
|
|||
let offset = 0;
|
||||
while (offset < shortText.length) {
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertNotEOF(nread);
|
||||
assert(nread !== null);
|
||||
const s = decode(readBuf.subarray(0, nread as number));
|
||||
assertEquals(shortText.substr(offset, nread as number), s);
|
||||
offset += nread as number;
|
||||
}
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertEquals(nread, Deno.EOF);
|
||||
assertEquals(nread, null);
|
||||
}
|
||||
|
||||
// Larger than given buf
|
||||
|
@ -273,13 +272,13 @@ test("requestBodyReaderWithContentLength", async function (): Promise<void> {
|
|||
let offset = 0;
|
||||
while (offset < longText.length) {
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertNotEOF(nread);
|
||||
assert(nread !== null);
|
||||
const s = decode(readBuf.subarray(0, nread as number));
|
||||
assertEquals(longText.substr(offset, nread as number), s);
|
||||
offset += nread as number;
|
||||
}
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertEquals(nread, Deno.EOF);
|
||||
assertEquals(nread, null);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -307,13 +306,13 @@ test("requestBodyReaderWithTransferEncoding", async function (): Promise<void> {
|
|||
let offset = 0;
|
||||
while (offset < shortText.length) {
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertNotEOF(nread);
|
||||
assert(nread !== null);
|
||||
const s = decode(readBuf.subarray(0, nread as number));
|
||||
assertEquals(shortText.substr(offset, nread as number), s);
|
||||
offset += nread as number;
|
||||
}
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertEquals(nread, Deno.EOF);
|
||||
assertEquals(nread, null);
|
||||
}
|
||||
|
||||
// Larger than internal buf
|
||||
|
@ -340,13 +339,13 @@ test("requestBodyReaderWithTransferEncoding", async function (): Promise<void> {
|
|||
let offset = 0;
|
||||
while (offset < longText.length) {
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertNotEOF(nread);
|
||||
assert(nread !== null);
|
||||
const s = decode(readBuf.subarray(0, nread as number));
|
||||
assertEquals(longText.substr(offset, nread as number), s);
|
||||
offset += nread as number;
|
||||
}
|
||||
const nread = await req.body.read(readBuf);
|
||||
assertEquals(nread, Deno.EOF);
|
||||
assertEquals(nread, null);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -372,7 +371,7 @@ test({
|
|||
try {
|
||||
const r = new TextProtoReader(new BufReader(p.stdout!));
|
||||
const s = await r.readLine();
|
||||
assert(s !== Deno.EOF && s.includes("server listening"));
|
||||
assert(s !== null && s.includes("server listening"));
|
||||
await delay(100);
|
||||
// Reqeusts to the server and immediately closes the connection
|
||||
const conn = await Deno.connect({ port: 4502 });
|
||||
|
@ -419,7 +418,7 @@ test({
|
|||
const r = new TextProtoReader(new BufReader(p.stdout!));
|
||||
const s = await r.readLine();
|
||||
assert(
|
||||
s !== Deno.EOF && s.includes("server listening"),
|
||||
s !== null && s.includes("server listening"),
|
||||
"server must be started"
|
||||
);
|
||||
// Requests to the server and immediately closes the connection
|
||||
|
@ -433,7 +432,8 @@ test({
|
|||
new TextEncoder().encode("GET / HTTP/1.0\r\n\r\n")
|
||||
);
|
||||
const res = new Uint8Array(100);
|
||||
const nread = assertNotEOF(await conn.read(res));
|
||||
const nread = await conn.read(res);
|
||||
assert(nread !== null);
|
||||
conn.close();
|
||||
const resStr = new TextDecoder().decode(res.subarray(0, nread));
|
||||
assert(resStr.includes("Hello HTTPS"));
|
||||
|
@ -476,7 +476,7 @@ test({
|
|||
);
|
||||
const res = new Uint8Array(100);
|
||||
const nread = await conn.read(res);
|
||||
assert(nread !== Deno.EOF);
|
||||
assert(nread !== null);
|
||||
const resStr = new TextDecoder().decode(res.subarray(0, nread));
|
||||
assertStrContains(resStr, "/hello");
|
||||
server.close();
|
||||
|
|
|
@ -83,7 +83,7 @@ export class BufReader implements Reader {
|
|||
// Read new data: try a limited number of times.
|
||||
for (let i = MAX_CONSECUTIVE_EMPTY_READS; i > 0; i--) {
|
||||
const rr = await this.rd.read(this.buf.subarray(this.w));
|
||||
if (rr === Deno.EOF) {
|
||||
if (rr === null) {
|
||||
this.eof = true;
|
||||
return;
|
||||
}
|
||||
|
@ -120,8 +120,8 @@ export class BufReader implements Reader {
|
|||
* hence n may be less than len(p).
|
||||
* To read exactly len(p) bytes, use io.ReadFull(b, p).
|
||||
*/
|
||||
async read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
let rr: number | Deno.EOF = p.byteLength;
|
||||
async read(p: Uint8Array): Promise<number | null> {
|
||||
let rr: number | null = p.byteLength;
|
||||
if (p.byteLength === 0) return rr;
|
||||
|
||||
if (this.r === this.w) {
|
||||
|
@ -129,7 +129,7 @@ export class BufReader implements Reader {
|
|||
// Large read, empty buffer.
|
||||
// Read directly into p to avoid copy.
|
||||
const rr = await this.rd.read(p);
|
||||
const nread = rr === Deno.EOF ? 0 : rr;
|
||||
const nread = rr ?? 0;
|
||||
assert(nread >= 0, "negative read");
|
||||
// if (rr.nread > 0) {
|
||||
// this.lastByte = p[rr.nread - 1];
|
||||
|
@ -143,7 +143,7 @@ export class BufReader implements Reader {
|
|||
this.r = 0;
|
||||
this.w = 0;
|
||||
rr = await this.rd.read(this.buf);
|
||||
if (rr === 0 || rr === Deno.EOF) return rr;
|
||||
if (rr === 0 || rr === null) return rr;
|
||||
assert(rr >= 0, "negative read");
|
||||
this.w += rr;
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ export class BufReader implements Reader {
|
|||
* If successful, `p` is returned.
|
||||
*
|
||||
* If the end of the underlying stream has been reached, and there are no more
|
||||
* bytes available in the buffer, `readFull()` returns `EOF` instead.
|
||||
* bytes available in the buffer, `readFull()` returns `null` instead.
|
||||
*
|
||||
* An error is thrown if some bytes could be read, but not enough to fill `p`
|
||||
* entirely before the underlying stream reported an error or EOF. Any error
|
||||
|
@ -170,14 +170,14 @@ export class BufReader implements Reader {
|
|||
*
|
||||
* Ported from https://golang.org/pkg/io/#ReadFull
|
||||
*/
|
||||
async readFull(p: Uint8Array): Promise<Uint8Array | Deno.EOF> {
|
||||
async readFull(p: Uint8Array): Promise<Uint8Array | null> {
|
||||
let bytesRead = 0;
|
||||
while (bytesRead < p.length) {
|
||||
try {
|
||||
const rr = await this.read(p.subarray(bytesRead));
|
||||
if (rr === Deno.EOF) {
|
||||
if (rr === null) {
|
||||
if (bytesRead === 0) {
|
||||
return Deno.EOF;
|
||||
return null;
|
||||
} else {
|
||||
throw new PartialReadError();
|
||||
}
|
||||
|
@ -191,10 +191,10 @@ export class BufReader implements Reader {
|
|||
return p;
|
||||
}
|
||||
|
||||
/** Returns the next byte [0, 255] or `EOF`. */
|
||||
async readByte(): Promise<number | Deno.EOF> {
|
||||
/** Returns the next byte [0, 255] or `null`. */
|
||||
async readByte(): Promise<number | null> {
|
||||
while (this.r === this.w) {
|
||||
if (this.eof) return Deno.EOF;
|
||||
if (this.eof) return null;
|
||||
await this._fill(); // buffer is empty.
|
||||
}
|
||||
const c = this.buf[this.r];
|
||||
|
@ -207,17 +207,17 @@ export class BufReader implements Reader {
|
|||
* 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).
|
||||
* (often `null`).
|
||||
* 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 | Deno.EOF> {
|
||||
async readString(delim: string): Promise<string | null> {
|
||||
if (delim.length !== 1) {
|
||||
throw new Error("Delimiter should be a single character");
|
||||
}
|
||||
const buffer = await this.readSlice(delim.charCodeAt(0));
|
||||
if (buffer == Deno.EOF) return Deno.EOF;
|
||||
if (buffer === null) return null;
|
||||
return new TextDecoder().decode(buffer);
|
||||
}
|
||||
|
||||
|
@ -237,14 +237,14 @@ export class BufReader implements Reader {
|
|||
* When the end of the underlying stream is reached, the final bytes in the
|
||||
* stream are returned. No indication or error is given if the input ends
|
||||
* without a final line end. When there are no more trailing bytes to read,
|
||||
* `readLine()` returns the `EOF` symbol.
|
||||
* `readLine()` returns `null`.
|
||||
*
|
||||
* Calling `unreadByte()` after `readLine()` will always unread the last byte
|
||||
* read (possibly a character belonging to the line end) even if that byte is
|
||||
* not part of the line returned by `readLine()`.
|
||||
*/
|
||||
async readLine(): Promise<ReadLineResult | Deno.EOF> {
|
||||
let line: Uint8Array | Deno.EOF;
|
||||
async readLine(): Promise<ReadLineResult | null> {
|
||||
let line: Uint8Array | null;
|
||||
|
||||
try {
|
||||
line = await this.readSlice(LF);
|
||||
|
@ -277,8 +277,8 @@ export class BufReader implements Reader {
|
|||
return { line: partial, more: !this.eof };
|
||||
}
|
||||
|
||||
if (line === Deno.EOF) {
|
||||
return Deno.EOF;
|
||||
if (line === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (line.byteLength === 0) {
|
||||
|
@ -306,12 +306,12 @@ export class BufReader implements Reader {
|
|||
* If `readSlice()` encounters the end of the underlying stream and there are
|
||||
* any bytes left in the buffer, the rest of the buffer is returned. In other
|
||||
* words, EOF is always treated as a delimiter. Once the buffer is empty,
|
||||
* it returns `EOF`.
|
||||
* it returns `null`.
|
||||
*
|
||||
* Because the data returned from `readSlice()` will be overwritten by the
|
||||
* next I/O operation, most clients should use `readString()` instead.
|
||||
*/
|
||||
async readSlice(delim: number): Promise<Uint8Array | Deno.EOF> {
|
||||
async readSlice(delim: number): Promise<Uint8Array | null> {
|
||||
let s = 0; // search start index
|
||||
let slice: Uint8Array | undefined;
|
||||
|
||||
|
@ -328,7 +328,7 @@ export class BufReader implements Reader {
|
|||
// EOF?
|
||||
if (this.eof) {
|
||||
if (this.r === this.w) {
|
||||
return Deno.EOF;
|
||||
return null;
|
||||
}
|
||||
slice = this.buf.subarray(this.r, this.w);
|
||||
this.r = this.w;
|
||||
|
@ -367,13 +367,13 @@ export class BufReader implements Reader {
|
|||
*
|
||||
* When the end of the underlying stream is reached, but there are unread
|
||||
* bytes left in the buffer, those bytes are returned. If there are no bytes
|
||||
* left in the buffer, it returns `EOF`.
|
||||
* left in the buffer, it returns `null`.
|
||||
*
|
||||
* If an error is encountered before `n` bytes are available, `peek()` throws
|
||||
* an error with the `partial` property set to a slice of the buffer that
|
||||
* contains the bytes that were available before the error occurred.
|
||||
*/
|
||||
async peek(n: number): Promise<Uint8Array | Deno.EOF> {
|
||||
async peek(n: number): Promise<Uint8Array | null> {
|
||||
if (n < 0) {
|
||||
throw Error("negative count");
|
||||
}
|
||||
|
@ -390,7 +390,7 @@ export class BufReader implements Reader {
|
|||
}
|
||||
|
||||
if (avail === 0 && this.eof) {
|
||||
return Deno.EOF;
|
||||
return null;
|
||||
} else if (avail < n && this.eof) {
|
||||
return this.buf.subarray(this.r, this.r + avail);
|
||||
} else if (avail < n) {
|
||||
|
@ -656,7 +656,7 @@ export async function* readDelim(
|
|||
let matchIndex = 0;
|
||||
while (true) {
|
||||
const result = await reader.read(inspectArr);
|
||||
if (result === Deno.EOF) {
|
||||
if (result === null) {
|
||||
// Yield last chunk.
|
||||
yield inputBuffer.bytes();
|
||||
return;
|
||||
|
|
|
@ -5,12 +5,7 @@
|
|||
|
||||
const { Buffer } = Deno;
|
||||
type Reader = Deno.Reader;
|
||||
import {
|
||||
assert,
|
||||
assertEquals,
|
||||
fail,
|
||||
assertNotEOF,
|
||||
} from "../testing/asserts.ts";
|
||||
import { assert, assertEquals, fail } from "../testing/asserts.ts";
|
||||
import {
|
||||
BufReader,
|
||||
BufWriter,
|
||||
|
@ -30,7 +25,7 @@ async function readBytes(buf: BufReader): Promise<string> {
|
|||
let nb = 0;
|
||||
while (true) {
|
||||
const c = await buf.readByte();
|
||||
if (c === Deno.EOF) {
|
||||
if (c === null) {
|
||||
break; // EOF
|
||||
}
|
||||
b[nb] = c;
|
||||
|
@ -69,7 +64,7 @@ async function reads(buf: BufReader, m: number): Promise<string> {
|
|||
let nb = 0;
|
||||
while (true) {
|
||||
const result = await buf.read(b.subarray(nb, nb + m));
|
||||
if (result === Deno.EOF) {
|
||||
if (result === null) {
|
||||
break;
|
||||
}
|
||||
nb += result;
|
||||
|
@ -152,7 +147,8 @@ Deno.test("bufioBufferFull", async function (): Promise<void> {
|
|||
assertEquals(decoder.decode(err.partial), "And now, hello, ");
|
||||
}
|
||||
|
||||
const line = assertNotEOF(await buf.readSlice(charCode("!")));
|
||||
const line = await buf.readSlice(charCode("!"));
|
||||
assert(line !== null);
|
||||
const actual = decoder.decode(line);
|
||||
assertEquals(actual, "world!");
|
||||
});
|
||||
|
@ -161,14 +157,16 @@ Deno.test("bufioReadString", async function (): Promise<void> {
|
|||
const string = "And now, hello world!";
|
||||
const buf = new BufReader(stringsReader(string), MIN_READ_BUFFER_SIZE);
|
||||
|
||||
const line = assertNotEOF(await buf.readString(","));
|
||||
const line = await buf.readString(",");
|
||||
assert(line !== null);
|
||||
assertEquals(line, "And now,");
|
||||
assertEquals(line.length, 8);
|
||||
|
||||
const line2 = assertNotEOF(await buf.readString(","));
|
||||
const line2 = await buf.readString(",");
|
||||
assert(line2 !== null);
|
||||
assertEquals(line2, " hello world!");
|
||||
|
||||
assertEquals(await buf.readString(","), Deno.EOF);
|
||||
assertEquals(await buf.readString(","), null);
|
||||
|
||||
try {
|
||||
await buf.readString("deno");
|
||||
|
@ -192,7 +190,7 @@ const testOutput = encoder.encode("0123456789abcdefghijklmnopqrstuvwxy");
|
|||
class TestReader implements Reader {
|
||||
constructor(private data: Uint8Array, private stride: number) {}
|
||||
|
||||
read(buf: Uint8Array): Promise<number | Deno.EOF> {
|
||||
read(buf: Uint8Array): Promise<number | null> {
|
||||
let nread = this.stride;
|
||||
if (nread > this.data.byteLength) {
|
||||
nread = this.data.byteLength;
|
||||
|
@ -201,7 +199,7 @@ class TestReader implements Reader {
|
|||
nread = buf.byteLength;
|
||||
}
|
||||
if (nread === 0) {
|
||||
return Promise.resolve(Deno.EOF);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
copyBytes(buf as Uint8Array, this.data);
|
||||
this.data = this.data.subarray(nread);
|
||||
|
@ -216,7 +214,7 @@ async function testReadLine(input: Uint8Array): Promise<void> {
|
|||
const l = new BufReader(reader, input.byteLength + 1);
|
||||
while (true) {
|
||||
const r = await l.readLine();
|
||||
if (r === Deno.EOF) {
|
||||
if (r === null) {
|
||||
break;
|
||||
}
|
||||
const { line, more } = r;
|
||||
|
@ -253,10 +251,12 @@ Deno.test("bufioPeek", async function (): Promise<void> {
|
|||
MIN_READ_BUFFER_SIZE
|
||||
);
|
||||
|
||||
let actual = assertNotEOF(await buf.peek(1));
|
||||
let actual = await buf.peek(1);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "a");
|
||||
|
||||
actual = assertNotEOF(await buf.peek(4));
|
||||
actual = await buf.peek(4);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "abcd");
|
||||
|
||||
try {
|
||||
|
@ -271,33 +271,39 @@ Deno.test("bufioPeek", async function (): Promise<void> {
|
|||
await buf.read(p.subarray(0, 3));
|
||||
assertEquals(decoder.decode(p.subarray(0, 3)), "abc");
|
||||
|
||||
actual = assertNotEOF(await buf.peek(1));
|
||||
actual = await buf.peek(1);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "d");
|
||||
|
||||
actual = assertNotEOF(await buf.peek(1));
|
||||
actual = await buf.peek(1);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "d");
|
||||
|
||||
actual = assertNotEOF(await buf.peek(1));
|
||||
actual = await buf.peek(1);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "d");
|
||||
|
||||
actual = assertNotEOF(await buf.peek(2));
|
||||
actual = await buf.peek(2);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "de");
|
||||
|
||||
const res = await buf.read(p.subarray(0, 3));
|
||||
assertEquals(decoder.decode(p.subarray(0, 3)), "def");
|
||||
assert(res !== Deno.EOF);
|
||||
assert(res !== null);
|
||||
|
||||
actual = assertNotEOF(await buf.peek(4));
|
||||
actual = await buf.peek(4);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "ghij");
|
||||
|
||||
await buf.read(p);
|
||||
assertEquals(decoder.decode(p), "ghijklmnop");
|
||||
|
||||
actual = assertNotEOF(await buf.peek(0));
|
||||
actual = await buf.peek(0);
|
||||
assert(actual !== null);
|
||||
assertEquals(decoder.decode(actual), "");
|
||||
|
||||
const r = await buf.peek(1);
|
||||
assert(r === Deno.EOF);
|
||||
assert(r === null);
|
||||
/* TODO
|
||||
Test for issue 3022, not exposing a reader's error on a successful Peek.
|
||||
buf = NewReaderSize(dataAndEOFReader("abcd"), 32)
|
||||
|
@ -396,7 +402,8 @@ Deno.test("bufReaderReadFull", async function (): Promise<void> {
|
|||
const bufr = new BufReader(data, 3);
|
||||
{
|
||||
const buf = new Uint8Array(6);
|
||||
const r = assertNotEOF(await bufr.readFull(buf));
|
||||
const r = await bufr.readFull(buf);
|
||||
assert(r !== null);
|
||||
assertEquals(r, buf);
|
||||
assertEquals(dec.decode(buf), "Hello ");
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ type Reader = Deno.Reader;
|
|||
export class OneByteReader implements Reader {
|
||||
constructor(readonly r: Reader) {}
|
||||
|
||||
read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
if (p.byteLength === 0) {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ export class OneByteReader implements Reader {
|
|||
export class HalfReader implements Reader {
|
||||
constructor(readonly r: Reader) {}
|
||||
|
||||
read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
if (!(p instanceof Uint8Array)) {
|
||||
throw Error("expected Uint8Array");
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ export class TimeoutReader implements Reader {
|
|||
count = 0;
|
||||
constructor(readonly r: Reader) {}
|
||||
|
||||
read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
this.count++;
|
||||
if (this.count === 2) {
|
||||
throw new Deno.errors.TimedOut();
|
||||
|
|
|
@ -21,13 +21,13 @@ export async function copyN(
|
|||
buf = new Uint8Array(size - bytesRead);
|
||||
}
|
||||
const result = await r.read(buf);
|
||||
const nread = result === Deno.EOF ? 0 : result;
|
||||
const nread = result ?? 0;
|
||||
bytesRead += nread;
|
||||
if (nread > 0) {
|
||||
const n = await dest.write(buf.slice(0, nread));
|
||||
assert(n === nread, "could not write");
|
||||
}
|
||||
if (result === Deno.EOF) {
|
||||
if (result === null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -35,31 +35,31 @@ export async function copyN(
|
|||
}
|
||||
|
||||
/** Read big endian 16bit short from BufReader */
|
||||
export async function readShort(buf: BufReader): Promise<number | Deno.EOF> {
|
||||
export async function readShort(buf: BufReader): Promise<number | null> {
|
||||
const high = await buf.readByte();
|
||||
if (high === Deno.EOF) return Deno.EOF;
|
||||
if (high === null) return null;
|
||||
const low = await buf.readByte();
|
||||
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||
if (low === null) throw new Deno.errors.UnexpectedEof();
|
||||
return (high << 8) | low;
|
||||
}
|
||||
|
||||
/** Read big endian 32bit integer from BufReader */
|
||||
export async function readInt(buf: BufReader): Promise<number | Deno.EOF> {
|
||||
export async function readInt(buf: BufReader): Promise<number | null> {
|
||||
const high = await readShort(buf);
|
||||
if (high === Deno.EOF) return Deno.EOF;
|
||||
if (high === null) return null;
|
||||
const low = await readShort(buf);
|
||||
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||
if (low === null) throw new Deno.errors.UnexpectedEof();
|
||||
return (high << 16) | low;
|
||||
}
|
||||
|
||||
const MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
|
||||
|
||||
/** Read big endian 64bit long from BufReader */
|
||||
export async function readLong(buf: BufReader): Promise<number | Deno.EOF> {
|
||||
export async function readLong(buf: BufReader): Promise<number | null> {
|
||||
const high = await readInt(buf);
|
||||
if (high === Deno.EOF) return Deno.EOF;
|
||||
if (high === null) return null;
|
||||
const low = await readInt(buf);
|
||||
if (low === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||
if (low === null) throw new Deno.errors.UnexpectedEof();
|
||||
const big = (BigInt(high) << 32n) | BigInt(low);
|
||||
// We probably should provide a similar API that returns BigInt values.
|
||||
if (big > MAX_SAFE_INTEGER) {
|
||||
|
|
|
@ -17,7 +17,7 @@ class BinaryReader implements Reader {
|
|||
|
||||
constructor(private bytes: Uint8Array = new Uint8Array(0)) {}
|
||||
|
||||
read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
p.set(this.bytes.subarray(this.index, p.byteLength));
|
||||
this.index += p.byteLength;
|
||||
return Promise.resolve(p.byteLength);
|
||||
|
|
|
@ -9,12 +9,12 @@ export class StringReader implements Reader {
|
|||
|
||||
constructor(private readonly s: string) {}
|
||||
|
||||
read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
read(p: Uint8Array): Promise<number | null> {
|
||||
const n = Math.min(p.byteLength, this.buf.byteLength - this.offs);
|
||||
p.set(this.buf.slice(this.offs, this.offs + n));
|
||||
this.offs += n;
|
||||
if (n === 0) {
|
||||
return Promise.resolve(Deno.EOF);
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
return Promise.resolve(n);
|
||||
}
|
||||
|
@ -29,11 +29,11 @@ export class MultiReader implements Reader {
|
|||
this.readers = readers;
|
||||
}
|
||||
|
||||
async read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
async read(p: Uint8Array): Promise<number | null> {
|
||||
const r = this.readers[this.currentIndex];
|
||||
if (!r) return Deno.EOF;
|
||||
if (!r) return null;
|
||||
const result = await r.read(p);
|
||||
if (result === Deno.EOF) {
|
||||
if (result === null) {
|
||||
this.currentIndex++;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ test("ioStringReader", async function (): Promise<void> {
|
|||
const res0 = await r.read(new Uint8Array(6));
|
||||
assertEquals(res0, 6);
|
||||
const res1 = await r.read(new Uint8Array(6));
|
||||
assertEquals(res1, Deno.EOF);
|
||||
assertEquals(res1, null);
|
||||
});
|
||||
|
||||
test("ioStringReader", async function (): Promise<void> {
|
||||
|
@ -23,7 +23,7 @@ test("ioStringReader", async function (): Promise<void> {
|
|||
assertEquals(res2, 3);
|
||||
assertEquals(decode(buf), "def");
|
||||
const res3 = await r.read(buf);
|
||||
assertEquals(res3, Deno.EOF);
|
||||
assertEquals(res3, null);
|
||||
assertEquals(decode(buf), "def");
|
||||
});
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ export function scanUntilBoundary(
|
|||
newLineDashBoundary: Uint8Array,
|
||||
total: number,
|
||||
eof: boolean
|
||||
): number | Deno.EOF {
|
||||
): number | null {
|
||||
if (total === 0) {
|
||||
// At beginning of body, allow dashBoundary.
|
||||
if (hasPrefix(buf, dashBoundary)) {
|
||||
|
@ -115,7 +115,7 @@ export function scanUntilBoundary(
|
|||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return Deno.EOF;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (hasPrefix(dashBoundary, buf)) {
|
||||
|
@ -132,7 +132,7 @@ export function scanUntilBoundary(
|
|||
case 0:
|
||||
return i;
|
||||
case 1:
|
||||
return i > 0 ? i : Deno.EOF;
|
||||
return i > 0 ? i : null;
|
||||
}
|
||||
}
|
||||
if (hasPrefix(newLineDashBoundary, buf)) {
|
||||
|
@ -151,12 +151,12 @@ export function scanUntilBoundary(
|
|||
}
|
||||
|
||||
class PartReader implements Reader, Closer {
|
||||
n: number | Deno.EOF = 0;
|
||||
n: number | null = 0;
|
||||
total = 0;
|
||||
|
||||
constructor(private mr: MultipartReader, public readonly headers: Headers) {}
|
||||
|
||||
async read(p: Uint8Array): Promise<number | Deno.EOF> {
|
||||
async read(p: Uint8Array): Promise<number | null> {
|
||||
const br = this.mr.bufReader;
|
||||
|
||||
// Read into buffer until we identify some data to return,
|
||||
|
@ -165,7 +165,7 @@ class PartReader implements Reader, Closer {
|
|||
while (this.n === 0) {
|
||||
peekLength = max(peekLength, br.buffered());
|
||||
const peekBuf = await br.peek(peekLength);
|
||||
if (peekBuf === Deno.EOF) {
|
||||
if (peekBuf === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
const eof = peekBuf.length < peekLength;
|
||||
|
@ -183,8 +183,8 @@ class PartReader implements Reader, Closer {
|
|||
}
|
||||
}
|
||||
|
||||
if (this.n === Deno.EOF) {
|
||||
return Deno.EOF;
|
||||
if (this.n === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nread = min(p.length, this.n);
|
||||
|
@ -288,7 +288,7 @@ export class MultipartReader {
|
|||
const buf = new Buffer(new Uint8Array(maxValueBytes));
|
||||
for (;;) {
|
||||
const p = await this.nextPart();
|
||||
if (p === Deno.EOF) {
|
||||
if (p === null) {
|
||||
break;
|
||||
}
|
||||
if (p.formName === "") {
|
||||
|
@ -354,7 +354,7 @@ export class MultipartReader {
|
|||
private currentPart: PartReader | undefined;
|
||||
private partsRead = 0;
|
||||
|
||||
private async nextPart(): Promise<PartReader | Deno.EOF> {
|
||||
private async nextPart(): Promise<PartReader | null> {
|
||||
if (this.currentPart) {
|
||||
this.currentPart.close();
|
||||
}
|
||||
|
@ -364,14 +364,14 @@ export class MultipartReader {
|
|||
let expectNewPart = false;
|
||||
for (;;) {
|
||||
const line = await this.bufReader.readSlice("\n".charCodeAt(0));
|
||||
if (line === Deno.EOF) {
|
||||
if (line === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
if (this.isBoundaryDelimiterLine(line)) {
|
||||
this.partsRead++;
|
||||
const r = new TextProtoReader(this.bufReader);
|
||||
const headers = await r.readMIMEHeader();
|
||||
if (headers === Deno.EOF) {
|
||||
if (headers === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
const np = new PartReader(this, headers);
|
||||
|
@ -379,7 +379,7 @@ export class MultipartReader {
|
|||
return np;
|
||||
}
|
||||
if (this.isFinalBoundary(line)) {
|
||||
return Deno.EOF;
|
||||
return null;
|
||||
}
|
||||
if (expectNewPart) {
|
||||
throw new Error(`expecting a new Part; got line ${line}`);
|
||||
|
|
|
@ -31,7 +31,7 @@ test("multipartScanUntilBoundary1", function (): void {
|
|||
0,
|
||||
true
|
||||
);
|
||||
assertEquals(n, Deno.EOF);
|
||||
assertEquals(n, null);
|
||||
});
|
||||
|
||||
test("multipartScanUntilBoundary2", function (): void {
|
||||
|
|
|
@ -379,8 +379,3 @@ export function unimplemented(msg?: string): never {
|
|||
export function unreachable(): never {
|
||||
throw new AssertionError("unreachable");
|
||||
}
|
||||
|
||||
export function assertNotEOF<T extends {}>(val: T | Deno.EOF): T {
|
||||
assertNotEquals(val, Deno.EOF);
|
||||
return val as T;
|
||||
}
|
||||
|
|
|
@ -22,9 +22,9 @@ export class TextProtoReader {
|
|||
/** readLine() reads a single line from the TextProtoReader,
|
||||
* eliding the final \n or \r\n from the returned string.
|
||||
*/
|
||||
async readLine(): Promise<string | Deno.EOF> {
|
||||
async readLine(): Promise<string | null> {
|
||||
const s = await this.readLineSlice();
|
||||
if (s === Deno.EOF) return Deno.EOF;
|
||||
if (s === null) return null;
|
||||
return str(s);
|
||||
}
|
||||
|
||||
|
@ -48,20 +48,20 @@ export class TextProtoReader {
|
|||
* "Long-Key": {"Even Longer Value"},
|
||||
* }
|
||||
*/
|
||||
async readMIMEHeader(): Promise<Headers | Deno.EOF> {
|
||||
async readMIMEHeader(): Promise<Headers | null> {
|
||||
const m = new Headers();
|
||||
let line: Uint8Array | undefined;
|
||||
|
||||
// The first line cannot start with a leading space.
|
||||
let buf = await this.r.peek(1);
|
||||
if (buf === Deno.EOF) {
|
||||
return Deno.EOF;
|
||||
if (buf === null) {
|
||||
return null;
|
||||
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
|
||||
line = (await this.readLineSlice()) as Uint8Array;
|
||||
}
|
||||
|
||||
buf = await this.r.peek(1);
|
||||
if (buf === Deno.EOF) {
|
||||
if (buf === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
} else if (buf[0] == charCode(" ") || buf[0] == charCode("\t")) {
|
||||
throw new Deno.errors.InvalidData(
|
||||
|
@ -71,7 +71,7 @@ export class TextProtoReader {
|
|||
|
||||
while (true) {
|
||||
const kv = await this.readLineSlice(); // readContinuedLineSlice
|
||||
if (kv === Deno.EOF) throw new Deno.errors.UnexpectedEof();
|
||||
if (kv === null) throw new Deno.errors.UnexpectedEof();
|
||||
if (kv.byteLength === 0) return m;
|
||||
|
||||
// Key ends at first colon
|
||||
|
@ -112,12 +112,12 @@ export class TextProtoReader {
|
|||
}
|
||||
}
|
||||
|
||||
async readLineSlice(): Promise<Uint8Array | Deno.EOF> {
|
||||
async readLineSlice(): Promise<Uint8Array | null> {
|
||||
// this.closeDot();
|
||||
let line: Uint8Array | undefined;
|
||||
while (true) {
|
||||
const r = await this.r.readLine();
|
||||
if (r === Deno.EOF) return Deno.EOF;
|
||||
if (r === null) return null;
|
||||
const { line: l, more } = r;
|
||||
|
||||
// Avoid the copy if the first call produced a full line.
|
||||
|
|
|
@ -6,12 +6,7 @@
|
|||
import { BufReader } from "../io/bufio.ts";
|
||||
import { TextProtoReader } from "./mod.ts";
|
||||
import { stringsReader } from "../io/util.ts";
|
||||
import {
|
||||
assert,
|
||||
assertEquals,
|
||||
assertThrows,
|
||||
assertNotEOF,
|
||||
} from "../testing/asserts.ts";
|
||||
import { assert, assertEquals, assertThrows } from "../testing/asserts.ts";
|
||||
const { test } = Deno;
|
||||
|
||||
function reader(s: string): TextProtoReader {
|
||||
|
@ -31,7 +26,7 @@ test({
|
|||
test("[textproto] ReadEmpty", async () => {
|
||||
const r = reader("");
|
||||
const m = await r.readMIMEHeader();
|
||||
assertEquals(m, Deno.EOF);
|
||||
assertEquals(m, null);
|
||||
});
|
||||
|
||||
test("[textproto] Reader", async () => {
|
||||
|
@ -43,7 +38,7 @@ test("[textproto] Reader", async () => {
|
|||
assertEquals(s, "line2");
|
||||
|
||||
s = await r.readLine();
|
||||
assert(s === Deno.EOF);
|
||||
assert(s === null);
|
||||
});
|
||||
|
||||
test({
|
||||
|
@ -53,7 +48,8 @@ test({
|
|||
"my-key: Value 1 \r\nLong-key: Even Longer Value\r\nmy-Key: " +
|
||||
"Value 2\r\n\n";
|
||||
const r = reader(input);
|
||||
const m = assertNotEOF(await r.readMIMEHeader());
|
||||
const m = await r.readMIMEHeader();
|
||||
assert(m !== null);
|
||||
assertEquals(m.get("My-Key"), "Value 1, Value 2");
|
||||
assertEquals(m.get("Long-key"), "Even Longer Value");
|
||||
},
|
||||
|
@ -64,7 +60,8 @@ test({
|
|||
async fn(): Promise<void> {
|
||||
const input = "Foo: bar\n\n";
|
||||
const r = reader(input);
|
||||
const m = assertNotEOF(await r.readMIMEHeader());
|
||||
const m = await r.readMIMEHeader();
|
||||
assert(m !== null);
|
||||
assertEquals(m.get("Foo"), "bar");
|
||||
},
|
||||
});
|
||||
|
@ -74,7 +71,8 @@ test({
|
|||
async fn(): Promise<void> {
|
||||
const input = ": bar\ntest-1: 1\n\n";
|
||||
const r = reader(input);
|
||||
const m = assertNotEOF(await r.readMIMEHeader());
|
||||
const m = await r.readMIMEHeader();
|
||||
assert(m !== null);
|
||||
assertEquals(m.get("Test-1"), "1");
|
||||
},
|
||||
});
|
||||
|
@ -89,7 +87,8 @@ test({
|
|||
}
|
||||
const sdata = data.join("");
|
||||
const r = reader(`Cookie: ${sdata}\r\n\r\n`);
|
||||
const m = assertNotEOF(await r.readMIMEHeader());
|
||||
const m = await r.readMIMEHeader();
|
||||
assert(m !== null);
|
||||
assertEquals(m.get("Cookie"), sdata);
|
||||
},
|
||||
});
|
||||
|
@ -106,7 +105,8 @@ test({
|
|||
"Audio Mode : None\r\n" +
|
||||
"Privilege : 127\r\n\r\n";
|
||||
const r = reader(input);
|
||||
const m = assertNotEOF(await r.readMIMEHeader());
|
||||
const m = await r.readMIMEHeader();
|
||||
assert(m !== null);
|
||||
assertEquals(m.get("Foo"), "bar");
|
||||
assertEquals(m.get("Content-Language"), "en");
|
||||
// Make sure we drop headers with trailing whitespace
|
||||
|
@ -174,7 +174,8 @@ test({
|
|||
"------WebKitFormBoundaryimeZ2Le9LjohiUiG--\r\n\n",
|
||||
];
|
||||
const r = reader(input.join(""));
|
||||
const m = assertNotEOF(await r.readMIMEHeader());
|
||||
const m = await r.readMIMEHeader();
|
||||
assert(m !== null);
|
||||
assertEquals(m.get("Accept"), "*/*");
|
||||
assertEquals(m.get("Content-Disposition"), 'form-data; name="test"');
|
||||
},
|
||||
|
|
|
@ -102,7 +102,7 @@ const tpr = new TextProtoReader(new BufReader(Deno.stdin));
|
|||
while (true) {
|
||||
await Deno.stdout.write(encode("> "));
|
||||
const line = await tpr.readLine();
|
||||
if (line === Deno.EOF) {
|
||||
if (line === null) {
|
||||
break;
|
||||
}
|
||||
if (line === "close") {
|
||||
|
|
|
@ -31,7 +31,7 @@ const tpr = new TextProtoReader(new BufReader(Deno.stdin));
|
|||
while (true) {
|
||||
await Deno.stdout.write(encode("> "));
|
||||
const line = await tpr.readLine();
|
||||
if (line === Deno.EOF) {
|
||||
if (line === null) {
|
||||
break;
|
||||
}
|
||||
if (line === "close") {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { Sha1 } from "../util/sha1.ts";
|
|||
import { writeResponse } from "../http/io.ts";
|
||||
import { TextProtoReader } from "../textproto/mod.ts";
|
||||
import { Deferred, deferred } from "../util/async.ts";
|
||||
import { assertNotEOF } from "../testing/asserts.ts";
|
||||
import { assert } from "../testing/asserts.ts";
|
||||
import { concat } from "../bytes/mod.ts";
|
||||
import Conn = Deno.Conn;
|
||||
import Writer = Deno.Writer;
|
||||
|
@ -149,7 +149,8 @@ export async function writeFrame(
|
|||
* @throws `Error` Frame is invalid
|
||||
*/
|
||||
export async function readFrame(buf: BufReader): Promise<WebSocketFrame> {
|
||||
let b = assertNotEOF(await buf.readByte());
|
||||
let b = await buf.readByte();
|
||||
assert(b !== null);
|
||||
let isLastFrame = false;
|
||||
switch (b >>> 4) {
|
||||
case 0b1000:
|
||||
|
@ -163,25 +164,28 @@ export async function readFrame(buf: BufReader): Promise<WebSocketFrame> {
|
|||
}
|
||||
const opcode = b & 0x0f;
|
||||
// has_mask & payload
|
||||
b = assertNotEOF(await buf.readByte());
|
||||
b = await buf.readByte();
|
||||
assert(b !== null);
|
||||
const hasMask = b >>> 7;
|
||||
let payloadLength = b & 0b01111111;
|
||||
if (payloadLength === 126) {
|
||||
const l = assertNotEOF(await readShort(buf));
|
||||
const l = await readShort(buf);
|
||||
assert(l !== null);
|
||||
payloadLength = l;
|
||||
} else if (payloadLength === 127) {
|
||||
const l = assertNotEOF(await readLong(buf));
|
||||
const l = await readLong(buf);
|
||||
assert(l !== null);
|
||||
payloadLength = Number(l);
|
||||
}
|
||||
// mask
|
||||
let mask: Uint8Array | undefined;
|
||||
if (hasMask) {
|
||||
mask = new Uint8Array(4);
|
||||
assertNotEOF(await buf.readFull(mask));
|
||||
assert((await buf.readFull(mask)) !== null);
|
||||
}
|
||||
// payload
|
||||
const payload = new Uint8Array(payloadLength);
|
||||
assertNotEOF(await buf.readFull(payload));
|
||||
assert((await buf.readFull(payload)) !== null);
|
||||
return {
|
||||
isLastFrame,
|
||||
opcode,
|
||||
|
@ -479,7 +483,7 @@ export async function handshake(
|
|||
|
||||
const tpReader = new TextProtoReader(bufReader);
|
||||
const statusLine = await tpReader.readLine();
|
||||
if (statusLine === Deno.EOF) {
|
||||
if (statusLine === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
const m = statusLine.match(/^(?<version>\S+) (?<statusCode>\S+) /);
|
||||
|
@ -497,7 +501,7 @@ export async function handshake(
|
|||
}
|
||||
|
||||
const responseHeaders = await tpReader.readMIMEHeader();
|
||||
if (responseHeaders === Deno.EOF) {
|
||||
if (responseHeaders === null) {
|
||||
throw new Deno.errors.UnexpectedEof();
|
||||
}
|
||||
|
||||
|
|
|
@ -278,7 +278,7 @@ function dummyConn(r: Reader, w: Writer): Conn {
|
|||
rid: -1,
|
||||
closeRead: (): void => {},
|
||||
closeWrite: (): void => {},
|
||||
read: (x): Promise<number | Deno.EOF> => r.read(x),
|
||||
read: (x): Promise<number | null> => r.read(x),
|
||||
write: (x): Promise<number> => w.write(x),
|
||||
close: (): void => {},
|
||||
localAddr: { transport: "tcp", hostname: "0.0.0.0", port: 0 },
|
||||
|
@ -335,8 +335,8 @@ test("[ws] createSecKeyHasCorrectLength", () => {
|
|||
test("[ws] WebSocket should throw `Deno.errors.ConnectionReset` when peer closed connection without close frame", async () => {
|
||||
const buf = new Buffer();
|
||||
const eofReader: Deno.Reader = {
|
||||
read(_: Uint8Array): Promise<number | Deno.EOF> {
|
||||
return Promise.resolve(Deno.EOF);
|
||||
read(_: Uint8Array): Promise<number | null> {
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
};
|
||||
const conn = dummyConn(eofReader, buf);
|
||||
|
@ -353,8 +353,8 @@ test("[ws] WebSocket should throw `Deno.errors.ConnectionReset` when peer closed
|
|||
test("[ws] WebSocket shouldn't throw `Deno.errors.UnexpectedEof` on recive()", async () => {
|
||||
const buf = new Buffer();
|
||||
const eofReader: Deno.Reader = {
|
||||
read(_: Uint8Array): Promise<number | Deno.EOF> {
|
||||
return Promise.resolve(Deno.EOF);
|
||||
read(_: Uint8Array): Promise<number | null> {
|
||||
return Promise.resolve(null);
|
||||
},
|
||||
};
|
||||
const conn = dummyConn(eofReader, buf);
|
||||
|
|
|
@ -13,7 +13,7 @@ async function handle(conn: Deno.Conn): Promise<void> {
|
|||
try {
|
||||
while (true) {
|
||||
const r = await conn.read(buffer);
|
||||
if (r === Deno.EOF) {
|
||||
if (r === null) {
|
||||
break;
|
||||
}
|
||||
await conn.write(response);
|
||||
|
|
Loading…
Reference in a new issue