fix(cli/buffer): allow Buffer to store MAX_SIZE bytes (#6570)

This commit is contained in:
Marcos Casagrande 2020-07-10 17:49:35 +02:00 committed by GitHub
parent 1bcc35b84a
commit 39dba12a06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 134 additions and 14 deletions

View file

@ -11,7 +11,7 @@ import { assert } from "./util.ts";
// buffer.ReadFrom. As long as the Buffer has at least MIN_READ bytes beyond
// what is required to hold the contents of r, readFrom() will not grow the
// underlying buffer.
const MIN_READ = 512;
const MIN_READ = 32 * 1024;
const MAX_SIZE = 2 ** 32 - 2;
// `off` is the offset into `dst` where it will at which to begin writing values
@ -133,17 +133,17 @@ export class Buffer implements Reader, ReaderSync, Writer, WriterSync {
// we instead let capacity get twice as large so we
// don't spend all our time copying.
copyBytes(this.#buf.subarray(this.#off), this.#buf);
} else if (c > MAX_SIZE - c - n) {
} else if (c + n > MAX_SIZE) {
throw new Error("The buffer cannot be grown beyond the maximum size.");
} else {
// Not enough space anywhere, we need to allocate.
const buf = new Uint8Array(2 * c + n);
const buf = new Uint8Array(Math.min(2 * c + n, MAX_SIZE));
copyBytes(this.#buf.subarray(this.#off), buf);
this.#buf = buf;
}
// Restore this.#off and len(this.#buf).
this.#off = 0;
this.#reslice(m + n);
this.#reslice(Math.min(m + n, MAX_SIZE));
return m;
};
@ -157,30 +157,48 @@ export class Buffer implements Reader, ReaderSync, Writer, WriterSync {
async readFrom(r: Reader): Promise<number> {
let n = 0;
const tmp = new Uint8Array(MIN_READ);
while (true) {
const i = this.#grow(MIN_READ);
this.#reslice(i);
const fub = new Uint8Array(this.#buf.buffer, i);
const nread = await r.read(fub);
const shouldGrow = this.capacity - this.length < MIN_READ;
// read into tmp buffer if there's not enough room
// otherwise read directly into the internal buffer
const buf = shouldGrow
? tmp
: new Uint8Array(this.#buf.buffer, this.length);
const nread = await r.read(buf);
if (nread === null) {
return n;
}
this.#reslice(i + nread);
// write will grow if needed
if (shouldGrow) this.writeSync(buf.subarray(0, nread));
else this.#reslice(this.length + nread);
n += nread;
}
}
readFromSync(r: ReaderSync): number {
let n = 0;
const tmp = new Uint8Array(MIN_READ);
while (true) {
const i = this.#grow(MIN_READ);
this.#reslice(i);
const fub = new Uint8Array(this.#buf.buffer, i);
const nread = r.readSync(fub);
const shouldGrow = this.capacity - this.length < MIN_READ;
// read into tmp buffer if there's not enough room
// otherwise read directly into the internal buffer
const buf = shouldGrow
? tmp
: new Uint8Array(this.#buf.buffer, this.length);
const nread = r.readSync(buf);
if (nread === null) {
return n;
}
this.#reslice(i + nread);
// write will grow if needed
if (shouldGrow) this.writeSync(buf.subarray(0, nread));
else this.#reslice(this.length + nread);
n += nread;
}
}