UNPKG

@haelp/teto

Version:

A typescript-based controllable TETR.IO client.

161 lines (160 loc) 4.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "Bits", { enumerable: true, get: function() { return Bits; } }); const MAX_BITS = Number.MAX_SAFE_INTEGER.toString(2).length; class Bits { buffer; _length; _offset; constructor(t){ if (typeof t === "number") { this.buffer = Buffer.alloc(Math.ceil(t / 8)); } else if (t instanceof Buffer) { this.buffer = t; } else { throw new TypeError("Initialize by specifying a bit-length or referencing a Buffer"); } this._length = this.buffer.length * 8; this._offset = 0; } static alloc(t, r, n) { return new Bits(Buffer.alloc(t, r ?? 0, n)); } static from(t, r, n) { return new Bits(Buffer.from(t, r, n)); } get eof() { return this._offset === this._length; } get length() { return this._length; } get offset() { return this._offset; } set offset(t) { if (t < 0) { throw new RangeError("Cannot set offset below 0"); } if (t > this._length) { throw new RangeError(`Cannot set offset to ${t}, buffer length is ${this._length}`); } this._offset = Math.floor(t); } get remaining() { return this._length - this._offset; } clear(t = 0) { this.buffer.fill(t); this._offset = 0; return this; } clearBit(t) { this.insert(0, 1, t); return this; } flipBit(t) { const result = this.peek(1, t) ^ 1; this.modifyBit(result, t); return result; } getBit(t) { return this.peek(1, t); } insert(val, bits = 1, pos) { let r = typeof pos === "number" ? pos | 0 : this._offset; if (r + bits > this._length) { throw new RangeError(`Cannot write ${bits} bits, only ${this.remaining} bit(s) left`); } if (bits > MAX_BITS) { throw new RangeError(`Cannot write ${bits} bits, max is ${MAX_BITS}`); } let i = bits; while(i > 0){ const byteIndex = r >> 3; const bitIndex = r & 7; const o = Math.min(8 - bitIndex, i); const mask = (1 << o) - 1; const shift = 8 - o - bitIndex; const u = (val >>> i - o & mask) << shift; this.buffer[byteIndex] = this.buffer[byteIndex] & ~(mask << shift) | u; r += o; i -= o; } return r; } modifyBit(val, pos) { this.insert(val, 1, pos); return val; } peek(bits = 1, pos) { let e = typeof pos === "number" ? pos | 0 : this._offset; if (e + bits > this._length) { throw new RangeError(`Cannot read ${bits} bits, only ${this.remaining} bit(s) left`); } if (bits > MAX_BITS) { throw new RangeError(`Reading ${bits} bits would overflow result, max is ${MAX_BITS}`); } const bitOffset = e & 7; const i = Math.min(8 - bitOffset, bits); const mask = (1 << i) - 1; let s = this.buffer[e >> 3] >> 8 - i - bitOffset & mask; e += i; let remainingBits = bits - i; while(remainingBits >= 8){ s <<= 8; s |= this.buffer[e >> 3]; e += 8; remainingBits -= 8; } if (remainingBits > 0) { const shift = 8 - remainingBits; s <<= remainingBits; s |= this.buffer[e >> 3] >> shift & 255 >> shift; } return s; } read(bits = 1) { const val = this.peek(bits, this._offset); this._offset += bits; return val; } seek(t, mode = 1) { switch(mode){ case 2: this.offset = this._offset + t; break; case 3: this.offset = this.length - t; break; default: this.offset = t; } return this; } setBit(t) { this.insert(1, 1, t); return this; } skip(t) { return this.seek(t, 2); } testBit(t) { return !!this.peek(1, t); } toString(encoding = "utf8") { return this.buffer.toString(encoding); } write(val, bits = 1) { this._offset = this.insert(val, bits, this._offset); return this; } } //# sourceMappingURL=bits.js.map