Buffer

import { Buffer } from "jsr:@ende/streams";

class

class Buffer

A variable-sized buffer of bytes with readable and writable getters that allows you to work with Web Streams API.

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 Go Buffer.

Example: Buffer input bytes and convert it to a string

import { Buffer } from "@ende/streams/buffer";
import { toText } from "@ende/streams/to-text";
import { assert } from "@ende/assert";
import { assertEquals } from "@ende/assert";

// Create a new buffer
const buf = new Buffer();
assertEquals(buf.capacity, 0);
assertEquals(buf.length, 0);

// Dummy input stream
const inputStream = ReadableStream.from([
  "hello, ",
  "world",
  "!",
]);

// Pipe the input stream to the buffer
await inputStream.pipeThrough(new TextEncoderStream()).pipeTo(buf.writable);
assert(buf.capacity > 0);
assert(buf.length > 0);

// Convert the buffered bytes to a string
const result = await toText(buf.readable);
assertEquals(result, "hello, world!");
assert(buf.empty());

Constructors

constructor

new Buffer(ab?: ArrayBufferLike | ArrayLike<number>)

Constructs a new instance.

ab?: ArrayBufferLike | ArrayLike<number>

An optional buffer to use as the initial buffer.

Methods

readable

get readable(): ReadableStream<Uint8Array>

Getter returning the instance's ReadableStream.

Returns

A ReadableStream of the buffer.

Example: Read the content out of the buffer to stdout

import { Buffer } from "@ende/streams/buffer";

const buf = new Buffer();
await buf.readable.pipeTo(Ende.stdout.writable);

writable

get writable(): WritableStream<Uint8Array>

Getter returning the instance's WritableStream.

Returns

A WritableStream of the buffer.

Example: Write the data from stdin to the buffer

import { Buffer } from "@ende/streams/buffer";

const buf = new Buffer();
await Ende.stdin.readable.pipeTo(buf.writable);

bytes

bytes(options: BufferBytesOptions = [UNSUPPORTED]): Uint8Array

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 that mutates or consumes the buffer, like reading data out via readable, 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. If options is not provided, options.copy defaults to true.

options: BufferBytesOptions = [UNSUPPORTED]

Options for the bytes method.

Returns

A copy or a slice of the buffer.

Example: Copy the buffer

import { assertEquals } from "@ende/assert";
import { assertNotEquals } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([0, 1, 2]);
const buf = new Buffer(array.buffer);
const copied = buf.bytes();
assertEquals(copied.length, array.length);

// Modify an element in the original array
array[1] = 99;
assertEquals(copied[0], array[0]);
// The copied buffer is not affected by the modification
assertNotEquals(copied[1], array[1]);
assertEquals(copied[2], array[2]);

Example: Get a slice to the buffer

import { assertEquals } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([0, 1, 2]);
const buf = new Buffer(array.buffer);
const slice = buf.bytes({ copy: false });
assertEquals(slice.length, array.length);

// Modify an element in the original array
array[1] = 99;
assertEquals(slice[0], array[0]);
// The slice _is_ affected by the modification
assertEquals(slice[1], array[1]);
assertEquals(slice[2], array[2]);

empty

empty(): boolean

Returns whether the unread portion of the buffer is empty.

Returns

Whether the buffer is empty.

Example: Empty buffer

import { assert } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const buf = new Buffer();
assert(buf.empty());

Example: Non-empty buffer

import { assert } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([42]);
const buf = new Buffer(array.buffer);
assert(!buf.empty());

Example: Non-empty, but the content was already read

import { assert } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([42]);
const buf = new Buffer(array.buffer);
assert(!buf.empty());
// Read the content out of the buffer
await buf.readable.pipeTo(Ende.stdout.writable);
// The buffer is now empty
assert(buf.empty());

length

get length(): number

A read only number of bytes of the unread portion of the buffer.

Returns

The number of bytes in the unread portion of the buffer.

Example: Basic usage

import { assertEquals } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([0, 1, 2]);
const buf = new Buffer(array.buffer);
assertEquals(buf.length, 3);

Example: Length becomes 0 after the content is read

import { assertEquals } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([42]);
const buf = new Buffer(array.buffer);
assertEquals(buf.length, 1);
// Read the content out of the buffer
await buf.readable.pipeTo(Ende.stdout.writable);
// The length is now 0
assertEquals(buf.length, 0);

capacity

get capacity(): number

The read only capacity of the buffer's underlying byte slice, that is, the total space allocated for the buffer's data.

Returns

The number of allocated bytes for the buffer.

Example: Basic usage

import { assertEquals } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const arrayBuffer = new ArrayBuffer(256);
const buf = new Buffer(arrayBuffer);
assertEquals(buf.capacity, 256);

truncate

truncate(n: number): void

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.

n: number

The number of bytes to keep.

Example: Basic usage

import { assertEquals } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([0, 1, 2]);
const buf = new Buffer(array.buffer);
assertEquals(buf.bytes(), array);

// Discard all but the first 2 bytes
buf.truncate(2);
assertEquals(buf.bytes(), array.slice(0, 2));

reset

reset(): void

Resets to an empty buffer.

Example: Basic usage

import { assert } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const array = new Uint8Array([0, 1, 2]);
const buf = new Buffer(array.buffer);
assert(!buf.empty());

// Reset
buf.reset();
assert(buf.empty());

grow

grow(n: number): void

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.

n: number

The number of bytes to grow the buffer by.

Based on Go Lang's Buffer.Grow.

Example: Basic usage

import { assert } from "@ende/assert";
import { assertEquals } from "@ende/assert";
import { Buffer } from "@ende/streams/buffer";

const buf = new Buffer();
assertEquals(buf.capacity, 0);

buf.grow(200);
assert(buf.capacity >= 200);

Source