Initial Commit
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
import type {
|
||||
BitPackerSchema,
|
||||
PackingContext,
|
||||
PackingStrategy,
|
||||
} from "@suaveplan/bitpacker";
|
||||
import { BITPACKER_CODES, BitpackerError } from "@suaveplan/bitpacker";
|
||||
|
||||
function bitsRequired(maxValue: number): number {
|
||||
if (maxValue <= 0) return 0;
|
||||
return Math.floor(Math.log2(maxValue)) + 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bitset schema: `{ _bitset: { maxSize: number } }`.
|
||||
*/
|
||||
export class BitsetPackingStrategy implements PackingStrategy {
|
||||
canHandle(schema: BitPackerSchema): boolean {
|
||||
return (
|
||||
typeof schema === "object" && schema !== null && "_bitset" in schema
|
||||
);
|
||||
}
|
||||
|
||||
pack(
|
||||
data: unknown,
|
||||
schema: BitPackerSchema,
|
||||
context: PackingContext
|
||||
): void {
|
||||
const cfg = (schema as { _bitset: { maxSize: number } })._bitset;
|
||||
const set = data as Set<number>;
|
||||
|
||||
if (!(set instanceof Set)) {
|
||||
throw new BitpackerError(
|
||||
BITPACKER_CODES.INVALID_SCHEMA,
|
||||
`Expected Set<number> for bitset schema, got ${typeof data}`,
|
||||
{ context: { data } }
|
||||
);
|
||||
}
|
||||
|
||||
if (set.size > cfg.maxSize) {
|
||||
throw new BitpackerError(
|
||||
BITPACKER_CODES.VALUE_OUT_OF_RANGE,
|
||||
`Bitset size ${set.size} exceeds max ${cfg.maxSize}`,
|
||||
{ context: { size: set.size, maxSize: cfg.maxSize } }
|
||||
);
|
||||
}
|
||||
|
||||
context.writer.writeUint(set.size, bitsRequired(cfg.maxSize));
|
||||
|
||||
for (const index of set) {
|
||||
context.writer.writeUint(index, bitsRequired(cfg.maxSize));
|
||||
}
|
||||
}
|
||||
|
||||
unpack(schema: BitPackerSchema, context: PackingContext): unknown {
|
||||
const cfg = (schema as { _bitset: { maxSize: number } })._bitset;
|
||||
const size = context.reader.readUint(bitsRequired(cfg.maxSize));
|
||||
const result = new Set<number>();
|
||||
|
||||
for (let i = 0; i < size; i++) {
|
||||
result.add(context.reader.readUint(bitsRequired(cfg.maxSize)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user