summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--io/bufio.ts6
-rw-r--r--io/bufio_test.ts2
-rw-r--r--io/ioutil.ts47
-rw-r--r--io/ioutil_test.ts4
-rw-r--r--ws/mod.ts10
5 files changed, 43 insertions, 26 deletions
diff --git a/io/bufio.ts b/io/bufio.ts
index 99b563816..dc6d6b3cc 100644
--- a/io/bufio.ts
+++ b/io/bufio.ts
@@ -192,10 +192,10 @@ export class BufReader implements Reader {
return p;
}
- /** Returns the next byte [0, 255] or -1 if EOF. */
- async readByte(): Promise<number> {
+ /** Returns the next byte [0, 255] or `EOF`. */
+ async readByte(): Promise<number | EOF> {
while (this.r === this.w) {
- if (this.eof) return -1;
+ if (this.eof) return EOF;
await this._fill(); // buffer is empty.
}
const c = this.buf[this.r];
diff --git a/io/bufio_test.ts b/io/bufio_test.ts
index 84b6f9142..6433c7a5a 100644
--- a/io/bufio_test.ts
+++ b/io/bufio_test.ts
@@ -35,7 +35,7 @@ async function readBytes(buf: BufReader): Promise<string> {
let nb = 0;
while (true) {
let c = await buf.readByte();
- if (c < 0) {
+ if (c === EOF) {
break; // EOF
}
b[nb] = c;
diff --git a/io/ioutil.ts b/io/ioutil.ts
index 484aba281..979549fbf 100644
--- a/io/ioutil.ts
+++ b/io/ioutil.ts
@@ -1,5 +1,5 @@
// Copyright 2018-2019 the Deno authors. All rights reserved. MIT license.
-import { BufReader } from "./bufio.ts";
+import { BufReader, EOF, UnexpectedEOFError } from "./bufio.ts";
type Reader = Deno.Reader;
type Writer = Deno.Writer;
import { assert } from "../testing/asserts.ts";
@@ -30,36 +30,47 @@ export async function copyN(
}
/** Read big endian 16bit short from BufReader */
-export async function readShort(buf: BufReader): Promise<number> {
- const [high, low] = [await buf.readByte(), await buf.readByte()];
+export async function readShort(buf: BufReader): Promise<number | EOF> {
+ const high = await buf.readByte();
+ if (high === EOF) return EOF;
+ const low = await buf.readByte();
+ if (low === EOF) throw new UnexpectedEOFError();
return (high << 8) | low;
}
/** Read big endian 32bit integer from BufReader */
-export async function readInt(buf: BufReader): Promise<number> {
- const [high, low] = [await readShort(buf), await readShort(buf)];
+export async function readInt(buf: BufReader): Promise<number | EOF> {
+ const high = await readShort(buf);
+ if (high === EOF) return EOF;
+ const low = await readShort(buf);
+ if (low === EOF) throw new UnexpectedEOFError();
return (high << 16) | low;
}
-const BIT32 = 0xffffffff;
+const MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
/** Read big endian 64bit long from BufReader */
-export async function readLong(buf: BufReader): Promise<number> {
- const [high, low] = [await readInt(buf), await readInt(buf)];
- // ECMAScript doesn't support 64bit bit ops.
- return high ? high * (BIT32 + 1) + low : low;
+export async function readLong(buf: BufReader): Promise<number | EOF> {
+ const high = await readInt(buf);
+ if (high === EOF) return EOF;
+ const low = await readInt(buf);
+ if (low === EOF) throw new UnexpectedEOFError();
+ const big = (BigInt(high) << 32n) | BigInt(low);
+ // We probably should provide a similar API that returns BigInt values.
+ if (big > MAX_SAFE_INTEGER) {
+ throw new RangeError(
+ "Long value too big to be represented as a Javascript number."
+ );
+ }
+ return Number(big);
}
/** Slice number into 64bit big endian byte array */
export function sliceLongToBytes(d: number, dest = new Array(8)): number[] {
- let mask = 0xff;
- let low = (d << 32) >>> 32;
- let high = (d - low) / (BIT32 + 1);
- let shift = 24;
- for (let i = 0; i < 4; i++) {
- dest[i] = (high >>> shift) & mask;
- dest[i + 4] = (low >>> shift) & mask;
- shift -= 8;
+ let big = BigInt(d);
+ for (let i = 0; i < 8; i++) {
+ dest[7 - i] = Number(big & 0xffn);
+ big >>= 8n;
}
return dest;
}
diff --git a/io/ioutil_test.ts b/io/ioutil_test.ts
index c1c1ded72..4e34f5698 100644
--- a/io/ioutil_test.ts
+++ b/io/ioutil_test.ts
@@ -40,10 +40,10 @@ test(async function testReadInt(): Promise<void> {
test(async function testReadLong(): Promise<void> {
const r = new BinaryReader(
- new Uint8Array([0x12, 0x34, 0x56, 0x78, 0x12, 0x34, 0x56, 0x78])
+ new Uint8Array([0x00, 0x00, 0x00, 0x78, 0x12, 0x34, 0x56, 0x78])
);
const long = await readLong(new BufReader(r));
- assertEquals(long, 0x1234567812345678);
+ assertEquals(long, 0x7812345678);
});
test(async function testReadLong2(): Promise<void> {
diff --git a/ws/mod.ts b/ws/mod.ts
index 86ab2f045..d74e4a92b 100644
--- a/ws/mod.ts
+++ b/ws/mod.ts
@@ -142,6 +142,7 @@ export async function writeFrame(
/** Read websocket frame from given BufReader */
export async function readFrame(buf: BufReader): Promise<WebSocketFrame> {
let b = await buf.readByte();
+ if (b === EOF) throw new UnexpectedEOFError();
let isLastFrame = false;
switch (b >>> 4) {
case 0b1000:
@@ -156,12 +157,17 @@ export async function readFrame(buf: BufReader): Promise<WebSocketFrame> {
const opcode = b & 0x0f;
// has_mask & payload
b = await buf.readByte();
+ if (b === EOF) throw new UnexpectedEOFError();
const hasMask = b >>> 7;
let payloadLength = b & 0b01111111;
if (payloadLength === 126) {
- payloadLength = await readShort(buf);
+ const l = await readShort(buf);
+ if (l === EOF) throw new UnexpectedEOFError();
+ payloadLength = l;
} else if (payloadLength === 127) {
- payloadLength = await readLong(buf);
+ const l = await readLong(buf);
+ if (l === EOF) throw new UnexpectedEOFError();
+ payloadLength = Number(l);
}
// mask
let mask;