finished implementation of BigBitFlagSets
This commit is contained in:
76
node/src/builders/bigint.ts
Normal file
76
node/src/builders/bigint.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { BigBitFlagDefinitionFactory, FlagDefinition } from '~/definitions'
|
||||
import { BigBitFlagSet } from '~/flagsets'
|
||||
|
||||
import {
|
||||
applyDeclarations,
|
||||
FlagWithValueOrOrdinal,
|
||||
ListOfFlagsWithValueOrOrdinal,
|
||||
NamedFlagWithValueOrOrdinal,
|
||||
} from './declarative'
|
||||
import { FlagSetBuilder } from './generic'
|
||||
import {
|
||||
DefineWithValueOrOrdinal,
|
||||
RequireParentsOrDefineWithValueOrOrdinal,
|
||||
WithValueOrOrdinal,
|
||||
WithValueOrOrdinalOrCompose,
|
||||
} from './syntax'
|
||||
|
||||
export class BigBitFlagSetBuilder
|
||||
implements
|
||||
WithValueOrOrdinalOrCompose<bigint, bigint, BigBitFlagSet>,
|
||||
RequireParentsOrDefineWithValueOrOrdinal<bigint, bigint, BigBitFlagSet>
|
||||
{
|
||||
private readonly _underlying: FlagSetBuilder<bigint>
|
||||
|
||||
public constructor() {
|
||||
this._underlying = new FlagSetBuilder()
|
||||
}
|
||||
|
||||
public define(): WithValueOrOrdinal<bigint, bigint, BigBitFlagSet>
|
||||
public define(alias: string): WithValueOrOrdinalOrCompose<bigint, bigint, BigBitFlagSet>
|
||||
public define(alias?: string): WithValueOrOrdinalOrCompose<bigint, bigint, BigBitFlagSet> {
|
||||
this._underlying.define(alias)
|
||||
return this
|
||||
}
|
||||
|
||||
public compose(...flags: string[]): DefineWithValueOrOrdinal<bigint, bigint, BigBitFlagSet> {
|
||||
this._underlying.compose(flags)
|
||||
return this
|
||||
}
|
||||
|
||||
public withValue(
|
||||
value: bigint,
|
||||
): RequireParentsOrDefineWithValueOrOrdinal<bigint, bigint, BigBitFlagSet> {
|
||||
this._underlying.withValue(value)
|
||||
return this
|
||||
}
|
||||
|
||||
public withOrdinal(
|
||||
ordinal: number,
|
||||
): RequireParentsOrDefineWithValueOrOrdinal<bigint, bigint, BigBitFlagSet> {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
public requires(...flags: string[]): DefineWithValueOrOrdinal<bigint, bigint, BigBitFlagSet> {
|
||||
this._underlying.requires(flags)
|
||||
return this
|
||||
}
|
||||
|
||||
public getResult(): BigBitFlagSet {
|
||||
const graph = this._underlying.finish()
|
||||
const factory = new BigBitFlagDefinitionFactory()
|
||||
return new BigBitFlagSet(graph.intoDictionary(factory))
|
||||
}
|
||||
}
|
||||
|
||||
export function createBigBitFlagSet(declarations: FlagWithValueOrOrdinal<bigint>[]): BigBitFlagSet
|
||||
export function createBigBitFlagSet<D extends string>(
|
||||
declarations: Record<D, NamedFlagWithValueOrOrdinal<bigint>>,
|
||||
): BigBitFlagSet & Record<D, FlagDefinition<bigint>>
|
||||
export function createBigBitFlagSet(
|
||||
declarations: ListOfFlagsWithValueOrOrdinal<bigint>,
|
||||
): BigBitFlagSet {
|
||||
const builder = new BigBitFlagSetBuilder()
|
||||
applyDeclarations(declarations, builder)
|
||||
return builder.getResult()
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
export { ArrayFlagSetBuilder, createArrayFlagSet } from './array'
|
||||
export { BigBitFlagSetBuilder, createBigBitFlagSet } from './bigint'
|
||||
export { CollectionFlagSetBuilder, createCollectionFlagSet } from './collection'
|
||||
export { BitFlagSetBuilder, createBitFlagSet } from './number'
|
||||
|
||||
88
node/src/definitions/bigint.ts
Normal file
88
node/src/definitions/bigint.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { ENV_BI } from '~/env'
|
||||
|
||||
import { FlagDefinition, FlagDefinitionFactory, PartialFlagDefinition } from '.'
|
||||
|
||||
interface PrecomputedValues {
|
||||
base: bigint
|
||||
additive: bigint
|
||||
subtractive: bigint
|
||||
}
|
||||
|
||||
export class BigBitFlagDefinition implements FlagDefinition<bigint> {
|
||||
private readonly _baseValue: bigint
|
||||
private readonly _additiveValue: bigint
|
||||
private readonly _subtractiveValue: bigint
|
||||
private readonly _alias: string | undefined
|
||||
|
||||
public constructor(precomputedValues: PrecomputedValues, alias: string | undefined) {
|
||||
this._baseValue = precomputedValues.base
|
||||
this._additiveValue = precomputedValues.additive
|
||||
this._subtractiveValue = precomputedValues.subtractive
|
||||
this._alias = alias
|
||||
}
|
||||
|
||||
public get alias(): string | undefined {
|
||||
return this._alias
|
||||
}
|
||||
|
||||
public get values(): bigint {
|
||||
return this._baseValue
|
||||
}
|
||||
|
||||
public isIn(set: bigint): boolean {
|
||||
return (set & this._additiveValue) === this._additiveValue
|
||||
}
|
||||
|
||||
public addTo(set: bigint): bigint {
|
||||
return set | this._additiveValue
|
||||
}
|
||||
|
||||
public removeFrom(set: bigint): bigint {
|
||||
return set | this._additiveValue
|
||||
}
|
||||
}
|
||||
|
||||
export class BigBitFlagDefinitionFactory implements FlagDefinitionFactory<bigint, bigint> {
|
||||
public makeDefinitions(
|
||||
sortedPartialDefinitions: PartialFlagDefinition<bigint>[],
|
||||
results: Map<PartialFlagDefinition<bigint>, FlagDefinition<bigint>>,
|
||||
): void {
|
||||
const precomputedValues = new Map<PartialFlagDefinition<bigint>, PrecomputedValues>()
|
||||
|
||||
for (let i = 0; i < sortedPartialDefinitions.length; i++) {
|
||||
const pfd = sortedPartialDefinitions[i]
|
||||
|
||||
const values: PrecomputedValues = {
|
||||
base: pfd.value ?? ENV_BI.ZERO,
|
||||
additive: pfd.value ?? ENV_BI.ZERO,
|
||||
subtractive: pfd.value ?? ENV_BI.ZERO,
|
||||
}
|
||||
|
||||
for (const parentPfd of pfd.parents) {
|
||||
const parentValues = precomputedValues.get(parentPfd)
|
||||
if (parentValues !== undefined) {
|
||||
values.additive = values.additive | parentValues.additive
|
||||
if (pfd.value === undefined) {
|
||||
values.base = values.base | parentValues.base
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
precomputedValues.set(pfd, values)
|
||||
}
|
||||
|
||||
for (let i = sortedPartialDefinitions.length - 1; i >= 0; i--) {
|
||||
const pfd = sortedPartialDefinitions[i]
|
||||
const values = precomputedValues.get(pfd)!
|
||||
|
||||
for (const childPfd of pfd.children) {
|
||||
const childValues = precomputedValues.get(childPfd)
|
||||
if (childValues !== undefined) {
|
||||
values.subtractive = values.subtractive | childValues.subtractive
|
||||
}
|
||||
}
|
||||
|
||||
results.set(pfd, new BigBitFlagDefinition(values, pfd.alias))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,10 @@
|
||||
export { FlagsDictionary, FlagDefinition, printFlagValue, valueToString } from './dictionary'
|
||||
export { BigBitFlagDefinition, BigBitFlagDefinitionFactory } from './bigint'
|
||||
export { FlagDefinition, FlagsDictionary, printFlagValue, valueToString } from './dictionary'
|
||||
export {
|
||||
FlagsGraph,
|
||||
PartialFlagInit,
|
||||
PartialFlagDefinition,
|
||||
refByAlias,
|
||||
FlagDefinitionFactory,
|
||||
FlagsGraph,
|
||||
PartialFlagDefinition,
|
||||
PartialFlagInit,
|
||||
refByAlias,
|
||||
} from './graph'
|
||||
export { BitFlagDefinition, BitFlagDefinitionFactory } from './number'
|
||||
|
||||
@@ -1,33 +1,31 @@
|
||||
import { FlagDefinition, FlagsDictionary } from '~/definitions'
|
||||
import { BigBitFlagsIterator, EnumerateFlags, useIterator } from '~/enumeration'
|
||||
import { ENV_BI } from '~/env'
|
||||
|
||||
import type { FlagSet } from '.'
|
||||
import { UnavailableFeatureError } from '../errors'
|
||||
import { ENV_BI } from '../env'
|
||||
import { BigBitFlagsIterator, EnumerateFlags, useIterator } from '../enumeration'
|
||||
|
||||
export class BigBitFlagSet implements FlagSet<bigint, bigint> {
|
||||
/**
|
||||
* Creates a new empty flag set.
|
||||
*
|
||||
* @throws UnavailableFeatureError When this constructor is called in an
|
||||
* environment that does not natively support {@link BigInt}s.
|
||||
*/
|
||||
public constructor() {
|
||||
if (!ENV_BI.AVAILABLE) {
|
||||
throw new UnavailableFeatureError('BigInts')
|
||||
}
|
||||
}
|
||||
private readonly _dictionary: FlagsDictionary<bigint, bigint>
|
||||
|
||||
minimum(flags: bigint): bigint {
|
||||
throw new Error('Method not implemented.')
|
||||
}
|
||||
|
||||
maximum(flags: bigint): bigint {
|
||||
throw new Error('Method not implemented.')
|
||||
public constructor(dictionary: FlagsDictionary<bigint, bigint>) {
|
||||
this._dictionary = dictionary
|
||||
}
|
||||
|
||||
public none(): bigint {
|
||||
return ENV_BI.ZERO
|
||||
}
|
||||
|
||||
public of(...values: bigint[]): bigint {
|
||||
return values.reduce((set, value) => set | value, ENV_BI.ZERO)
|
||||
}
|
||||
|
||||
public named(...aliases: string[]): bigint {
|
||||
return aliases.reduce(
|
||||
(set, alias) => set | (this.getFlag(alias)?.values ?? ENV_BI.ZERO),
|
||||
ENV_BI.ZERO,
|
||||
)
|
||||
}
|
||||
|
||||
public union(first: bigint, second: bigint): bigint {
|
||||
return first | second
|
||||
}
|
||||
@@ -44,11 +42,41 @@ export class BigBitFlagSet implements FlagSet<bigint, bigint> {
|
||||
return (first & second) == second
|
||||
}
|
||||
|
||||
public hasAny(flags: bigint, required: bigint): boolean {
|
||||
return this.minimum(this.intersection(flags, required)) !== ENV_BI.ZERO
|
||||
}
|
||||
|
||||
public hasAll(flags: bigint, required: bigint): boolean {
|
||||
return this.isSuperset(flags, this.maximum(required))
|
||||
}
|
||||
|
||||
public enumerate(flags: bigint): EnumerateFlags<bigint> {
|
||||
return useIterator(flags, BigBitFlagsIterator)
|
||||
}
|
||||
|
||||
public getFlag(alias: string): FlagDefinition<number, number> | undefined {
|
||||
return this._dictionary.lookUp(alias)
|
||||
public maximum(flags: bigint): bigint {
|
||||
let result = ENV_BI.ZERO
|
||||
for (const value of this.enumerate(flags)) {
|
||||
const definition = this._dictionary.findByValue(value)
|
||||
if (definition !== undefined) {
|
||||
result = definition.addTo(result)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public minimum(flags: bigint): bigint {
|
||||
let result = ENV_BI.ZERO
|
||||
for (const value of this.enumerate(flags)) {
|
||||
const definition = this._dictionary.findByValue(value)
|
||||
if (definition !== undefined && definition.isIn(flags)) {
|
||||
result = definition.addTo(result)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
public getFlag(alias: string): FlagDefinition<bigint> | undefined {
|
||||
return this._dictionary.findByAlias(alias)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,66 @@
|
||||
import type { FlagSet } from '.'
|
||||
import { BitFlagsIterator, EnumerateFlags, useIterator } from '~/enumeration'
|
||||
import { FlagDefinition, FlagsDictionary } from '~/definitions'
|
||||
import { BigBitFlagsIterator, BitFlagsIterator, EnumerateFlags, useIterator } from '~/enumeration'
|
||||
|
||||
import type { FlagSet } from '.'
|
||||
|
||||
export const BitFlags = {
|
||||
union<T extends number | bigint>(first: T, second: T): T {
|
||||
return (first | second) as T
|
||||
},
|
||||
|
||||
intersection<T extends number | bigint>(first: T, second: T): T {
|
||||
return (first & second) as T
|
||||
},
|
||||
|
||||
difference<T extends number | bigint>(first: T, second: T): T {
|
||||
return (first & ~second) as T
|
||||
},
|
||||
|
||||
isSuperset<T extends number | bigint>(first: T, second: T): boolean {
|
||||
return (first & second) === second
|
||||
},
|
||||
|
||||
enumerate<T extends number | bigint>(flags: T): EnumerateFlags<T> {
|
||||
if (typeof flags === 'number') {
|
||||
return useIterator(flags, BitFlagsIterator) as EnumerateFlags<T>
|
||||
} else {
|
||||
return useIterator(flags, BigBitFlagsIterator) as EnumerateFlags<T>
|
||||
}
|
||||
},
|
||||
} as {
|
||||
/**
|
||||
* Computes the union of two sets of bitflags.
|
||||
* Any bits that are set in either of the inputs will be set in the result.
|
||||
*/
|
||||
union(first: number, second: number): number {
|
||||
return first | second
|
||||
},
|
||||
union(first: number, second: number): number
|
||||
union(first: bigint, second: bigint): bigint
|
||||
|
||||
/**
|
||||
* Computes the intersection of two sets of bitflags.
|
||||
* Only bits that are set in both of the inputs will be set in the result.
|
||||
*/
|
||||
intersection(first: number, second: number): number {
|
||||
return first & second
|
||||
},
|
||||
intersection(first: number, second: number): number
|
||||
intersection(first: bigint, second: bigint): bigint
|
||||
|
||||
/**
|
||||
* Computes the difference between two sets of bitflags.
|
||||
* Only bits that are set in the first input and not set in the second will be set in the result.
|
||||
*/
|
||||
difference(first: number, second: number): number {
|
||||
return first & ~second
|
||||
},
|
||||
difference(first: number, second: number): number
|
||||
difference(first: bigint, second: bigint): bigint
|
||||
|
||||
/**
|
||||
* Tests if a set of bitflags is a superset of the other.
|
||||
* Return `true` if every bit that is set in the second input is also set in the first.
|
||||
*/
|
||||
isSuperset(first: number, second: number): boolean {
|
||||
return (first & second) === second
|
||||
},
|
||||
isSuperset(first: number, second: number): boolean
|
||||
isSuperset(first: bigint, second: bigint): boolean
|
||||
|
||||
/**
|
||||
* Returns an iterable over the individual bits that are set.
|
||||
*/
|
||||
enumerate(flags: number): EnumerateFlags<number> {
|
||||
return useIterator(flags, BitFlagsIterator)
|
||||
},
|
||||
enumerate(flags: number): EnumerateFlags<number>
|
||||
enumerate(flags: bigint): EnumerateFlags<bigint>
|
||||
}
|
||||
|
||||
export class BitFlagSet implements FlagSet<number, number> {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
export { createArrayFlagSet, createBitFlagSet, createCollectionFlagSet } from './builders'
|
||||
export {
|
||||
createArrayFlagSet,
|
||||
createBigBitFlagSet,
|
||||
createBitFlagSet,
|
||||
createCollectionFlagSet,
|
||||
} from './builders'
|
||||
export { FlagDefinition } from './definitions'
|
||||
export { InvalidBitFlagValueError } from './errors'
|
||||
export {
|
||||
|
||||
@@ -1,15 +1,41 @@
|
||||
import { BigBitFlagSet } from '~'
|
||||
import { describe, expect, test } from 'vitest'
|
||||
|
||||
import { BigBitFlagSet, BitFlags, createBigBitFlagSet } from '~'
|
||||
|
||||
describe(BigBitFlagSet, () => {
|
||||
test('none', () => {
|
||||
const flags = new BigBitFlagSet()
|
||||
const flags = createBigBitFlagSet([])
|
||||
|
||||
expect(flags.none()).toEqual(0n)
|
||||
})
|
||||
|
||||
test('of', () => {
|
||||
const flags = createBigBitFlagSet([])
|
||||
|
||||
expect(flags.of()).toEqual(0n)
|
||||
expect(flags.of(1n)).toEqual(1n)
|
||||
expect(flags.of(3n, 8n)).toEqual(11n)
|
||||
expect(flags.of(3n, 5n, 2n)).toEqual(7n)
|
||||
})
|
||||
|
||||
test('named', () => {
|
||||
const flags = createBigBitFlagSet([
|
||||
{ value: 1n, as: 'A' },
|
||||
{ value: 2n, as: 'B' },
|
||||
{ value: 4n, as: 'C' },
|
||||
{ value: 8n, as: 'D' },
|
||||
{ compose: ['A', 'B'], as: 'AB' },
|
||||
{ compose: ['A', 'C'], as: 'AC' },
|
||||
])
|
||||
|
||||
expect(flags.named()).toEqual(0n)
|
||||
expect(flags.named('A')).toEqual(1n)
|
||||
expect(flags.named('AB', 'D')).toEqual(11n)
|
||||
expect(flags.named('AB', 'AC', 'B')).toEqual(7n)
|
||||
})
|
||||
|
||||
test('union', () => {
|
||||
const flags = new BigBitFlagSet()
|
||||
const flags = createBigBitFlagSet([])
|
||||
|
||||
expect(flags.union(0n, 0n)).toEqual(0n)
|
||||
expect(flags.union(1n, 0n)).toEqual(1n)
|
||||
@@ -19,7 +45,7 @@ describe(BigBitFlagSet, () => {
|
||||
})
|
||||
|
||||
test('difference', () => {
|
||||
const flags = new BigBitFlagSet()
|
||||
const flags = createBigBitFlagSet([])
|
||||
|
||||
expect(flags.difference(0n, 0n)).toEqual(0n)
|
||||
expect(flags.difference(1n, 0n)).toEqual(1n)
|
||||
@@ -29,7 +55,7 @@ describe(BigBitFlagSet, () => {
|
||||
})
|
||||
|
||||
test('intersection', () => {
|
||||
const flags = new BigBitFlagSet()
|
||||
const flags = createBigBitFlagSet([])
|
||||
|
||||
expect(flags.intersection(0n, 0n)).toEqual(0n)
|
||||
expect(flags.intersection(1n, 0n)).toEqual(0n)
|
||||
@@ -40,7 +66,7 @@ describe(BigBitFlagSet, () => {
|
||||
})
|
||||
|
||||
test('isSuperset', () => {
|
||||
const flags = new BigBitFlagSet()
|
||||
const flags = createBigBitFlagSet([])
|
||||
|
||||
expect(flags.isSuperset(0n, 0n)).toBe(true)
|
||||
expect(flags.isSuperset(3n, 0n)).toBe(true)
|
||||
@@ -50,8 +76,40 @@ describe(BigBitFlagSet, () => {
|
||||
expect(flags.isSuperset(8n, 4n)).toBe(false)
|
||||
})
|
||||
|
||||
test('hasAny', () => {
|
||||
const flags = createBigBitFlagSet([
|
||||
{ value: 1n, as: 'A' },
|
||||
{ value: 2n, as: 'B', requires: ['A'] },
|
||||
{ value: 4n, as: 'C', requires: ['A'] },
|
||||
{ value: 8n, as: 'D', requires: ['B', 'C'] },
|
||||
])
|
||||
|
||||
expect(flags.hasAny(15n, 0n)).toBe(false)
|
||||
expect(flags.hasAny(0n, 0n)).toBe(false)
|
||||
expect(flags.hasAny(7n, 1n)).toBe(true)
|
||||
expect(flags.hasAny(1n, 7n)).toBe(true)
|
||||
expect(flags.hasAny(5n, 12n)).toBe(false)
|
||||
expect(flags.hasAny(2n, 2n)).toBe(false)
|
||||
})
|
||||
|
||||
test('hasAll', () => {
|
||||
const flags = createBigBitFlagSet([
|
||||
{ value: 1n, as: 'A' },
|
||||
{ value: 2n, as: 'B', requires: ['A'] },
|
||||
{ value: 4n, as: 'C', requires: ['A'] },
|
||||
{ value: 8n, as: 'D', requires: ['B', 'C'] },
|
||||
])
|
||||
|
||||
expect(flags.hasAll(15n, 0n)).toBe(true)
|
||||
expect(flags.hasAll(0n, 0n)).toBe(true)
|
||||
expect(flags.hasAll(7n, 2n)).toBe(true)
|
||||
expect(flags.hasAll(6n, 2n)).toBe(false)
|
||||
expect(flags.hasAll(1n, 7n)).toBe(false)
|
||||
expect(flags.hasAll(5n, 12n)).toBe(false)
|
||||
})
|
||||
|
||||
test('enumerate', () => {
|
||||
const flags = new BigBitFlagSet()
|
||||
const flags = createBigBitFlagSet([])
|
||||
|
||||
expect([...flags.enumerate(0n)]).toEqual([])
|
||||
expect([...flags.enumerate(1n)]).toEqual([1n])
|
||||
@@ -60,4 +118,81 @@ describe(BigBitFlagSet, () => {
|
||||
expect([...flags.enumerate(11n)]).toEqual([1n, 2n, 8n])
|
||||
expect([...flags.enumerate(100n)]).toEqual([4n, 32n, 64n])
|
||||
})
|
||||
|
||||
test('maximum', () => {
|
||||
const flags = createBigBitFlagSet([
|
||||
{ value: 1n, as: 'A' },
|
||||
{ value: 2n, as: 'B', requires: ['A'] },
|
||||
{ value: 4n, as: 'C', requires: ['A'] },
|
||||
{ value: 8n, as: 'D', requires: ['B', 'C'] },
|
||||
])
|
||||
|
||||
expect(flags.maximum(0n)).toEqual(0n)
|
||||
expect(flags.maximum(1n)).toEqual(1n)
|
||||
expect(flags.maximum(2n)).toEqual(3n)
|
||||
expect(flags.maximum(3n)).toEqual(3n)
|
||||
expect(flags.maximum(4n)).toEqual(5n)
|
||||
expect(flags.maximum(8n)).toEqual(15n)
|
||||
})
|
||||
|
||||
test('minimum', () => {
|
||||
const flags = createBigBitFlagSet([
|
||||
{ value: 1n, as: 'A' },
|
||||
{ value: 2n, as: 'B', requires: ['A'] },
|
||||
{ value: 4n, as: 'C', requires: ['A'] },
|
||||
{ value: 8n, as: 'D', requires: ['B', 'C'] },
|
||||
])
|
||||
|
||||
expect(flags.minimum(0n)).toEqual(0n)
|
||||
expect(flags.minimum(1n)).toEqual(1n)
|
||||
expect(flags.minimum(2n)).toEqual(0n)
|
||||
expect(flags.minimum(3n)).toEqual(3n)
|
||||
expect(flags.minimum(4n)).toEqual(0n)
|
||||
expect(flags.minimum(13n)).toEqual(5n)
|
||||
})
|
||||
})
|
||||
|
||||
describe('BitFlags', () => {
|
||||
test('union', () => {
|
||||
expect(BitFlags.union(0n, 0n)).toEqual(0n)
|
||||
expect(BitFlags.union(1n, 0n)).toEqual(1n)
|
||||
expect(BitFlags.union(0n, 2n)).toEqual(2n)
|
||||
expect(BitFlags.union(1n, 2n)).toEqual(3n)
|
||||
expect(BitFlags.union(3n, 6n)).toEqual(7n)
|
||||
})
|
||||
|
||||
test('difference', () => {
|
||||
expect(BitFlags.difference(0n, 0n)).toEqual(0n)
|
||||
expect(BitFlags.difference(1n, 0n)).toEqual(1n)
|
||||
expect(BitFlags.difference(3n, 6n)).toEqual(1n)
|
||||
expect(BitFlags.difference(6n, 3n)).toEqual(4n)
|
||||
expect(BitFlags.difference(8n, 17n)).toEqual(8n)
|
||||
})
|
||||
|
||||
test('intersection', () => {
|
||||
expect(BitFlags.intersection(0n, 0n)).toEqual(0n)
|
||||
expect(BitFlags.intersection(1n, 0n)).toEqual(0n)
|
||||
expect(BitFlags.intersection(1n, 2n)).toEqual(0n)
|
||||
expect(BitFlags.intersection(1n, 3n)).toEqual(1n)
|
||||
expect(BitFlags.intersection(11n, 5n)).toEqual(1n)
|
||||
expect(BitFlags.intersection(11n, 7n)).toEqual(3n)
|
||||
})
|
||||
|
||||
test('isSuperset', () => {
|
||||
expect(BitFlags.isSuperset(0n, 0n)).toBe(true)
|
||||
expect(BitFlags.isSuperset(3n, 0n)).toBe(true)
|
||||
expect(BitFlags.isSuperset(3n, 1n)).toBe(true)
|
||||
expect(BitFlags.isSuperset(3n, 3n)).toBe(true)
|
||||
expect(BitFlags.isSuperset(0n, 3n)).toBe(false)
|
||||
expect(BitFlags.isSuperset(8n, 4n)).toBe(false)
|
||||
})
|
||||
|
||||
test('enumerate', () => {
|
||||
expect([...BitFlags.enumerate(0n)]).toEqual([])
|
||||
expect([...BitFlags.enumerate(1n)]).toEqual([1n])
|
||||
expect([...BitFlags.enumerate(2n)]).toEqual([2n])
|
||||
expect([...BitFlags.enumerate(3n)]).toEqual([1n, 2n])
|
||||
expect([...BitFlags.enumerate(11n)]).toEqual([1n, 2n, 8n])
|
||||
expect([...BitFlags.enumerate(100n)]).toEqual([4n, 32n, 64n])
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user