summaryrefslogtreecommitdiff
path: root/buffer.ts
diff options
context:
space:
mode:
Diffstat (limited to 'buffer.ts')
-rw-r--r--buffer.ts217
1 files changed, 0 insertions, 217 deletions
diff --git a/buffer.ts b/buffer.ts
deleted file mode 100644
index d177bc18d..000000000
--- a/buffer.ts
+++ /dev/null
@@ -1,217 +0,0 @@
-// 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
-
-//import * as io from "./io";
-import { Reader, Writer, ReadResult } from "deno";
-import { assert, copyBytes } from "./util.ts";
-
-// 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 = 512;
-const MAX_SIZE = 2 ** 32 - 2;
-
-const encoder = new TextEncoder();
-export function stringsReader(s: string): Reader {
- const ui8 = encoder.encode(s);
- return new Buffer(ui8.buffer as ArrayBuffer);
-}
-
-/** A Buffer is a variable-sized buffer of bytes with read() and write()
- * methods. Based on https://golang.org/pkg/bytes/#Buffer
- */
-export class Buffer implements Reader, Writer {
- private buf: Uint8Array; // contents are the bytes buf[off : len(buf)]
- private off = 0; // read at buf[off], write at buf[buf.byteLength]
-
- constructor(ab?: ArrayBuffer) {
- if (ab == null) {
- this.buf = new Uint8Array(0);
- } else {
- this.buf = new Uint8Array(ab);
- }
- }
-
- /** bytes() 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()). 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.
- */
- bytes(): Uint8Array {
- return this.buf.subarray(this.off);
- }
-
- /** toString() returns the contents of the unread portion of the buffer
- * as a string. Warning - if multibyte characters are present when data is
- * flowing through the buffer, this method may result in incorrect strings
- * due to a character being split.
- */
- toString(): string {
- const decoder = new TextDecoder();
- return decoder.decode(this.buf.subarray(this.off));
- }
-
- /** empty() returns whether the unread portion of the buffer is empty. */
- empty() {
- return this.buf.byteLength <= this.off;
- }
-
- /** length is a getter that returns the number of bytes of the unread
- * portion of the buffer
- */
- get length() {
- return this.buf.byteLength - this.off;
- }
-
- /** Returns the capacity of the buffer's underlying byte slice, that is,
- * the total space allocated for the buffer's data.
- */
- get capacity(): number {
- return this.buf.buffer.byteLength;
- }
-
- /** truncate() 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.
- */
- truncate(n: number): void {
- 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() resets the buffer to be empty, but it retains the underlying
- * storage for use by future writes. reset() is the same as truncate(0)
- */
- reset(): void {
- this._reslice(0);
- this.off = 0;
- }
-
- /** _tryGrowByReslice() is a version of grow for the fast-case
- * where the internal buffer only needs to be resliced. It returns the index
- * where bytes should be written and whether it succeeded.
- * It returns -1 if a reslice was not needed.
- */
- private _tryGrowByReslice(n: number): number {
- const l = this.buf.byteLength;
- if (n <= this.capacity - l) {
- this._reslice(l + n);
- return l;
- }
- return -1;
- }
-
- private _reslice(len: number): void {
- assert(len <= this.buf.buffer.byteLength);
- this.buf = new Uint8Array(this.buf.buffer, 0, len);
- }
-
- /** read() reads the next len(p) bytes from the buffer or until the buffer
- * is drained. The return value n is the number of bytes read. If the
- * buffer has no data to return, eof in the response will be true.
- */
- async read(p: Uint8Array): Promise<ReadResult> {
- if (this.empty()) {
- // Buffer is empty, reset to recover space.
- this.reset();
- if (p.byteLength === 0) {
- // TODO This edge case should be tested by porting TestReadEmptyAtEOF
- // from the Go tests.
- return { nread: 0, eof: false };
- }
- return { nread: 0, eof: true };
- }
- const nread = copyBytes(p, this.buf.subarray(this.off));
- this.off += nread;
- return { nread, eof: false };
- }
-
- async write(p: Uint8Array): Promise<number> {
- const m = this._grow(p.byteLength);
- return copyBytes(this.buf, p, m);
- }
-
- /** _grow() grows the buffer to guarantee space for n more bytes.
- * It returns the index where bytes should be written.
- * If the buffer can't grow it will throw with ErrTooLarge.
- */
- private _grow(n: number): number {
- 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, this.buf.subarray(this.off));
- } else if (c > MAX_SIZE - c - n) {
- throw Error("ErrTooLarge"); // TODO DenoError(TooLarge)
- } else {
- // Not enough space anywhere, we need to allocate.
- const buf = new Uint8Array(2 * c + n);
- copyBytes(buf, this.buf.subarray(this.off));
- this.buf = buf;
- }
- // Restore this.off and len(this.buf).
- this.off = 0;
- this._reslice(m + n);
- return m;
- }
-
- /** grow() 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 panic. If
- * the buffer can't grow it will throw ErrTooLarge.
- * Based on https://golang.org/pkg/bytes/#Buffer.Grow
- */
- grow(n: number): void {
- if (n < 0) {
- throw Error("Buffer.grow: negative count");
- }
- const m = this._grow(n);
- this._reslice(m);
- }
-
- /** readFrom() reads data from r until EOF and appends it to the buffer,
- * growing the buffer as needed. It returns the number of bytes read. If the
- * buffer becomes too large, readFrom will panic with ErrTooLarge.
- * Based on https://golang.org/pkg/bytes/#Buffer.ReadFrom
- */
- async readFrom(r: Reader): Promise<number> {
- let n = 0;
- while (true) {
- try {
- const i = this._grow(MIN_READ);
- this._reslice(i);
- const fub = new Uint8Array(this.buf.buffer, i);
- const { nread, eof } = await r.read(fub);
- this._reslice(i + nread);
- n += nread;
- if (eof) {
- return n;
- }
- } catch (e) {
- return n;
- }
- }
- }
-}