CRBT-Team/Purplet

View on GitHub
packages/serialize/src/BitBuffer.ts

Summary

Maintainability
A
0 mins
Test Coverage
export class BitBuffer {
  private array: Uint8Array;
  private byteIndex = 0;
  private bitIndex = 0;

  get index() {
    return this.byteIndex * 8 + this.bitIndex;
  }

  set index(value: number) {
    this.byteIndex = Math.floor(value / 8);
    this.bitIndex = value % 8;
  }

  get buffer() {
    return this.array.buffer;
  }

  set buffer(v: ArrayBufferLike) {
    this.array = new Uint8Array(v);
  }

  constructor(input: Uint8Array | ArrayBufferLike | ArrayLike<number> | number = 256) {
    this.array = new Uint8Array(
      input instanceof Uint8Array ? input.buffer : (input as ArrayBufferLike)
    );
  }

  seek(index: number) {
    this.index = index;
    return this;
  }

  read(length = 1) {
    let result = 0;
    for (let i = 0; i < length; i++) {
      const bit = (this.array[this.byteIndex] >> this.bitIndex) & 1;
      result |= bit << i;
      this.bitIndex++;
      if (this.bitIndex >= 8) {
        this.bitIndex = 0;
        this.byteIndex++;
      }
    }
    return result;
  }

  write(value: number, length = 1) {
    for (let i = 0; i < length; i++) {
      const bit = (value >> i) & 1;
      this.array[this.byteIndex] |= bit << this.bitIndex;
      this.bitIndex++;
      if (this.bitIndex >= 8) {
        this.bitIndex = 0;
        this.byteIndex++;
      }
    }
    return this;
  }

  readBI(length = 1) {
    let result = 0n;
    for (let i = 0n; i < length; i++) {
      const bit = (this.array[this.byteIndex] >> this.bitIndex) & 1;
      if (bit) {
        result |= 1n << i;
      }
      this.bitIndex++;
      if (this.bitIndex >= 8) {
        this.bitIndex = 0;
        this.byteIndex++;
      }
    }
    return result;
  }

  writeBI(value: bigint, length = 1) {
    for (let i = 0n; i < length; i++) {
      const bit = (value >> i) & 1n;
      if (bit) {
        this.array[this.byteIndex] |= 1 << this.bitIndex;
      }
      this.bitIndex++;
      if (this.bitIndex >= 8) {
        this.bitIndex = 0;
        this.byteIndex++;
      }
    }
    return this;
  }
}