Last active
July 28, 2023 14:43
-
-
Save realsba/725fd395a26ac195da737dabf0a97194 to your computer and use it in GitHub Desktop.
JS implementation of BinaryStream
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
export default class BinaryStream { | |
_offset = 0; | |
_dataview = null; | |
_uint8Array = null; | |
constructor(buffer) { | |
this._dataview = new DataView(buffer); | |
this._uint8Array = new Uint8Array(buffer); | |
} | |
get buffer() { | |
return this._dataview.buffer; | |
} | |
readUInt8() { | |
return this._dataview.getUint8(this._offset++); | |
}; | |
readUInt16() { | |
let value = this._dataview.getUint16(this._offset); | |
this._offset += 2; | |
return value; | |
}; | |
readUInt32() { | |
let value = this._dataview.getUint32(this._offset); | |
this._offset += 4; | |
return value; | |
}; | |
readFloat() { | |
let value = this._dataview.getFloat32(this._offset); | |
this._offset += 4; | |
return value; | |
}; | |
readString() { | |
let decoder = new TextDecoder(); | |
let length = this.readUInt16(); | |
let value = decoder.decode(this._dataview.buffer.slice(this._offset, this._offset + length)); | |
this._offset += length; | |
return value; | |
}; | |
writeUInt8(value) { | |
this._dataview.setUint8(this._offset++, value); | |
}; | |
writeUInt16(value) { | |
this._dataview.setUint16(this._offset, value); | |
this._offset += 2; | |
}; | |
writeUInt32(value) { | |
this._dataview.setUint32(this._offset, value); | |
this._offset += 4; | |
}; | |
writeFloat(value) { | |
this._dataview.setFloat32(this._offset, value); | |
this._offset += 4; | |
}; | |
writeString(value) { | |
let encoder = new TextEncoder(); | |
value = encoder.encode(value); | |
this.writeUInt16(value.length); | |
this._uint8Array.set(value, this._offset); | |
this._offset += value.length; | |
}; | |
} |
export default class BinaryStream {
#offset = 0;
#dataview = null;
constructor(buffer) {
this.#dataview = new DataView(buffer);
}
// Read unsigned 8-bit integer
readUInt8() {
if (this.#offset + 1 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getUint8(this.#offset);
this.#offset += 1;
return value;
}
// Read unsigned 16-bit integer
readUInt16() {
if (this.#offset + 2 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getUint16(this.#offset);
this.#offset += 2;
return value;
}
// Read unsigned 32-bit integer
readUInt32() {
if (this.#offset + 4 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getUint32(this.#offset);
this.#offset += 4;
return value;
}
// Read 32-bit floating point number
readFloat() {
if (this.#offset + 4 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getFloat32(this.#offset);
this.#offset += 4;
return value;
}
// Read string
readString() {
const length = this.readUInt16();
if (this.#offset + length > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const decoder = new TextDecoder();
const value = decoder.decode(this.#dataview.buffer.slice(this.#offset, this.#offset + length));
this.#offset += length;
return value;
}
// Write unsigned 8-bit integer
writeUInt8(value) {
this.#dataview.setUint8(this.#offset, value);
this.#offset += 1;
}
// Write unsigned 16-bit integer
writeUInt16(value) {
this.#dataview.setUint16(this.#offset, value);
this.#offset += 2;
}
// Write unsigned 32-bit integer
writeUInt32(value) {
this.#dataview.setUint32(this.#offset, value);
this.#offset += 4;
}
// Write 32-bit floating point number
writeFloat(value) {
this.#dataview.setFloat32(this.#offset, value);
this.#offset += 4;
}
// Write string
writeString(value) {
const encoder = new TextEncoder();
const encodedValue = encoder.encode(value);
this.writeUInt16(encodedValue.length);
const remainingSpace = this.#dataview.byteLength - this.#offset;
if (encodedValue.length > remainingSpace) {
throw new Error('Not enough space in the buffer to write the string.');
}
new Uint8Array(this.#dataview.buffer, this.#offset).set(encodedValue);
this.#offset += encodedValue.length;
}
}
export default class BinaryStream {
#offset = 0;
#dataview = null;
constructor(buffer) {
this.#dataview = new DataView(buffer);
}
// Read unsigned 8-bit integer
readUInt8() {
if (this.#offset + 1 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getUint8(this.#offset);
this.#offset += 1;
return value;
}
// Read unsigned 16-bit integer
readUInt16() {
if (this.#offset + 2 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getUint16(this.#offset);
this.#offset += 2;
return value;
}
// Read unsigned 32-bit integer
readUInt32() {
if (this.#offset + 4 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getUint32(this.#offset);
this.#offset += 4;
return value;
}
// Read 32-bit floating point number
readFloat() {
if (this.#offset + 4 > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const value = this.#dataview.getFloat32(this.#offset);
this.#offset += 4;
return value;
}
// Read string
readString() {
const length = this.readUInt16();
if (this.#offset + length > this.#dataview.byteLength) {
throw new Error('Attempted to read beyond buffer boundaries.');
}
const decoder = new TextDecoder();
const value = decoder.decode(this.#dataview.buffer.slice(this.#offset, this.#offset + length));
this.#offset += length;
return value;
}
// Write unsigned 8-bit integer
writeUInt8(value) {
this.#dataview.setUint8(this.#offset, value);
this.#offset += 1;
}
// Write unsigned 16-bit integer
writeUInt16(value) {
this.#dataview.setUint16(this.#offset, value);
this.#offset += 2;
}
// Write unsigned 32-bit integer
writeUInt32(value) {
this.#dataview.setUint32(this.#offset, value);
this.#offset += 4;
}
// Write 32-bit floating point number
writeFloat(value) {
this.#dataview.setFloat32(this.#offset, value);
this.#offset += 4;
}
// Write string
writeString(value) {
const encoder = new TextEncoder();
const encodedValue = encoder.encode(value);
this.writeUInt16(encodedValue.length);
const remainingSpace = this.#dataview.byteLength - this.#offset;
if (encodedValue.length > remainingSpace) {
throw new Error('Not enough space in the buffer to write the string.');
}
new Uint8Array(this.#dataview.buffer, this.#offset).set(encodedValue);
this.#offset += encodedValue.length;
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Potential Issue:
In the writeString method, there seems to be an error with the line this._uint8Array.set(value, this._offset);. It should be using this._dataview.set instead, as the class doesn't have a _uint8Array property. The correct line should be:
Error Handling:
The code doesn't have any error handling mechanisms for cases where the _offset goes beyond the buffer's bounds. It might be a good idea to add some validation to ensure that the reading and writing operations don't exceed the buffer size.