mirror of
https://github.com/denoland/deno.git
synced 2025-08-30 23:38:03 +00:00
refactor: Rename runtime/rt to runtime/js (#8806)
This commit is contained in:
parent
55dc467b41
commit
ffb5f7a4e1
42 changed files with 5 additions and 12 deletions
241
runtime/js/13_buffer.js
Normal file
241
runtime/js/13_buffer.js
Normal file
|
@ -0,0 +1,241 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
// This code has been ported almost directly from Go's src/bytes/buffer.go
|
||||
// Copyright 2009 The Go Authors. All rights reserved. BSD license.
|
||||
// https://github.com/golang/go/blob/master/LICENSE
|
||||
|
||||
((window) => {
|
||||
const { assert } = window.__bootstrap.util;
|
||||
|
||||
// MIN_READ is the minimum ArrayBuffer size passed to a read call by
|
||||
// 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 = 32 * 1024;
|
||||
const MAX_SIZE = 2 ** 32 - 2;
|
||||
|
||||
// `off` is the offset into `dst` where it will at which to begin writing values
|
||||
// from `src`.
|
||||
// Returns the number of bytes copied.
|
||||
function copyBytes(src, dst, off = 0) {
|
||||
const r = dst.byteLength - off;
|
||||
if (src.byteLength > r) {
|
||||
src = src.subarray(0, r);
|
||||
}
|
||||
dst.set(src, off);
|
||||
return src.byteLength;
|
||||
}
|
||||
|
||||
class Buffer {
|
||||
#buf = null; // contents are the bytes buf[off : len(buf)]
|
||||
#off = 0; // read at buf[off], write at buf[buf.byteLength]
|
||||
|
||||
constructor(ab) {
|
||||
if (ab == null) {
|
||||
this.#buf = new Uint8Array(0);
|
||||
return;
|
||||
}
|
||||
|
||||
this.#buf = new Uint8Array(ab);
|
||||
}
|
||||
|
||||
bytes(options = { copy: true }) {
|
||||
if (options.copy === false) return this.#buf.subarray(this.#off);
|
||||
return this.#buf.slice(this.#off);
|
||||
}
|
||||
|
||||
empty() {
|
||||
return this.#buf.byteLength <= this.#off;
|
||||
}
|
||||
|
||||
get length() {
|
||||
return this.#buf.byteLength - this.#off;
|
||||
}
|
||||
|
||||
get capacity() {
|
||||
return this.#buf.buffer.byteLength;
|
||||
}
|
||||
|
||||
truncate(n) {
|
||||
if (n === 0) {
|
||||
this.reset();
|
||||
return;
|
||||
}
|
||||
if (n < 0 || n > this.length) {
|
||||
throw Error("bytes.Buffer: truncation out of range");
|
||||
}
|
||||
this.#reslice(this.#off + n);
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.#reslice(0);
|
||||
this.#off = 0;
|
||||
}
|
||||
|
||||
#tryGrowByReslice = (n) => {
|
||||
const l = this.#buf.byteLength;
|
||||
if (n <= this.capacity - l) {
|
||||
this.#reslice(l + n);
|
||||
return l;
|
||||
}
|
||||
return -1;
|
||||
};
|
||||
|
||||
#reslice = (len) => {
|
||||
assert(len <= this.#buf.buffer.byteLength);
|
||||
this.#buf = new Uint8Array(this.#buf.buffer, 0, len);
|
||||
};
|
||||
|
||||
readSync(p) {
|
||||
if (this.empty()) {
|
||||
// Buffer is empty, reset to recover space.
|
||||
this.reset();
|
||||
if (p.byteLength === 0) {
|
||||
// this edge case is tested in 'bufferReadEmptyAtEOF' test
|
||||
return 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
const nread = copyBytes(this.#buf.subarray(this.#off), p);
|
||||
this.#off += nread;
|
||||
return nread;
|
||||
}
|
||||
|
||||
read(p) {
|
||||
const rr = this.readSync(p);
|
||||
return Promise.resolve(rr);
|
||||
}
|
||||
|
||||
writeSync(p) {
|
||||
const m = this.#grow(p.byteLength);
|
||||
return copyBytes(p, this.#buf, m);
|
||||
}
|
||||
|
||||
write(p) {
|
||||
const n = this.writeSync(p);
|
||||
return Promise.resolve(n);
|
||||
}
|
||||
|
||||
#grow = (n) => {
|
||||
const m = this.length;
|
||||
// If buffer is empty, reset to recover space.
|
||||
if (m === 0 && this.#off !== 0) {
|
||||
this.reset();
|
||||
}
|
||||
// Fast: Try to grow by means of a reslice.
|
||||
const i = this.#tryGrowByReslice(n);
|
||||
if (i >= 0) {
|
||||
return i;
|
||||
}
|
||||
const c = this.capacity;
|
||||
if (n <= Math.floor(c / 2) - m) {
|
||||
// We can slide things down instead of allocating a new
|
||||
// ArrayBuffer. We only need m+n <= c to slide, but
|
||||
// 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 + 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(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(Math.min(m + n, MAX_SIZE));
|
||||
return m;
|
||||
};
|
||||
|
||||
grow(n) {
|
||||
if (n < 0) {
|
||||
throw Error("Buffer.grow: negative count");
|
||||
}
|
||||
const m = this.#grow(n);
|
||||
this.#reslice(m);
|
||||
}
|
||||
|
||||
async readFrom(r) {
|
||||
let n = 0;
|
||||
const tmp = new Uint8Array(MIN_READ);
|
||||
while (true) {
|
||||
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;
|
||||
}
|
||||
|
||||
// write will grow if needed
|
||||
if (shouldGrow) this.writeSync(buf.subarray(0, nread));
|
||||
else this.#reslice(this.length + nread);
|
||||
|
||||
n += nread;
|
||||
}
|
||||
}
|
||||
|
||||
readFromSync(r) {
|
||||
let n = 0;
|
||||
const tmp = new Uint8Array(MIN_READ);
|
||||
while (true) {
|
||||
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;
|
||||
}
|
||||
|
||||
// write will grow if needed
|
||||
if (shouldGrow) this.writeSync(buf.subarray(0, nread));
|
||||
else this.#reslice(this.length + nread);
|
||||
|
||||
n += nread;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function readAll(r) {
|
||||
const buf = new Buffer();
|
||||
await buf.readFrom(r);
|
||||
return buf.bytes();
|
||||
}
|
||||
|
||||
function readAllSync(r) {
|
||||
const buf = new Buffer();
|
||||
buf.readFromSync(r);
|
||||
return buf.bytes();
|
||||
}
|
||||
|
||||
async function writeAll(w, arr) {
|
||||
let nwritten = 0;
|
||||
while (nwritten < arr.length) {
|
||||
nwritten += await w.write(arr.subarray(nwritten));
|
||||
}
|
||||
}
|
||||
|
||||
function writeAllSync(w, arr) {
|
||||
let nwritten = 0;
|
||||
while (nwritten < arr.length) {
|
||||
nwritten += w.writeSync(arr.subarray(nwritten));
|
||||
}
|
||||
}
|
||||
|
||||
window.__bootstrap.buffer = {
|
||||
writeAll,
|
||||
writeAllSync,
|
||||
readAll,
|
||||
readAllSync,
|
||||
Buffer,
|
||||
};
|
||||
})(this);
|
Loading…
Add table
Add a link
Reference in a new issue