tuples-boolean-bitmasker
TypeScript icon, indicating that this package has built-in type declarations

1.0.2 • Public • Published

tuples-boolean-bitmasker

Use fixed length array of boolean as input for comparsion system.

Version Size Dependencies
npm npm bundle size Libraries.io dependency status for latest release

Ever had to take a known length ordered set of booleans and wanted to compare if any item would end up checking essentially for true === true in multi-dimensional arrays as a way of filtering?

If this happened, maybe you've wondered if there were a quicker way?

There is, and it’s referenced in computer science terminology as a "Bit mask" and typically use "Bitwise" operators where we use numbers that are internally represented in binary and can mutate numbers using "Bitwise" operators such as shift bit, or inverse them, or compare against something ("Bit mask").

Binary? (a refresher)

(Disclaimer: The author is not a computer scientist, this a non exhaustive attempt at vulgarization, parts may be left out)

This is to illustrate how we can take a known set of booleans for any purpose, and how we can convert into numbers as a simpler way of doing filtering.

In binary, any number are sequence of 1 and 0 (a.k.a. base 2), any number is broken down like this. For example the number 22 (as decimal, or base 10, like we write it) in ECMAScript you can know by adding the radix argument (what numeral base) to the toString method; Number(22).toString(2) = 10110;

Decimal 22 in binary is 10110. Binary reads from right to left. Any 0 found when reading left-to-right are ignored too. It's helpful to us non-computers, but 0 is always ignored. Each 1 has a meaning in relation to where it is. Each slot as a value at the power of two 2n (that's where "base 2" is from).

So 10110 is broken down as 24 + 0 + 22 + 21 + 0 , or 16 + 0 + 4 + 2 + 0.

We could say that each binary slot have a meaning. As if 1 stands for true.

A "Bit mask" can be used as a query mechanism.

A "Bitwise" operation is a mutation mechanism to query.

Bitwise and Bit masks

We can use the numbers as way of storing enable/disable per bit, and we can use this library as an aid to visualize and also to make operations.

If we were to convert numbers in binary, and ask if there is a collision between the two, we'd use a "Bitwise" operator against each other:

101   -> Here's what I can do, I'm 5, my bits are flipped "on" at slot 1 and 4.
100   -> I'm just checkin' if you have bit 4 "on"

So the 101 (or 0b101) could be seen as a "Mask", from which we can compare against something else. Say 100 would be just before doing an action, checking if current user has its matching flag "on".

In that context, we want to check if both have something in common ("Logical AND"), the "Bitwise" walks each "slot" and sees if there is a bit flipped on (i.e. 1 instead of 0) successively at each slot from right to left.

In JavaScript, you'd do;

0b100 & 0b101 // 4

But what when there is no collision

100   -> Here's what I can do, I'm 4, my bits are flipped "on" only at slot 4
001   -> I'm just checkin' if you have bit 1 "on"

In JavaScript, you'd do

0b100 & 0b001 // 0

No collision, not enabled.

There are more use-cases for Bit masks and Bitwise operations than Logical AND, other use-cases can be used with this BitMasker and goes beyond the scope of this document.

Lastly, about Bit masking and Bitwise, as previously said, this principle is not new. It is common in low-level software (e.g. Linux Kernel, Networking, etc.). For example, the Linux filesystem modeled their File System permissions using a similar model. You can read more on Wikipedia about it.

Usage in the context of a Web Application

Now imagine your Redux or RxJS, or Vuex, or any application state system that contains values with booleans in them.

Sometimes we have requirements that asks to display data based on those booleans.

Requirements that might look like;

Artist's profile fields visibility

Field name Casting agent Artist Anonymous
phoneNumber N Y N
fullName N Y Y
artistName Y Y Y

And we have to walk through many objects to create an Artist data object Record.

For each field, we'd have to check if we can display it and we would manually write array of arrays and iterate.

How about we could tell, "display phone number when X"

// But that can get out of hand quickly
const displayMap: Record<string, [boolean, boolean, boolean]> = {
  phoneNumber: [false, true, false],
}

While storing mapping for hide/show mapping can be done in many ways, booleans feels nice. And is readable.

But, the faster way of covering all possible combinations that almost always been available in computes can be used.

Documentation about it feels a bit like dark magic, here's how we can help ourselves and use both methods together.

import BitMasker from 'tuples-boolean-bitmasker'
 
// displayMap would normally be built once per app startup
// Field visibility mapping should not change dynamically
// This could even come from a static JSON file loaded at App startup
const displayMap: Record<string, BitMasker> = {
  phoneNumber: new BitMasker([false, true, false]),
}
 
// But when it comes to what's sensitive to the current user
// We can do this dynamically
const CURRENT_USER = new BitMasker([true, true, false]) // 0b110
 
// Under the hood, BitMasker helps doing bitwise logic
// So we don't have to write things like this
 
// If we want to check if we should do something, we can use & operator
 
// If we get a non-zero, it means the 3rd bit is present
0b010 & 0b110 // 2
// Using BitMasker includes would do the same,
displayMap['phoneNumber'].includes(CURRENT_USER) // true
 
// Or the opposite
const ANOTHER_USER = new BitMasker([false, false, true])
0b010 & ANOTHER_USER.toNumber() // 0
displayMap['phoneNumber'].includes(ANOTHER_USER) // false

With BitMasker you can use both methods interchangeably.

Bookmarks

Links that helped me prototype

Package Sidebar

Install

npm i tuples-boolean-bitmasker

Weekly Downloads

1

Version

1.0.2

License

MIT

Unpacked Size

265 kB

Total Files

14

Last publish

Collaborators

  • renoirb