Bit Flag Utilities for Permission Sets
Represent up to 30 permissions as one 32-bit mask with helpers to build, test, add, remove, toggle and list enabled flags.
Code
export function createFlagSet(names) {
if (!Array.isArray(names) || names.length === 0) {
throw new TypeError("names must be a non-empty array");
}
if (names.length > 30) throw new RangeError("at most 30 flags are supported");
const bits = new Map();
const all = [];
for (const name of names) {
if (typeof name !== "string" || name.trim() === "") {
throw new TypeError("flag names must be non-empty strings");
}
const normalized = name.trim();
if (bits.has(normalized)) throw new Error(`duplicate flag "${normalized}"`);
bits.set(normalized, 1 << bits.size);
all.push(normalized);
}
const resolve = (name) => {
const bit = bits.get(name);
if (bit === undefined) throw new Error(`unknown flag "${name}"`);
return bit;
};
return {
names: () => [...all],
mask(...selected) {
return selected.reduce((mask, name) => mask | resolve(name), 0);
},
has(mask, name) {
return (mask & resolve(name)) !== 0;
},
add(mask, name) {
return mask | resolve(name);
},
remove(mask, name) {
return mask & ~resolve(name);
},
toggle(mask, name) {
return mask ^ resolve(name);
},
toNames(mask) {
return all.filter((name) => (mask & resolve(name)) !== 0);
},
};
}
const permissions = createFlagSet(["read", "write", "admin"]);
let mask = permissions.mask("read", "write");
console.log(mask, permissions.toNames(mask));
mask = permissions.remove(mask, "write");
mask = permissions.toggle(mask, "admin");
console.log(permissions.has(mask, "write"), permissions.toNames(mask));Report a problem with this exampleOpens a pre-filled issue on GitHub.