2020-11-15 07:32:46 +00:00
|
|
|
// Ported from https://github.com/discordjs/discord.js/blob/master/src/util/BitField.js
|
|
|
|
export type BitFieldResolvable = number | BitField | string | BitField[]
|
|
|
|
|
2020-12-03 04:06:41 +00:00
|
|
|
/** Bit Field utility to work with Bits and Flags */
|
2020-11-15 07:32:46 +00:00
|
|
|
export class BitField {
|
|
|
|
flags: { [name: string]: number } = {}
|
2020-11-16 11:37:42 +00:00
|
|
|
bitfield: number
|
2020-11-15 07:32:46 +00:00
|
|
|
|
|
|
|
constructor(flags: { [name: string]: number }, bits: any) {
|
|
|
|
this.flags = flags
|
|
|
|
this.bitfield = BitField.resolve(this.flags, bits)
|
|
|
|
}
|
|
|
|
|
|
|
|
any(bit: BitFieldResolvable): boolean {
|
|
|
|
return (this.bitfield & BitField.resolve(this.flags, bit)) !== 0
|
|
|
|
}
|
|
|
|
|
|
|
|
equals(bit: BitFieldResolvable): boolean {
|
|
|
|
return this.bitfield === BitField.resolve(this.flags, bit)
|
|
|
|
}
|
|
|
|
|
|
|
|
has(bit: BitFieldResolvable, ...args: any[]): boolean {
|
2020-12-02 12:29:52 +00:00
|
|
|
if (Array.isArray(bit)) return bit.every((p) => this.has(p))
|
2020-11-15 07:32:46 +00:00
|
|
|
return (this.bitfield & BitField.resolve(this.flags, bit)) === bit
|
|
|
|
}
|
|
|
|
|
|
|
|
missing(bits: any, ...hasParams: any[]): string[] {
|
2020-12-02 12:29:52 +00:00
|
|
|
if (!Array.isArray(bits))
|
|
|
|
bits = new BitField(this.flags, bits).toArray(false)
|
2020-11-15 07:32:46 +00:00
|
|
|
return bits.filter((p: any) => !this.has(p, ...hasParams))
|
|
|
|
}
|
|
|
|
|
|
|
|
freeze(): Readonly<BitField> {
|
|
|
|
return Object.freeze(this)
|
|
|
|
}
|
|
|
|
|
|
|
|
add(...bits: BitFieldResolvable[]): BitField {
|
|
|
|
let total = 0
|
|
|
|
for (const bit of bits) {
|
|
|
|
total |= BitField.resolve(this.flags, bit)
|
|
|
|
}
|
2020-12-02 12:29:52 +00:00
|
|
|
if (Object.isFrozen(this))
|
|
|
|
return new BitField(this.flags, this.bitfield | total)
|
2020-11-15 07:32:46 +00:00
|
|
|
this.bitfield |= total
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
|
|
|
remove(...bits: BitFieldResolvable[]): BitField {
|
|
|
|
let total = 0
|
|
|
|
for (const bit of bits) {
|
|
|
|
total |= BitField.resolve(this.flags, bit)
|
|
|
|
}
|
2020-12-02 12:29:52 +00:00
|
|
|
if (Object.isFrozen(this))
|
|
|
|
return new BitField(this.flags, this.bitfield & ~total)
|
2020-11-15 07:32:46 +00:00
|
|
|
this.bitfield &= ~total
|
|
|
|
return this
|
|
|
|
}
|
|
|
|
|
|
|
|
serialize(...hasParams: any[]): { [key: string]: any } {
|
|
|
|
const serialized: { [key: string]: any } = {}
|
2020-12-02 12:29:52 +00:00
|
|
|
for (const [flag, bit] of Object.entries(this.flags))
|
|
|
|
serialized[flag] = this.has(
|
|
|
|
BitField.resolve(this.flags, bit),
|
|
|
|
...hasParams
|
|
|
|
)
|
2020-11-15 07:32:46 +00:00
|
|
|
return serialized
|
|
|
|
}
|
|
|
|
|
|
|
|
toArray(...hasParams: any[]): string[] {
|
2020-12-02 12:29:52 +00:00
|
|
|
return Object.keys(this.flags).filter((bit) =>
|
|
|
|
this.has(BitField.resolve(this.flags, bit), ...hasParams)
|
|
|
|
)
|
2020-11-15 07:32:46 +00:00
|
|
|
}
|
|
|
|
|
2020-11-16 11:37:42 +00:00
|
|
|
toJSON(): number {
|
2020-11-15 07:32:46 +00:00
|
|
|
return this.bitfield
|
|
|
|
}
|
|
|
|
|
2020-11-16 11:37:42 +00:00
|
|
|
valueOf(): number {
|
2020-11-15 07:32:46 +00:00
|
|
|
return this.bitfield
|
|
|
|
}
|
|
|
|
|
2020-11-16 11:37:42 +00:00
|
|
|
*[Symbol.iterator](): Iterator<string> {
|
2020-11-15 07:32:46 +00:00
|
|
|
yield* this.toArray()
|
|
|
|
}
|
|
|
|
|
|
|
|
static resolve(flags: any, bit: BitFieldResolvable = 0): number {
|
|
|
|
if (typeof bit === 'string' && !isNaN(parseInt(bit))) return parseInt(bit)
|
|
|
|
if (typeof bit === 'number' && bit >= 0) return bit
|
|
|
|
if (bit instanceof BitField) return this.resolve(flags, bit.bitfield)
|
2020-12-02 12:29:52 +00:00
|
|
|
if (Array.isArray(bit))
|
|
|
|
return bit
|
|
|
|
.map((p) => this.resolve(flags, p))
|
|
|
|
.reduce((prev, p) => prev | p, 0)
|
|
|
|
if (typeof bit === 'string' && typeof flags[bit] !== 'undefined')
|
|
|
|
return flags[bit]
|
2020-11-15 07:32:46 +00:00
|
|
|
const error = new RangeError('BITFIELD_INVALID')
|
|
|
|
throw error
|
|
|
|
}
|
2020-12-02 12:29:52 +00:00
|
|
|
}
|