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:
parent
aacf92eb11
commit
94816457e4
5 changed files with 43 additions and 26 deletions
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
|
|
47
io/ioutil.ts
47
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;
|
||||
}
|
||||
|
|
|
@ -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> {
|
||||
|
|
10
ws/mod.ts
10
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;
|
||||
|
|
Loading…
Reference in a new issue