Files
grin-web-wallet/scripts/bit_reader.js
2024-12-20 18:08:44 -08:00

125 lines
2.6 KiB
JavaScript
Executable File

// Use strict
"use strict";
// Classes
// Bit reader class
class BitReader {
// Public
// Constructor
constructor(data) {
// Set data
this.data = data;
// Initialize byte index
this.byteIndex = 0;
// Initialize bit index
this.bitIndex = 0;
}
// Get bits
getBits(numberOfBits) {
// Check if more than one byte is requested
if(numberOfBits > Common.BITS_IN_A_BYTE) {
// Initialize result
var result = 0;
// Go through all bytes
while(numberOfBits > 0) {
// Update result to make space for more bits
result <<= Math.min(numberOfBits, Common.BITS_IN_A_BYTE);
// Include bits in result
result |= this.getBits(Math.min(numberOfBits, Common.BITS_IN_A_BYTE));
// Update number of bits
numberOfBits -= Common.BITS_IN_A_BYTE;
}
// Return result
return result;
}
// Otherwise
else {
// Check if no bits requested
if(numberOfBits === 0) {
// Return zero
return 0;
}
// Check if number of bits is invalid
if(this.byteIndex === this.data["length"] || (this.byteIndex === this.data["length"] - 1 && this.bitIndex + numberOfBits > Common.BITS_IN_A_BYTE)) {
// Throw error
throw "Invalid number of bits.";
}
// Initialize result to data at the byte index
var result = this.data[this.byteIndex] << Common.BITS_IN_A_BYTE;
// Check if more data is needed
if(this.bitIndex + numberOfBits > Common.BITS_IN_A_BYTE) {
// Append next byte to the result
result |= this.data[this.byteIndex + 1];
}
// Remove upper bits from result
result &= (1 << (Common.BITS_IN_A_BYTE * 2 - this.bitIndex)) - 1;
// Remove lower bits from result
result >>>= (Common.BITS_IN_A_BYTE * 2 - (this.bitIndex + numberOfBits));
// Update bit index
this.bitIndex += numberOfBits;
// Check if bit index overflowed into the next byte
if(this.bitIndex >= Common.BITS_IN_A_BYTE) {
// Increment byte index
++this.byteIndex;
// Correct bit index
this.bitIndex %= Common.BITS_IN_A_BYTE;
}
// Return result
return result;
}
}
// Get bytes
getBytes(numberOfBytes) {
// Initialize result
var result = new Uint8Array(numberOfBytes);
// Go through all bytes
for(var i = 0; i < numberOfBytes; ++i) {
// Set byte in the result
result[i] = this.getBits(Common.BITS_IN_A_BYTE);
}
// Return result
return result;
}
}
// Main function
// Set global object's bit reader
globalThis["BitReader"] = BitReader;