Update compression file

This commit is contained in:
Eric Bailey
2025-06-20 11:50:55 -05:00
parent 6fcae251fe
commit 6c689a3c7c
+38 -9
View File
@@ -1,26 +1,55 @@
/*
* This module provides functions to pack and unpack flags into a compact
* binary format for storage in our NUX system. Given the max length of 300
* characters, and a 6-bit encoding scheme, we can store up to 1800 flags in a
* single string.
*/
const TRUTHY = '1'
const FALSY = '0'
/**
* Total number of characters that flags can be packed. This corresponds to the
* max-length of a NUX.
*/
const MAX_FLAGS = 300
const FLAGS_PER_CHAR = 6
/**
* Length of binary string chunks used to encode flags.
*/
const CHAR_CODE_LENGTH = 6
export function pack(flags: Record<string, boolean>) {
const values = Object.values(flags)
if (values.length > MAX_FLAGS) {
throw new Error(`Too many flags. Maximum supported is ${MAX_FLAGS}`)
}
const compacted = values.map(value => value ? '1' : '0').join('')
// split into chunks of 6 values
const encoded = (compacted.match(/.{1,6}/g) || [])
.map(chunk => String.fromCharCode(parseInt(chunk.padEnd(6, '0'), 2)))
/*
* Splits `compactBinaryNotation` string into 6 char chunks of 0s and 1s.
*/
const compactBinaryNotation = values
.map(value => (value ? TRUTHY : FALSY))
.join('')
const matcher = new RegExp(`.{1,${CHAR_CODE_LENGTH}}`, 'g')
const encoded = (compactBinaryNotation.match(matcher) || [])
.map(chunk =>
String.fromCharCode(parseInt(chunk.padEnd(CHAR_CODE_LENGTH, '0'), 2)),
)
.join('')
return encoded
}
export function unpack<K extends string>(encoded: string, keys: K[]) {
const binary = encoded.split('')
.map(char => char.charCodeAt(0).toString(2).padEnd(6, '0'))
const compactBinaryNotation = encoded
.split('')
.map(char => char.charCodeAt(0).toString(2).padEnd(CHAR_CODE_LENGTH, '0'))
.join('')
return keys.reduce((obj, key, i) => {
obj[key] = binary[i] === '1'
obj[key] = compactBinaryNotation[i] === TRUTHY
return obj
}, {} as Record<K, boolean>)
}