UNPKG

@mieweb/wikigdrive

Version:

Google Drive to MarkDown synchronization

489 lines (488 loc) 19 kB
// Copyright 2018-2025 the Deno authors. MIT license. // This module is browser compatible. var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _Buffer_instances, _Buffer_buf, _Buffer_off, _Buffer_tryGrowByReslice, _Buffer_reslice, _Buffer_grow; import { copy } from "../../bytes/1.0.6/copy.js"; // 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; /** * A variable-sized buffer of bytes with `read()` and `write()` methods. * * Buffer is almost always used with some I/O like files and sockets. It allows * one to buffer up a download from a socket. Buffer grows and shrinks as * necessary. * * Buffer is NOT the same thing as Node's Buffer. Node's Buffer was created in * 2009 before JavaScript had the concept of ArrayBuffers. It's simply a * non-standard ArrayBuffer. * * ArrayBuffer is a fixed memory allocation. Buffer is implemented on top of * ArrayBuffer. * * Based on {@link https://golang.org/pkg/bytes/#Buffer | Go Buffer}. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * await buf.write(new TextEncoder().encode("Hello, ")); * await buf.write(new TextEncoder().encode("world!")); * * const data = new Uint8Array(13); * await buf.read(data); * * assertEquals(new TextDecoder().decode(data), "Hello, world!"); * ``` */ export class Buffer { /** * Constructs a new instance with the specified {@linkcode ArrayBuffer} as its * initial contents. * * @param ab The ArrayBuffer to use as the initial contents of the buffer. */ constructor(ab) { _Buffer_instances.add(this); _Buffer_buf.set(this, void 0); // contents are the bytes buf[off : len(buf)] _Buffer_off.set(this, 0); // read at buf[off], write at buf[buf.byteLength] if (ab === undefined) { __classPrivateFieldSet(this, _Buffer_buf, new Uint8Array(0), "f"); } else if (ab instanceof SharedArrayBuffer) { // Note: This is necessary to avoid type error __classPrivateFieldSet(this, _Buffer_buf, new Uint8Array(ab), "f"); } else { __classPrivateFieldSet(this, _Buffer_buf, new Uint8Array(ab), "f"); } } /** * Returns a slice holding the unread portion of the buffer. * * The slice is valid for use only until the next buffer modification (that * is, only until the next call to a method like `read()`, `write()`, * `reset()`, or `truncate()`). If `options.copy` is false the slice aliases the buffer content at * least until the next buffer modification, so immediate changes to the * slice will affect the result of future reads. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * await buf.write(new TextEncoder().encode("Hello, world!")); * * const slice = buf.bytes(); * assertEquals(new TextDecoder().decode(slice), "Hello, world!"); * ``` * * @param options The options for the slice. * @returns A slice holding the unread portion of the buffer. */ bytes(options = { copy: true }) { if (options.copy === false) return __classPrivateFieldGet(this, _Buffer_buf, "f").subarray(__classPrivateFieldGet(this, _Buffer_off, "f")); return __classPrivateFieldGet(this, _Buffer_buf, "f").slice(__classPrivateFieldGet(this, _Buffer_off, "f")); } /** * Returns whether the unread portion of the buffer is empty. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * assertEquals(buf.empty(), true); * await buf.write(new TextEncoder().encode("Hello, world!")); * assertEquals(buf.empty(), false); * ``` * * @returns `true` if the unread portion of the buffer is empty, `false` * otherwise. */ empty() { return __classPrivateFieldGet(this, _Buffer_buf, "f").byteLength <= __classPrivateFieldGet(this, _Buffer_off, "f"); } /** * A read only number of bytes of the unread portion of the buffer. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * await buf.write(new TextEncoder().encode("Hello, world!")); * * assertEquals(buf.length, 13); * ``` * * @returns The number of bytes of the unread portion of the buffer. */ get length() { return __classPrivateFieldGet(this, _Buffer_buf, "f").byteLength - __classPrivateFieldGet(this, _Buffer_off, "f"); } /** * The read only capacity of the buffer's underlying byte slice, that is, * the total space allocated for the buffer's data. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * assertEquals(buf.capacity, 0); * await buf.write(new TextEncoder().encode("Hello, world!")); * assertEquals(buf.capacity, 13); * ``` * * @returns The capacity of the buffer. */ get capacity() { return __classPrivateFieldGet(this, _Buffer_buf, "f").buffer.byteLength; } /** * Discards all but the first `n` unread bytes from the buffer but * continues to use the same allocated storage. It throws if `n` is * negative or greater than the length of the buffer. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * await buf.write(new TextEncoder().encode("Hello, world!")); * buf.truncate(6); * assertEquals(buf.length, 6); * ``` * * @param n The number of bytes to keep. */ truncate(n) { if (n === 0) { this.reset(); return; } if (n < 0 || n > this.length) { throw new Error("Buffer truncation out of range"); } __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_reslice).call(this, __classPrivateFieldGet(this, _Buffer_off, "f") + n); } /** * Resets the contents * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * await buf.write(new TextEncoder().encode("Hello, world!")); * buf.reset(); * assertEquals(buf.length, 0); * ``` */ reset() { __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_reslice).call(this, 0); __classPrivateFieldSet(this, _Buffer_off, 0, "f"); } /** * Reads the next `p.length` bytes from the buffer or until the buffer is * drained. Returns the number of bytes read. If the buffer has no data to * return, the return is EOF (`null`). * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * await buf.write(new TextEncoder().encode("Hello, world!")); * * const data = new Uint8Array(5); * const res = await buf.read(data); * * assertEquals(res, 5); * assertEquals(new TextDecoder().decode(data), "Hello"); * ``` * * @param p The buffer to read data into. * @returns The number of bytes read. */ 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 = copy(__classPrivateFieldGet(this, _Buffer_buf, "f").subarray(__classPrivateFieldGet(this, _Buffer_off, "f")), p); __classPrivateFieldSet(this, _Buffer_off, __classPrivateFieldGet(this, _Buffer_off, "f") + nread, "f"); return nread; } /** * Reads the next `p.length` bytes from the buffer or until the buffer is * drained. Resolves to the number of bytes read. If the buffer has no * data to return, resolves to EOF (`null`). * * NOTE: This methods reads bytes synchronously; it's provided for * compatibility with `Reader` interfaces. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * await buf.write(new TextEncoder().encode("Hello, world!")); * * const data = new Uint8Array(5); * const res = await buf.read(data); * * assertEquals(res, 5); * assertEquals(new TextDecoder().decode(data), "Hello"); * ``` * * @param p The buffer to read data into. * @returns The number of bytes read. */ read(p) { const rr = this.readSync(p); return Promise.resolve(rr); } /** * Writes the given data to the buffer. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * const data = new TextEncoder().encode("Hello, world!"); * buf.writeSync(data); * * const slice = buf.bytes(); * assertEquals(new TextDecoder().decode(slice), "Hello, world!"); * ``` * * @param p The data to write to the buffer. * @returns The number of bytes written. */ writeSync(p) { const m = __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_grow).call(this, p.byteLength); return copy(p, __classPrivateFieldGet(this, _Buffer_buf, "f"), m); } /** * Writes the given data to the buffer. Resolves to the number of bytes * written. * * > [!NOTE] * > This methods writes bytes synchronously; it's provided for compatibility * > with the {@linkcode Writer} interface. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * const data = new TextEncoder().encode("Hello, world!"); * await buf.write(data); * * const slice = buf.bytes(); * assertEquals(new TextDecoder().decode(slice), "Hello, world!"); * ``` * * @param p The data to write to the buffer. * @returns The number of bytes written. */ write(p) { const n = this.writeSync(p); return Promise.resolve(n); } /** Grows the buffer's capacity, if necessary, to guarantee space for * another `n` bytes. After `.grow(n)`, at least `n` bytes can be written to * the buffer without another allocation. If `n` is negative, `.grow()` will * throw. If the buffer can't grow it will throw an error. * * Based on Go Lang's * {@link https://golang.org/pkg/bytes/#Buffer.Grow | Buffer.Grow}. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * buf.grow(10); * assertEquals(buf.capacity, 10); * ``` * * @param n The number of bytes to grow the buffer by. */ grow(n) { if (n < 0) { throw new Error("Buffer growth cannot be negative"); } const m = __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_grow).call(this, n); __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_reslice).call(this, m); } /** * Reads data from `r` until EOF (`null`) and appends it to the buffer, * growing the buffer as needed. It resolves to the number of bytes read. * If the buffer becomes too large, `.readFrom()` will reject with an error. * * Based on Go Lang's * {@link https://golang.org/pkg/bytes/#Buffer.ReadFrom | Buffer.ReadFrom}. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * const r = new Buffer(new TextEncoder().encode("Hello, world!")); * const n = await buf.readFrom(r); * * assertEquals(n, 13); * ``` * * @param r The reader to read from. * @returns The number of bytes read. */ 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(__classPrivateFieldGet(this, _Buffer_buf, "f").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 __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_reslice).call(this, this.length + nread); n += nread; } } /** Reads data from `r` until EOF (`null`) and appends it to the buffer, * growing the buffer as needed. It returns the number of bytes read. If the * buffer becomes too large, `.readFromSync()` will throw an error. * * Based on Go Lang's * {@link https://golang.org/pkg/bytes/#Buffer.ReadFrom | Buffer.ReadFrom}. * * @example Usage * ```ts * import { Buffer } from "@std/io/buffer"; * import { assertEquals } from "@std/assert/equals"; * * const buf = new Buffer(); * const r = new Buffer(new TextEncoder().encode("Hello, world!")); * const n = buf.readFromSync(r); * * assertEquals(n, 13); * ``` * * @param r The reader to read from. * @returns The number of bytes read. */ 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(__classPrivateFieldGet(this, _Buffer_buf, "f").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 __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_reslice).call(this, this.length + nread); n += nread; } } } _Buffer_buf = new WeakMap(), _Buffer_off = new WeakMap(), _Buffer_instances = new WeakSet(), _Buffer_tryGrowByReslice = function _Buffer_tryGrowByReslice(n) { const l = __classPrivateFieldGet(this, _Buffer_buf, "f").byteLength; if (n <= this.capacity - l) { __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_reslice).call(this, l + n); return l; } return -1; }, _Buffer_reslice = function _Buffer_reslice(len) { if (len > __classPrivateFieldGet(this, _Buffer_buf, "f").buffer.byteLength) { throw new RangeError("Length is greater than buffer capacity"); } __classPrivateFieldSet(this, _Buffer_buf, new Uint8Array(__classPrivateFieldGet(this, _Buffer_buf, "f").buffer, 0, len), "f"); }, _Buffer_grow = function _Buffer_grow(n) { const m = this.length; // If buffer is empty, reset to recover space. if (m === 0 && __classPrivateFieldGet(this, _Buffer_off, "f") !== 0) { this.reset(); } // Fast: Try to grow by means of a reslice. const i = __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_tryGrowByReslice).call(this, 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. copy(__classPrivateFieldGet(this, _Buffer_buf, "f").subarray(__classPrivateFieldGet(this, _Buffer_off, "f")), __classPrivateFieldGet(this, _Buffer_buf, "f")); } else if (c + n > MAX_SIZE) { throw new Error(`The buffer cannot be grown beyond the maximum size of "${MAX_SIZE}"`); } else { // Not enough space anywhere, we need to allocate. const buf = new Uint8Array(Math.min(2 * c + n, MAX_SIZE)); copy(__classPrivateFieldGet(this, _Buffer_buf, "f").subarray(__classPrivateFieldGet(this, _Buffer_off, "f")), buf); __classPrivateFieldSet(this, _Buffer_buf, buf, "f"); } // Restore this.#off and len(this.#buf). __classPrivateFieldSet(this, _Buffer_off, 0, "f"); __classPrivateFieldGet(this, _Buffer_instances, "m", _Buffer_reslice).call(this, Math.min(m + n, MAX_SIZE)); return m; };