javascriptnode.jstypescriptbufferbitarray

How to read a single bit from a Buffer in TypeScript?


I am aware that a similar question has already been asked before (see How to read a single bit buffer in node), but it seems none of the answers are helful. The first comment that has been accepted, stating to use buf.readUIntLE(), is not working since 2 arguments are expected, but 0 was provided.

Thus, I am currently trying to read a single bit (the 17th one) from a Buffer, but I can't find a way to easily read it. I have been using buffer.readUInt16BE(0) to read the 2 first bytes of the Buffer and so far it works fine, but I need to assign the 17th bit to a variable.

Note: My Buffer data is Big-Endian and I am coding in TypeScript.

I thought about doing something like:

const myVar: number = parseInt(buffer.readUIntBE(2, 1).toString().slice(0,1));

in order to read, then stringify the 3th byte, then getting the first caracter and convert it into a number, but I find it very clunky.

Is there a simple way to achieve this ?

UPDATE

I finally decided to create myself a small utility function to read a specific bit in a Buffer/UInt8Array that seems to do the job pretty well. Note: Byte are always read from left to right and bits are read from left to right. That comes handy when using the function.

/**    
 * @name readBit()
 * @brief Allows to read the value of a bit in a buffer by specifying from which byte to read the specified bit. 
 * @param buffer The Buffer/UInt8Array to read the bit from.
 * @param index The zero-based cardinal index of the byte to read the bit from.
 * @param bit The zero-based cardinal index of the bit to read from the byte.
 * @return The bit value.
 */
export function readBit(buffer: Buffer, index: number, bit: number): number {
    return (buffer[index] >> bit) & 1;
}

export default readBit;

If you want the function to be more intuitive, and to specify the zero-based index from left to right of bits, the function must be modified to this instead:

/**    
 * @name readBit()
 * @brief Allows to read the value of a bit in a buffer by specifying from which byte to read the specified bit. 
 * @param buffer The Buffer/UInt8Array to read the bit from.
 * @param byteIndex The zero-based cardinal index of the byte to read the bit from. Bytes reading is from right to left.
 * @param bitIndex The zero-based cardinal index of the bit to read from the byte. Bits reading is from left to right.
 * @return The bit value.
 */
export function readBit(buffer: Buffer, byteIndex: number, bitIndex: number): number {
    return (buffer[byteIndex] >> 7 - bitIndex) & 1;
}

export default readBit;

Thanks a lot to @Bergi for his help with this.


Solution

  • A buffer is also a Uint8Array typed array, you can simply access its bytes by index. (If you prefer to do it with a method call, the equivalent would be readUint8). Then simply access the respective bit in that byte:

    const position = 17;
    const bitOffset = position & 7; // in byte
    const byteIndex = position >> 3; // in buffer
    const bit = (buffer[byteIndex] >> bitOffset) & 1;
    

    (Regarding the numbers: there are 8 = bits in a byte, and 7 is (1<<3)-1 or 0b111)

    If you subscribe to MSB 0 bit numbering, as is used in most network protocols, you will however have to do

    const bit = (buffer[byteIndex] >> (7 - bitOffset)) & 1;