Skip to content

Instantly share code, notes, and snippets.

@freehuntx
Last active November 5, 2024 23:34
Show Gist options
  • Select an option

  • Save freehuntx/8b554edcc6238105286b73e6f8388761 to your computer and use it in GitHub Desktop.

Select an option

Save freehuntx/8b554edcc6238105286b73e6f8388761 to your computer and use it in GitHub Desktop.

Revisions

  1. freehuntx revised this gist Nov 5, 2024. 1 changed file with 33 additions and 26 deletions.
    59 changes: 33 additions & 26 deletions DataViewStream.js
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,11 @@
    class DataStream {
    class DataViewStream {
    _grow = false
    _offset = 0
    _byteOffset = 0
    _view = null
    _textDecoder = new TextDecoder()
    _textEncoder = new TextEncoder()

    get offset() { return this._offset }
    get byteOffset() { return this._byteOffset }
    get byteLength() { return this._view.byteLength }
    get bytesLeft() { return this._view.byteLength - this._offset }
    get buffer() { return this._view.buffer }
    @@ -24,24 +24,21 @@ class DataStream {
    const bytes = bits / 8

    this[name] = function(...args) {
    return this._view[name](this._offset, ...args)
    return this._view[name](this._byteOffset, ...args)
    }

    if (variant === 'get') {
    this[`read${type}${bits}`] = function(...args) {
    const res = this._view[name](this._offset, ...args)
    this._offset += bytes
    const res = this._view[name](this._byteOffset, ...args)
    this._byteOffset += bytes
    return res
    }
    } else {
    this[`write${type}${bits}`] = function(...args) {
    const missingBytes = (this.bytesLeft - bits/8) * -1
    if (missingBytes > 0 && this._grow) {
    this.appendBytes(missingBytes)
    }
    this.expectBytes(bits/8)

    const res = this._view[name](this._offset, ...args)
    this._offset += bytes
    const res = this._view[name](this._byteOffset, ...args)
    this._byteOffset += bytes
    return res
    }
    }
    @@ -52,8 +49,8 @@ class DataStream {
    this._grow = grow
    }

    seek(offset) {
    this._offset = offset
    seek(byteOffset) {
    this._byteOffset = byteOffset
    }

    appendBytes(num) {
    @@ -63,54 +60,64 @@ class DataStream {
    newBuffer.set(oldBuffer)
    this._view = new DataView(newBuffer.buffer)
    }

    expectBytes(byteCount) {
    if (!this._grow) return

    const missingBytes = (this.bytesLeft - byteCount) * -1
    if (missingBytes > 0) {
    this.appendBytes(missingBytes)
    }
    }

    // Buffer
    getBuffer(len=-1) {
    if (len === -1) len = this._view.byteLength - this._offset
    const offset = this._view.byteOffset + this._offset
    return this._view.buffer.slice(offset, offset + len)
    if (len === -1) len = this._view.byteLength - this._byteOffset
    const byteOffset = this._view.byteOffset + this._byteOffset
    return this._view.buffer.slice(byteOffset, byteOffset + len)
    }

    readBuffer(len=-1) {
    const buffer = this.getBuffer(len)
    this._offset += buffer.byteLength
    this._byteOffset += buffer.byteLength
    return buffer
    }

    setBuffer(buffer) {
    this.expectBytes(buffer.byteLength)
    const bytes = new Uint8Array(buffer)
    for (let i=0; i<bytes.length; i++) {
    this._view.setUint8(this._offset + i, bytes[i])
    this._view.setUint8(this._byteOffset + i, bytes[i])
    }
    }

    writeBuffer(buffer) {
    this.setBuffer(buffer)
    this._offset += buffer.byteLength
    this._byteOffset += buffer.byteLength
    }

    // Prefixed String
    getPString(byteLen=4) {
    const offset = this._offset
    const byteOffset = this._byteOffset
    let len = -1
    if (byteLen === 1) len = this.readInt8()
    else if (byteLen === 2) len = this.readInt16()
    else if (byteLen === 4) len = this.readInt32()
    const string = len > 0 ? this.readString(len) : ''
    this.seek(offset)
    this.seek(byteOffset)
    return string
    }

    readPString(byteLen=4) {
    const string = this.getPString(byteLen)
    this._offset += byteLen + string.length
    this._byteOffset += byteLen + string.length
    return string
    }

    setPString(string, byteLen=4) {
    const offset = this._offset
    const byteOffset = this._byteOffset
    this.writePString(string, byteLen)
    this.seek(offset)
    this.seek(byteOffset)
    }

    writePString(string, byteLen=4) {
    @@ -127,7 +134,7 @@ class DataStream {

    readString(len) {
    const string = this.getString(len)
    this._offset += len
    this._byteOffset += len
    return string
    }

  2. freehuntx created this gist Nov 5, 2024.
    141 changes: 141 additions & 0 deletions DataViewStream.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,141 @@
    class DataStream {
    _grow = false
    _offset = 0
    _view = null
    _textDecoder = new TextDecoder()
    _textEncoder = new TextEncoder()

    get offset() { return this._offset }
    get byteLength() { return this._view.byteLength }
    get bytesLeft() { return this._view.byteLength - this._offset }
    get buffer() { return this._view.buffer }

    constructor(buffer=null, grow=false) {
    this._grow = grow
    this._view = new DataView(buffer || new ArrayBuffer(0))

    for (const name of Object.getOwnPropertyNames(DataView.prototype)) {
    const match = name.match(/^([gs]et)([^\d]+)(\d+)$/)
    if (!match) continue

    const variant = match[1]
    const type = match[2]
    const bits = match[3]
    const bytes = bits / 8

    this[name] = function(...args) {
    return this._view[name](this._offset, ...args)
    }

    if (variant === 'get') {
    this[`read${type}${bits}`] = function(...args) {
    const res = this._view[name](this._offset, ...args)
    this._offset += bytes
    return res
    }
    } else {
    this[`write${type}${bits}`] = function(...args) {
    const missingBytes = (this.bytesLeft - bits/8) * -1
    if (missingBytes > 0 && this._grow) {
    this.appendBytes(missingBytes)
    }

    const res = this._view[name](this._offset, ...args)
    this._offset += bytes
    return res
    }
    }
    }
    }

    setCanGrow(grow) {
    this._grow = grow
    }

    seek(offset) {
    this._offset = offset
    }

    appendBytes(num) {
    if (!this._grow) throw new Error('Cannot grow')
    const oldBuffer = new Uint8Array(this._view.buffer)
    const newBuffer = new Uint8Array(new ArrayBuffer(oldBuffer.length + num))
    newBuffer.set(oldBuffer)
    this._view = new DataView(newBuffer.buffer)
    }

    // Buffer
    getBuffer(len=-1) {
    if (len === -1) len = this._view.byteLength - this._offset
    const offset = this._view.byteOffset + this._offset
    return this._view.buffer.slice(offset, offset + len)
    }

    readBuffer(len=-1) {
    const buffer = this.getBuffer(len)
    this._offset += buffer.byteLength
    return buffer
    }

    setBuffer(buffer) {
    const bytes = new Uint8Array(buffer)
    for (let i=0; i<bytes.length; i++) {
    this._view.setUint8(this._offset + i, bytes[i])
    }
    }

    writeBuffer(buffer) {
    this.setBuffer(buffer)
    this._offset += buffer.byteLength
    }

    // Prefixed String
    getPString(byteLen=4) {
    const offset = this._offset
    let len = -1
    if (byteLen === 1) len = this.readInt8()
    else if (byteLen === 2) len = this.readInt16()
    else if (byteLen === 4) len = this.readInt32()
    const string = len > 0 ? this.readString(len) : ''
    this.seek(offset)
    return string
    }

    readPString(byteLen=4) {
    const string = this.getPString(byteLen)
    this._offset += byteLen + string.length
    return string
    }

    setPString(string, byteLen=4) {
    const offset = this._offset
    this.writePString(string, byteLen)
    this.seek(offset)
    }

    writePString(string, byteLen=4) {
    if (byteLen === 1) this.writeInt8(string.length || -1)
    else if (byteLen === 2) this.writeInt16(string.length || -1)
    else if (byteLen === 4) this.writeInt32(string.length || -1)
    if (string.length > 0) this.writeString(string)
    }

    // String
    getString(len) {
    return this._textDecoder.decode(this.getBuffer(len))
    }

    readString(len) {
    const string = this.getString(len)
    this._offset += len
    return string
    }

    setString(string) {
    this.setBuffer(this._textEncoder.encode(string).buffer)
    }

    writeString(string) {
    this.writeBuffer(this._textEncoder.encode(string).buffer)
    }
    }