1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-12-23 15:49:44 -05:00

io: make port BufReader.readByte() return number | EOF

Original: 679b203053
This commit is contained in:
Bert Belder 2019-05-30 18:19:28 -07:00
parent aacf92eb11
commit 94816457e4
5 changed files with 43 additions and 26 deletions

View file

@ -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];

View file

@ -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;

View file

@ -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;
}

View file

@ -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> {

View file

@ -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;