@hazae41/cursor
Version:
Rust-like Cursor for TypeScript
257 lines (254 loc) • 7.73 kB
JavaScript
import { CursorReadLengthOverflowError, CursorWriteLengthOverflowError, CursorWriteUnknownError, CursorReadNullOverflowError } from './errors/index.mjs';
export { CursorReadUnknownError } from './errors/index.mjs';
import { Buffers } from '../../libs/buffers/buffers.mjs';
import { Bytes } from '../../libs/bytes/index.mjs';
import { Data } from '../../libs/dataviews/dataviews.mjs';
import { Utf8 } from '../../libs/utf8/utf8.mjs';
class Cursor {
#data;
#bytes;
#buffer;
offset;
/**
* A cursor for bytes
* @param inner
* @param offset
*/
constructor(buffer, offset = 0) {
this.offset = offset;
this.#data = Data.fromView(buffer);
this.#bytes = Bytes.fromView(buffer);
this.#buffer = Buffers.fromView(buffer);
}
static create(buffer, offset) {
return new Cursor(buffer, offset);
}
/**
* get bytes
*/
get bytes() {
return this.#bytes;
}
/**
* @returns total number of bytes
*/
get length() {
return this.#bytes.length;
}
/**
* @returns number of remaining bytes
*/
get remaining() {
return this.length - this.offset;
}
/**
* Get a subarray of the bytes before the current offset
* @returns subarray of the bytes before the current offset
*/
get before() {
return this.#bytes.subarray(0, this.offset);
}
/**
* Get a subarray of the bytes after the current offset
* @returns subarray of the bytes after the current offset
*/
get after() {
return this.#bytes.subarray(this.offset);
}
/**
* Get a subarray of the bytes
* @param length
* @returns subarray of the bytes
*/
getOrThrow(length) {
if (this.remaining < length)
throw CursorReadLengthOverflowError.from(this, length);
const subarray = this.#bytes.subarray(this.offset, this.offset + length);
return subarray;
}
/**
* Read a subarray of the bytes
* @param length
* @returns subarray of the bytes
*/
readOrThrow(length) {
const subarray = this.getOrThrow(length);
this.offset += length;
return subarray;
}
/**
* Set an array to the bytes
* @param array array
*/
setOrThrow(array) {
if (this.remaining < array.length)
throw CursorWriteLengthOverflowError.from(this, array.length);
this.#bytes.set(array, this.offset);
}
/**
* Write an array to the bytes
* @param array array
*/
writeOrThrow(array) {
this.setOrThrow(array);
this.offset += array.length;
}
getUint8OrThrow() {
return this.#bytes[this.offset];
}
readUint8OrThrow() {
const x = this.getUint8OrThrow();
this.offset++;
return x;
}
setUint8OrThrow(x) {
this.#bytes[this.offset] = x;
}
writeUint8OrThrow(x) {
this.setUint8OrThrow(x);
this.offset++;
}
getUint16OrThrow(littleEndian) {
return this.#data.getUint16(this.offset, littleEndian);
}
readUint16OrThrow(littleEndian) {
const x = this.getUint16OrThrow(littleEndian);
this.offset += 2;
return x;
}
setUint16OrThrow(x, littleEndian) {
this.#data.setUint16(this.offset, x, littleEndian);
}
writeUint16OrThrow(x, littleEndian) {
this.setUint16OrThrow(x, littleEndian);
this.offset += 2;
}
getUint24OrThrow(littleEndian) {
if (littleEndian)
return this.#buffer.readUIntLE(this.offset, 3);
else
return this.#buffer.readUIntBE(this.offset, 3);
}
readUint24OrThrow(littleEndian) {
const x = this.getUint24OrThrow(littleEndian);
this.offset += 3;
return x;
}
setUint24OrThrow(x, littleEndian) {
if (littleEndian)
this.#buffer.writeUIntLE(x, this.offset, 3);
else
this.#buffer.writeUIntBE(x, this.offset, 3);
}
writeUint24OrThrow(x, littleEndian) {
this.setUint24OrThrow(x, littleEndian);
this.offset += 3;
}
getUint32OrThrow(littleEndian) {
return this.#data.getUint32(this.offset, littleEndian);
}
readUint32OrThrow(littleEndian) {
const x = this.getUint32OrThrow(littleEndian);
this.offset += 4;
return x;
}
setUint32OrThrow(x, littleEndian) {
this.#data.setUint32(this.offset, x, littleEndian);
}
writeUint32OrThrow(x, littleEndian) {
this.setUint32OrThrow(x, littleEndian);
this.offset += 4;
}
getUint64OrThrow(littleEndian) {
return this.#data.getBigUint64(this.offset, littleEndian);
}
readUint64OrThrow(littleEndian) {
const x = this.getUint64OrThrow(littleEndian);
this.offset += 8;
return x;
}
setUint64OrThrow(x, littleEndian) {
this.#data.setBigUint64(this.offset, x, littleEndian);
}
writeUint64OrThrow(x, littleEndian) {
this.setUint64OrThrow(x, littleEndian);
this.offset += 8;
}
getUtf8OrThrow(length) {
return Utf8.decoder.decode(this.getOrThrow(length));
}
readUtf8OrThrow(length) {
return Utf8.decoder.decode(this.readOrThrow(length));
}
setUtf8OrThrow(text) {
const result = Utf8.encoder.encodeInto(text, this.after);
if (result.read !== text.length)
throw new CursorWriteUnknownError();
return;
}
writeUtf8OrThrow(text) {
const result = Utf8.encoder.encodeInto(text, this.after);
if (result.read !== text.length)
throw new CursorWriteUnknownError();
this.offset += result.written;
}
getNullOrThrow() {
let i = this.offset;
while (i < this.#bytes.length && this.#bytes[i] > 0)
i++;
if (i === this.#bytes.length)
throw CursorReadNullOverflowError.from(this);
return i;
}
getNulledOrThrow() {
return this.getOrThrow(this.getNullOrThrow());
}
readNulledOrThrow() {
return this.readOrThrow(this.getNullOrThrow());
}
setNulledOrThrow(array) {
const start = this.offset;
try {
this.writeNulledOrThrow(array);
}
finally {
this.offset = start;
}
}
writeNulledOrThrow(array) {
this.writeOrThrow(array);
this.writeUint8OrThrow(0);
}
getNulledStringOrThrow(encoding) {
return Buffers.fromView(this.getNulledOrThrow()).toString(encoding);
}
readNulledStringOrThrow(encoding) {
return Buffers.fromView(this.readNulledOrThrow()).toString(encoding);
}
setNulledStringOrThrow(text, encoding) {
this.setNulledOrThrow(Buffer.from(text, encoding));
}
writeNulledStringOrThrow(text, encoding) {
this.writeNulledOrThrow(Buffer.from(text, encoding));
}
/**
* Fill length bytes with value after offset
* @param value value to fill
* @param length length to fill
*/
fillOrThrow(value, length) {
if (this.remaining < length)
throw CursorWriteLengthOverflowError.from(this, length);
this.#bytes.fill(value, this.offset, this.offset + length);
this.offset += length;
}
*splitOrThrow(length) {
while (this.remaining >= length)
yield this.readOrThrow(length);
if (this.remaining)
yield this.readOrThrow(this.remaining);
return;
}
}
export { Cursor, CursorReadLengthOverflowError, CursorReadNullOverflowError, CursorWriteLengthOverflowError, CursorWriteUnknownError };
//# sourceMappingURL=index.mjs.map