UNPKG

@moon7/bits

Version:

Type-safe bitwise operations for JavaScript and TypeScript with named bit collections

1 lines 12.6 kB
{"version":3,"file":"index.umd.cjs","sources":["../src/type.ts","../src/mask.ts","../src/bits.ts","../src/util.ts","../src/named.ts"],"sourcesContent":["/**\n * Represents a field of bits as a numeric value\n * Used for efficient storage and manipulation of boolean flags\n */\nexport type BitField = number;\n\n/**\n * Constant representing all bits set to 1\n * Equivalent to a bitfield with every bit enabled\n */\nexport const ALL: BitField = ~0 >>> 0;\n\n/**\n * Constant representing all bits set to 0\n * Equivalent to a bitfield with every bit disabled\n */\nexport const NONE: BitField = 0;\n","import { BitField } from \"~/type\";\n\n/**\n * Gets the power of 2 value (bitmask) based on the bit's position\n *\n * @param i - Zero-based index of the bit position\n * @returns A number with only the bit at position i set to 1\n *\n * @example\n * ```ts\n * bitMask(0) // Returns 1 (binary: 0001)\n * bitMask(1) // Returns 2 (binary: 0010)\n * bitMask(2) // Returns 4 (binary: 0100)\n * ```\n */\nexport function bitMask(i: number) {\n return (1 << i) >>> 0;\n}\n\n/**\n * Checks if any of the bits specified by the mask are set in the bitfield\n *\n * @param bits - The bitfield to check\n * @param mask - The bitmask specifying which bits to check\n * @returns `true` if any bit from the mask is set in the bitfield, otherwise `false`\n *\n * @example\n * ```ts\n * checkMask(5, 4) // Returns true (5 = 0101, 4 = 0100, bits overlap)\n * checkMask(5, 8) // Returns false (5 = 0101, 8 = 1000, no overlap)\n * ```\n */\nexport function checkMask(bits: BitField, mask: number): boolean {\n return (bits & mask) !== 0;\n}\n\n/**\n * Sets (turns on) multiple bits specified by the mask in the bitfield\n *\n * @param bits - The original bitfield\n * @param mask - The bitmask specifying which bits to set\n * @returns A new bitfield with the specified bits set\n *\n * @example\n * ```ts\n * applyMask(5, 8) // Returns 13 (5 = 0101, 8 = 1000, result = 1101)\n * ```\n */\nexport function applyMask(bits: BitField, mask: number): BitField {\n return (bits | mask) >>> 0;\n}\n\n/**\n * Clears (turns off) multiple bits specified by the mask in the bitfield\n *\n * @param bits - The original bitfield\n * @param mask - The bitmask specifying which bits to clear\n * @returns A new bitfield with the specified bits cleared\n *\n * @example\n * ```ts\n * clearMask(5, 4) // Returns 1 (5 = 0101, 4 = 0100, result = 0001)\n * ```\n */\nexport function clearMask(bits: BitField, mask: number): BitField {\n return bits & ~mask;\n}\n\n/**\n * Toggles multiple bits specified by the mask in the bitfield\n *\n * @param bits - The original bitfield\n * @param mask - The bitmask specifying which bits to toggle\n * @returns A new bitfield with the specified bits toggled\n *\n * @example\n * ```ts\n * toggleMask(5, 6) // Returns 3 (5 = 0101, 6 = 0110, result = 0011)\n * ```\n */\nexport function toggleMask(bits: BitField, mask: number): BitField {\n return (bits ^ mask) >>> 0;\n}\n","import { applyMask, bitMask, checkMask, clearMask, toggleMask } from \"~/mask\";\nimport { BitField } from \"~/type\";\n\n/**\n * Gets the value of a single bit at the specified index\n *\n * @param bits - The bitfield to check\n * @param index - Zero-based index of the bit to check\n * @returns `true` if the bit is set, otherwise `false`\n *\n * @example\n * ```ts\n * getBit(5, 0) // Returns true (5 = 0101, bit 0 is 1)\n * getBit(5, 1) // Returns false (5 = 0101, bit 1 is 0)\n * ```\n */\nexport function getBit(bits: BitField, index: number): boolean {\n return checkMask(bits, bitMask(index));\n}\n\n/**\n * Sets a single bit at the specified index to the given boolean value\n *\n * @param bits - The original bitfield\n * @param index - Zero-based index of the bit to set\n * @param value - The boolean value to set (true = 1, false = 0)\n * @returns A new bitfield with the bit at the specified index set to the given value\n *\n * @example\n * ```ts\n * setBit(5, 1, true) // Returns 7 (5 = 0101, setting bit 1 to 1 gives 0111)\n * setBit(5, 0, false) // Returns 4 (5 = 0101, setting bit 0 to 0 gives 0100)\n * ```\n */\nexport function setBit(bits: BitField, index: number, value: boolean): BitField {\n return value ? setBitOn(bits, index) : setBitOff(bits, index);\n}\n\n/**\n * Sets (turns on) a single bit at the specified index\n *\n * @param bits - The original bitfield\n * @param index - Zero-based index of the bit to enable\n * @returns A new bitfield with the bit at the specified index set to 1\n *\n * @example\n * ```ts\n * setBitOn(5, 1) // Returns 7 (5 = 0101, setting bit 1 to 1 gives 0111)\n * ```\n */\nexport function setBitOn(bits: BitField, index: number): BitField {\n return applyMask(bits, bitMask(index));\n}\n\n/**\n * Clears (turns off) a single bit at the specified index\n *\n * @param bits - The original bitfield\n * @param index - Zero-based index of the bit to disable\n * @returns A new bitfield with the bit at the specified index set to 0\n *\n * @example\n * ```ts\n * setBitOff(5, 0) // Returns 4 (5 = 0101, setting bit 0 to 0 gives 0100)\n * ```\n */\nexport function setBitOff(bits: BitField, index: number): BitField {\n return clearMask(bits, bitMask(index));\n}\n\n/**\n * Toggles a single bit at the specified index\n *\n * @param bits - The original bitfield\n * @param index - Zero-based index of the bit to toggle\n * @returns A new bitfield with the bit at the specified index toggled\n *\n * @example\n * ```ts\n * toggleBit(5, 0) // Returns 4 (5 = 0101, toggling bit 0 gives 0100)\n * toggleBit(5, 1) // Returns 7 (5 = 0101, toggling bit 1 gives 0111)\n * ```\n */\nexport function toggleBit(bits: BitField, index: number): BitField {\n return toggleMask(bits, bitMask(index));\n}\n","import { BitField } from \"~/type\";\n\n/**\n * Converts a bitfield to its binary string representation\n *\n * @param bits - The bitfield to convert\n * @param length - The length of the resulting string (default: 32)\n * @returns A string of 0s and 1s representing the bitfield\n *\n * @example\n * ```ts\n * toBinaryString(5) // Returns \"00000000000000000000000000000101\"\n * toBinaryString(5, 8) // Returns \"00000101\"\n * ```\n */\nexport function toBinaryString(bits: BitField, length = 32): string {\n return bits.toString(2).padStart(length, \"0\");\n}\n\n/**\n * Converts a bitfield to a formatted binary string with grouping\n * Groups bits in blocks of 4 and blocks of 8 for improved readability\n *\n * @param bits - The bitfield to convert\n * @param length - The length of the resulting string (default: 32)\n * @returns A formatted string with spaces between groups of 4 bits and dashes between groups of 8 bits\n *\n * @example\n * ```ts\n * toFormattedBinaryString(5) // Returns \"0000 0000 - 0000 0000 - 0000 0000 - 0000 0101\"\n * ```\n */\nexport function toFormattedBinaryString(bits: BitField, length = 32): string {\n const str = toBinaryString(bits, length);\n return (\n str\n .match(/.{1,8}/g)\n ?.map(x => x.match(/.{1,4}/g)?.join(\" \"))\n .join(\" - \") ?? \"\"\n );\n}\n\n/**\n * Counts the number of bits set to 1 in a bitfield\n *\n * @param bits - The bitfield to analyze\n * @returns The number of bits set to 1\n *\n * @example\n * ```ts\n * countBits(0b10101) // Returns 3\n * ```\n */\nexport function countBits(bits: BitField): number {\n let count = 0;\n let value = bits;\n while (value) {\n count += value & 1;\n value >>>= 1;\n }\n return count;\n}\n\n/**\n * Checks if exactly one bit is set in the bitfield\n *\n * @param bits - The bitfield to check\n * @returns `true` if exactly one bit is set, otherwise `false`\n *\n * @example\n * ```ts\n * isSingleBit(8) // Returns true (only bit 3 is set)\n * isSingleBit(9) // Returns false (bits 0 and 3 are set)\n * ```\n */\nexport function isSingleBit(bits: BitField): boolean {\n return bits !== 0 && (bits & (bits - 1)) === 0;\n}\n","/**\n * Functions and types for creating named bit collections\n * Provides a type-safe way to define constants for bit positions and retrieve their bitmasks\n * @module named\n */\n\nimport { bitMask } from \"~/mask\";\nimport { BitField } from \"~/type\";\n\n/**\n * Type for a named bit collection with a mask lookup function\n *\n * @template T - A record mapping string keys to bit position numbers\n * @extends T - Includes all the original named bit positions\n * @property mask - Function to get a bitmask for a named bit position\n */\nexport type BitFlags<T extends Record<string, number>> = T & { mask: (name: keyof T) => BitField };\n\n/**\n * Creates a named bit collection from an object with explicit bit positions\n *\n * @template T - A record mapping string keys to bit position numbers\n * @param definition - An object mapping names to bit positions\n * @returns A named bit collection with the original mappings plus a mask function\n *\n * @example\n * ```ts\n * const UserFlags = defineBitFlags({\n * ADMIN: 0, // bit 0\n * MODERATOR: 1, // bit 1\n * VERIFIED: 2, // bit 2\n * PREMIUM: 3 // bit 3\n * });\n *\n * // Get bit position\n * const adminPosition = UserFlags.ADMIN; // 0\n *\n * // Get bitmask\n * const adminMask = UserFlags.mask(\"ADMIN\"); // 1 (binary: 0001)\n * ```\n */\nexport function defineBitFlags<T extends Record<string, number>>(definition: T): BitFlags<T> {\n const result = { ...definition } as BitFlags<T>;\n result.mask = (name: keyof T) => bitMask(result[name]);\n return result;\n}\n\n/**\n * Type for a named bit collection created from a sequence of string names\n *\n * @template T - String literal type with the names of bit positions\n * @property [K in T] - Each name is mapped to its sequential bit position\n * @property mask - Function to get a bitmask for a named bit position\n */\nexport type BitEnum<T extends string> = { [K in T]: number } & { mask: (name: T) => BitField };\n\n/**\n * Creates a named bit collection from a sequence of string names\n * Each name is automatically assigned a sequential bit position starting from 0\n *\n * @template T - String literal type with the names of bit positions\n * @param names - String names for each bit position\n * @returns A named bit collection with sequential bit positions and a mask function\n *\n * @example\n * ```ts\n * const UserRoles = defineBitEnum(\n * \"GUEST\", // bit 0\n * \"MEMBER\", // bit 1\n * \"MODERATOR\", // bit 2\n * \"ADMIN\" // bit 3\n * );\n *\n * // Get bit position\n * const adminPosition = UserRoles.ADMIN; // 3\n *\n * // Get bitmask\n * const adminMask = UserRoles.mask(\"ADMIN\"); // 8 (binary: 1000)\n * ```\n */\nexport function defineBitEnum<T extends string>(...names: readonly T[]): BitEnum<T> {\n const result = {} as Record<string, number> & { mask: (name: T) => BitField };\n names.forEach((name, index) => (result[name] = index));\n result.mask = (name: T) => bitMask(result[name]);\n return result as BitEnum<T>;\n}\n"],"names":["_a"],"mappings":";;;;AAUa,QAAA,MAAgB,OAAO;AAM7B,QAAM,OAAiB;ACDvB,WAAS,QAAQ,GAAW;AAC/B,WAAQ,KAAK,MAAO;AAAA,EACxB;AAegB,WAAA,UAAU,MAAgB,MAAuB;AAC7D,YAAQ,OAAO,UAAU;AAAA,EAC7B;AAcgB,WAAA,UAAU,MAAgB,MAAwB;AAC9D,YAAQ,OAAO,UAAU;AAAA,EAC7B;AAcgB,WAAA,UAAU,MAAgB,MAAwB;AAC9D,WAAO,OAAO,CAAC;AAAA,EACnB;AAcgB,WAAA,WAAW,MAAgB,MAAwB;AAC/D,YAAQ,OAAO,UAAU;AAAA,EAC7B;AClEgB,WAAA,OAAO,MAAgB,OAAwB;AAC3D,WAAO,UAAU,MAAM,QAAQ,KAAK,CAAC;AAAA,EACzC;AAgBgB,WAAA,OAAO,MAAgB,OAAe,OAA0B;AAC5E,WAAO,QAAQ,SAAS,MAAM,KAAK,IAAI,UAAU,MAAM,KAAK;AAAA,EAChE;AAcgB,WAAA,SAAS,MAAgB,OAAyB;AAC9D,WAAO,UAAU,MAAM,QAAQ,KAAK,CAAC;AAAA,EACzC;AAcgB,WAAA,UAAU,MAAgB,OAAyB;AAC/D,WAAO,UAAU,MAAM,QAAQ,KAAK,CAAC;AAAA,EACzC;AAegB,WAAA,UAAU,MAAgB,OAAyB;AAC/D,WAAO,WAAW,MAAM,QAAQ,KAAK,CAAC;AAAA,EAC1C;ACtEgB,WAAA,eAAe,MAAgB,SAAS,IAAY;AAChE,WAAO,KAAK,SAAS,CAAC,EAAE,SAAS,QAAQ,GAAG;AAAA,EAChD;AAegB,WAAA,wBAAwB,MAAgB,SAAS,IAAY;;AACnE,UAAA,MAAM,eAAe,MAAM,MAAM;AACvC,aACI,SACK,MAAM,SAAS,MADpB,mBAEM,IAAI;;AAAK,cAAAA,MAAA,EAAE,MAAM,SAAS,MAAjB,gBAAAA,IAAoB,KAAK;AAAA,OACnC,KAAK,WAAU;AAAA,EAE5B;AAaO,WAAS,UAAU,MAAwB;AAC9C,QAAI,QAAQ;AACZ,QAAI,QAAQ;AACZ,WAAO,OAAO;AACV,eAAS,QAAQ;AACN,iBAAA;AAAA,IAAA;AAER,WAAA;AAAA,EACX;AAcO,WAAS,YAAY,MAAyB;AACjD,WAAO,SAAS,MAAM,OAAQ,OAAO,OAAQ;AAAA,EACjD;ACpCO,WAAS,eAAiD,YAA4B;AACnF,UAAA,SAAS,EAAE,GAAG,WAAW;AAC/B,WAAO,OAAO,CAAC,SAAkB,QAAQ,OAAO,IAAI,CAAC;AAC9C,WAAA;AAAA,EACX;AAmCO,WAAS,iBAAmC,OAAiC;AAChF,UAAM,SAAS,CAAC;AAChB,UAAM,QAAQ,CAAC,MAAM,UAAW,OAAO,IAAI,IAAI,KAAM;AACrD,WAAO,OAAO,CAAC,SAAY,QAAQ,OAAO,IAAI,CAAC;AACxC,WAAA;AAAA,EACX;;;;;;;;;;;;;;;;;;;;;"}