89 lines
2.2 KiB
TypeScript
89 lines
2.2 KiB
TypeScript
/**
|
|
* CRC32 checksum utilities for data integrity
|
|
*/
|
|
|
|
// CRC32 lookup table
|
|
const CRC32_TABLE: number[] = [];
|
|
|
|
// Initialize the CRC32 table
|
|
function initCRC32Table(): void {
|
|
if (CRC32_TABLE.length > 0) return;
|
|
|
|
for (let i = 0; i < 256; i++) {
|
|
let crc = i;
|
|
for (let j = 0; j < 8; j++) {
|
|
crc = (crc & 1) ? (0xEDB88320 ^ (crc >>> 1)) : (crc >>> 1);
|
|
}
|
|
CRC32_TABLE[i] = crc >>> 0;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate CRC32 checksum for a string
|
|
*/
|
|
export function calculateCRC32(data: string): number {
|
|
initCRC32Table();
|
|
|
|
let crc = 0xFFFFFFFF;
|
|
for (let i = 0; i < data.length; i++) {
|
|
const byte = data.charCodeAt(i) & 0xFF;
|
|
crc = CRC32_TABLE[(crc ^ byte) & 0xFF] ^ (crc >>> 8);
|
|
}
|
|
return (~crc) >>> 0;
|
|
}
|
|
|
|
/**
|
|
* Calculate CRC32 checksum for a Buffer
|
|
*/
|
|
export function calculateCRC32Buffer(data: Buffer): number {
|
|
initCRC32Table();
|
|
|
|
let crc = 0xFFFFFFFF;
|
|
for (let i = 0; i < data.length; i++) {
|
|
crc = CRC32_TABLE[(crc ^ data[i]) & 0xFF] ^ (crc >>> 8);
|
|
}
|
|
return (~crc) >>> 0;
|
|
}
|
|
|
|
/**
|
|
* Calculate checksum for a document (serialized as JSON)
|
|
*/
|
|
export function calculateDocumentChecksum(doc: Record<string, any>): number {
|
|
// Exclude _checksum field from calculation
|
|
const { _checksum, ...docWithoutChecksum } = doc;
|
|
const json = JSON.stringify(docWithoutChecksum);
|
|
return calculateCRC32(json);
|
|
}
|
|
|
|
/**
|
|
* Add checksum to a document
|
|
*/
|
|
export function addChecksum<T extends Record<string, any>>(doc: T): T & { _checksum: number } {
|
|
const checksum = calculateDocumentChecksum(doc);
|
|
return { ...doc, _checksum: checksum };
|
|
}
|
|
|
|
/**
|
|
* Verify checksum of a document
|
|
* Returns true if checksum is valid or if document has no checksum
|
|
*/
|
|
export function verifyChecksum(doc: Record<string, any>): boolean {
|
|
if (!('_checksum' in doc)) {
|
|
// No checksum to verify
|
|
return true;
|
|
}
|
|
|
|
const storedChecksum = doc._checksum;
|
|
const calculatedChecksum = calculateDocumentChecksum(doc);
|
|
|
|
return storedChecksum === calculatedChecksum;
|
|
}
|
|
|
|
/**
|
|
* Remove checksum from a document
|
|
*/
|
|
export function removeChecksum<T extends Record<string, any>>(doc: T): Omit<T, '_checksum'> {
|
|
const { _checksum, ...docWithoutChecksum } = doc;
|
|
return docWithoutChecksum as Omit<T, '_checksum'>;
|
|
}
|