Skip to content

Instantly share code, notes, and snippets.

@trophygeek
Last active October 18, 2023 14:27
Show Gist options
  • Save trophygeek/d67ecb90cdb5f093313757d9e0d7f46e to your computer and use it in GitHub Desktop.
Save trophygeek/d67ecb90cdb5f093313757d9e0d7f46e to your computer and use it in GitHub Desktop.
Simple and easy to understand bloom filter in javascript for the browser. Uses BigInts and crypto.subtle.digest in 29 lines
/**
Simple and fast bloom filter (about 40 lines of actual code)
Uses build-in hash and BigInts to do work. Hash requires async/await
Meant for use in browser code not node
used like this:
// add to bloom
const bloomFilter = new BloomFilter();
bloomFilter.loadSaved(); // optional loading from localstorage
await bloomFilter.add("test1");
await bloomFilter.add("test2");
...
// check for values later
const found = await.bloomFilter.contains("test1"); // MAY be in bloom
const notFound = await.bloomFilter.contains("test3"); // Definitely NOT in bloom
...
bloomFilter.save(); // optional save
**/
class BloomFilter {
// may use 'SHA-256' for better distribution
constructor(shaStr='SHA-1') {
this.bloomBigInt = BigInt(0);
this.encoder = new TextEncoder(); // performance
this.shaStr = shaStr;
}
async hash(item) {
// hash into buffer
const hashBuffer = await crypto.subtle.digest(this.shaStr, // e.g.'SHA-1'
this.encoder.encode(item));
// hash buffer to bigint passes through hex string. must be a better way?
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray
.map((b) => b.toString(16).padStart(2, "0"))
.join("");
return BigInt(`0x${hashHex}`);
}
async add(item) {
const bn = await this.hash(item);
this.bloomBigInt = bn | this.bloomBigInt;
}
async contains(item) {
const bn = await this.hash(item);
return (bn & this.bloomBigInt) === bn;
}
// the save/restore could use some work
save() {
localStorage.setItem(`bloomSha1`, this.bloomBigInt.toString());
}
loadSaved() {
const loadedBitsStr = localStorage.getItem(`bloomSha1`) || '';
if (loadedBitsStr?.length) {
this.bloomBigInt = BigInt(loadedBitsStr);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment