copied set implementations from MultiFlag JS
This commit is contained in:
130
node/src/flagsets/base64.ts
Normal file
130
node/src/flagsets/base64.ts
Normal file
@@ -0,0 +1,130 @@
|
||||
import type { FlagSet } from '.'
|
||||
import {
|
||||
decodeB64Byte,
|
||||
encodeB64Byte,
|
||||
normaliseB64String,
|
||||
ZERO_STRING,
|
||||
} from '../base64'
|
||||
import {
|
||||
Base64BitflagIterator,
|
||||
EnumerateFlags,
|
||||
useIterator,
|
||||
} from '../enumeration'
|
||||
|
||||
/**
|
||||
* Provides flags that are stored in strings using a little-endian base 64
|
||||
* representation.
|
||||
*
|
||||
* This format is compact, easily serializable and allows for an unlimited
|
||||
* number of flags, but it is specific to Tatsuki. Use {@link CollectionFlagSet}
|
||||
* instead if you need the data to be easily understandable by other systems.
|
||||
*/
|
||||
export class Base64BitFlagSet implements FlagSet<number, string> {
|
||||
/*protected wrapValue(value: number): string {
|
||||
if (value < 1) {
|
||||
throw new RangeError(
|
||||
'Indices should be greater than or equal to 1.'
|
||||
)
|
||||
}
|
||||
const indexFromZero = value - 1
|
||||
const leadingBytes = ZERO_STRING.repeat(indexFromZero / 6)
|
||||
const bigEnd = encodeByte(1 << indexFromZero % 6)
|
||||
return leadingBytes + bigEnd
|
||||
}*/
|
||||
|
||||
public none(): string {
|
||||
return ''
|
||||
}
|
||||
|
||||
public union(first: string, second: string): string {
|
||||
let result = ''
|
||||
|
||||
let shorter, longer
|
||||
if (first.length < second.length) {
|
||||
shorter = first
|
||||
longer = second
|
||||
} else {
|
||||
shorter = second
|
||||
longer = first
|
||||
}
|
||||
|
||||
let i = 0
|
||||
// OR the bytes one by one
|
||||
for (; i < shorter.length; i++) {
|
||||
const value = decodeB64Byte(shorter[i]) | decodeB64Byte(longer[i])
|
||||
result += encodeB64Byte(value)
|
||||
}
|
||||
// if one string is longer than the other, append the remaining bytes (x | 0 = x)
|
||||
for (; i < longer.length; i++) {
|
||||
result += longer[i]
|
||||
}
|
||||
|
||||
return normaliseB64String(result)
|
||||
}
|
||||
|
||||
public intersection(first: string, second: string): string {
|
||||
let result = ''
|
||||
|
||||
const shorterLength = Math.min(first.length, second.length)
|
||||
let i = 0
|
||||
// AND the bytes one by one
|
||||
for (; i < shorterLength; i++) {
|
||||
const value = decodeB64Byte(first[i]) & decodeB64Byte(second[i])
|
||||
result += encodeB64Byte(value)
|
||||
}
|
||||
// if one string is longer than the other, don't add anything else (x & 0 = 0)
|
||||
|
||||
return normaliseB64String(result)
|
||||
}
|
||||
|
||||
public difference(first: string, second: string): string {
|
||||
let result = ''
|
||||
|
||||
const shorterLength = Math.min(first.length, second.length)
|
||||
let i = 0
|
||||
// AND the bytes one by one
|
||||
for (; i < shorterLength; i++) {
|
||||
const value = decodeB64Byte(first[i]) & ~decodeB64Byte(second[i])
|
||||
result += encodeB64Byte(value)
|
||||
}
|
||||
// if the first string is longer than the other, append its remaining bytes (x & ~0 = x)
|
||||
// if the second string is longer, don't add anything (0 & ~y = 0)
|
||||
for (; i < first.length; i++) {
|
||||
result += first[i]
|
||||
}
|
||||
|
||||
return normaliseB64String(result)
|
||||
}
|
||||
|
||||
public isSuperset(first: string, second: string): boolean {
|
||||
let result = true
|
||||
|
||||
const shorterLength = Math.min(first.length, second.length)
|
||||
let i = 0
|
||||
// AND the bytes one by one and check
|
||||
// if one is false we don't need to decode further
|
||||
for (; i < shorterLength && result; i++) {
|
||||
const secondValue = decodeB64Byte(second[i])
|
||||
result = (decodeB64Byte(first[i]) & secondValue) == secondValue
|
||||
}
|
||||
// if there are more characters in the second string, they must all be zeros
|
||||
// (0 & x is only equal to x when x is also 0)
|
||||
for (; i < second.length && result; i++) {
|
||||
result = second[i] == ZERO_STRING
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
public enumerate(flags: string): EnumerateFlags<number> {
|
||||
return useIterator(flags, Base64BitflagIterator)
|
||||
}
|
||||
|
||||
maximum(flags: string): string {
|
||||
throw new Error('not implemented')
|
||||
}
|
||||
|
||||
minimum(flags: string): string {
|
||||
throw new Error('not implemented')
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user