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 { ArrayFlagSetBuilder, createArrayFlagSet } from './array'
|
||||||
|
export { BigBitFlagSetBuilder, createBigBitFlagSet } from './bigint'
|
||||||
export { CollectionFlagSetBuilder, createCollectionFlagSet } from './collection'
|
export { CollectionFlagSetBuilder, createCollectionFlagSet } from './collection'
|
||||||
export { BitFlagSetBuilder, createBitFlagSet } from './number'
|
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 {
|
export {
|
||||||
FlagsGraph,
|
|
||||||
PartialFlagInit,
|
|
||||||
PartialFlagDefinition,
|
|
||||||
refByAlias,
|
|
||||||
FlagDefinitionFactory,
|
FlagDefinitionFactory,
|
||||||
|
FlagsGraph,
|
||||||
|
PartialFlagDefinition,
|
||||||
|
PartialFlagInit,
|
||||||
|
refByAlias,
|
||||||
} from './graph'
|
} from './graph'
|
||||||
export { BitFlagDefinition, BitFlagDefinitionFactory } from './number'
|
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 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> {
|
export class BigBitFlagSet implements FlagSet<bigint, bigint> {
|
||||||
/**
|
private readonly _dictionary: FlagsDictionary<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')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
minimum(flags: bigint): bigint {
|
public constructor(dictionary: FlagsDictionary<bigint, bigint>) {
|
||||||
throw new Error('Method not implemented.')
|
this._dictionary = dictionary
|
||||||
}
|
|
||||||
|
|
||||||
maximum(flags: bigint): bigint {
|
|
||||||
throw new Error('Method not implemented.')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public none(): bigint {
|
public none(): bigint {
|
||||||
return ENV_BI.ZERO
|
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 {
|
public union(first: bigint, second: bigint): bigint {
|
||||||
return first | second
|
return first | second
|
||||||
}
|
}
|
||||||
@@ -44,11 +42,41 @@ export class BigBitFlagSet implements FlagSet<bigint, bigint> {
|
|||||||
return (first & second) == second
|
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> {
|
public enumerate(flags: bigint): EnumerateFlags<bigint> {
|
||||||
return useIterator(flags, BigBitFlagsIterator)
|
return useIterator(flags, BigBitFlagsIterator)
|
||||||
}
|
}
|
||||||
|
|
||||||
public getFlag(alias: string): FlagDefinition<number, number> | undefined {
|
public maximum(flags: bigint): bigint {
|
||||||
return this._dictionary.lookUp(alias)
|
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 { FlagDefinition, FlagsDictionary } from '~/definitions'
|
||||||
|
import { BigBitFlagsIterator, BitFlagsIterator, EnumerateFlags, useIterator } from '~/enumeration'
|
||||||
|
|
||||||
|
import type { FlagSet } from '.'
|
||||||
|
|
||||||
export const BitFlags = {
|
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.
|
* Computes the union of two sets of bitflags.
|
||||||
* Any bits that are set in either of the inputs will be set in the result.
|
* Any bits that are set in either of the inputs will be set in the result.
|
||||||
*/
|
*/
|
||||||
union(first: number, second: number): number {
|
union(first: number, second: number): number
|
||||||
return first | second
|
union(first: bigint, second: bigint): bigint
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the intersection of two sets of bitflags.
|
* Computes the intersection of two sets of bitflags.
|
||||||
* Only bits that are set in both of the inputs will be set in the result.
|
* Only bits that are set in both of the inputs will be set in the result.
|
||||||
*/
|
*/
|
||||||
intersection(first: number, second: number): number {
|
intersection(first: number, second: number): number
|
||||||
return first & second
|
intersection(first: bigint, second: bigint): bigint
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Computes the difference between two sets of bitflags.
|
* 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.
|
* 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 {
|
difference(first: number, second: number): number
|
||||||
return first & ~second
|
difference(first: bigint, second: bigint): bigint
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if a set of bitflags is a superset of the other.
|
* 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.
|
* Return `true` if every bit that is set in the second input is also set in the first.
|
||||||
*/
|
*/
|
||||||
isSuperset(first: number, second: number): boolean {
|
isSuperset(first: number, second: number): boolean
|
||||||
return (first & second) === second
|
isSuperset(first: bigint, second: bigint): boolean
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an iterable over the individual bits that are set.
|
* Returns an iterable over the individual bits that are set.
|
||||||
*/
|
*/
|
||||||
enumerate(flags: number): EnumerateFlags<number> {
|
enumerate(flags: number): EnumerateFlags<number>
|
||||||
return useIterator(flags, BitFlagsIterator)
|
enumerate(flags: bigint): EnumerateFlags<bigint>
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class BitFlagSet implements FlagSet<number, number> {
|
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 { FlagDefinition } from './definitions'
|
||||||
export { InvalidBitFlagValueError } from './errors'
|
export { InvalidBitFlagValueError } from './errors'
|
||||||
export {
|
export {
|
||||||
|
|||||||
@@ -1,15 +1,41 @@
|
|||||||
import { BigBitFlagSet } from '~'
|
|
||||||
import { describe, expect, test } from 'vitest'
|
import { describe, expect, test } from 'vitest'
|
||||||
|
|
||||||
|
import { BigBitFlagSet, BitFlags, createBigBitFlagSet } from '~'
|
||||||
|
|
||||||
describe(BigBitFlagSet, () => {
|
describe(BigBitFlagSet, () => {
|
||||||
test('none', () => {
|
test('none', () => {
|
||||||
const flags = new BigBitFlagSet()
|
const flags = createBigBitFlagSet([])
|
||||||
|
|
||||||
expect(flags.none()).toEqual(0n)
|
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', () => {
|
test('union', () => {
|
||||||
const flags = new BigBitFlagSet()
|
const flags = createBigBitFlagSet([])
|
||||||
|
|
||||||
expect(flags.union(0n, 0n)).toEqual(0n)
|
expect(flags.union(0n, 0n)).toEqual(0n)
|
||||||
expect(flags.union(1n, 0n)).toEqual(1n)
|
expect(flags.union(1n, 0n)).toEqual(1n)
|
||||||
@@ -19,7 +45,7 @@ describe(BigBitFlagSet, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('difference', () => {
|
test('difference', () => {
|
||||||
const flags = new BigBitFlagSet()
|
const flags = createBigBitFlagSet([])
|
||||||
|
|
||||||
expect(flags.difference(0n, 0n)).toEqual(0n)
|
expect(flags.difference(0n, 0n)).toEqual(0n)
|
||||||
expect(flags.difference(1n, 0n)).toEqual(1n)
|
expect(flags.difference(1n, 0n)).toEqual(1n)
|
||||||
@@ -29,7 +55,7 @@ describe(BigBitFlagSet, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('intersection', () => {
|
test('intersection', () => {
|
||||||
const flags = new BigBitFlagSet()
|
const flags = createBigBitFlagSet([])
|
||||||
|
|
||||||
expect(flags.intersection(0n, 0n)).toEqual(0n)
|
expect(flags.intersection(0n, 0n)).toEqual(0n)
|
||||||
expect(flags.intersection(1n, 0n)).toEqual(0n)
|
expect(flags.intersection(1n, 0n)).toEqual(0n)
|
||||||
@@ -40,7 +66,7 @@ describe(BigBitFlagSet, () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('isSuperset', () => {
|
test('isSuperset', () => {
|
||||||
const flags = new BigBitFlagSet()
|
const flags = createBigBitFlagSet([])
|
||||||
|
|
||||||
expect(flags.isSuperset(0n, 0n)).toBe(true)
|
expect(flags.isSuperset(0n, 0n)).toBe(true)
|
||||||
expect(flags.isSuperset(3n, 0n)).toBe(true)
|
expect(flags.isSuperset(3n, 0n)).toBe(true)
|
||||||
@@ -50,8 +76,40 @@ describe(BigBitFlagSet, () => {
|
|||||||
expect(flags.isSuperset(8n, 4n)).toBe(false)
|
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', () => {
|
test('enumerate', () => {
|
||||||
const flags = new BigBitFlagSet()
|
const flags = createBigBitFlagSet([])
|
||||||
|
|
||||||
expect([...flags.enumerate(0n)]).toEqual([])
|
expect([...flags.enumerate(0n)]).toEqual([])
|
||||||
expect([...flags.enumerate(1n)]).toEqual([1n])
|
expect([...flags.enumerate(1n)]).toEqual([1n])
|
||||||
@@ -60,4 +118,81 @@ describe(BigBitFlagSet, () => {
|
|||||||
expect([...flags.enumerate(11n)]).toEqual([1n, 2n, 8n])
|
expect([...flags.enumerate(11n)]).toEqual([1n, 2n, 8n])
|
||||||
expect([...flags.enumerate(100n)]).toEqual([4n, 32n, 64n])
|
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