@hkdigital/lib-core 0.4.56 → 0.4.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,267 @@
1
+ # CRC32 Checksum Utilities
2
+
3
+ Fast, modular CRC32 implementation with support for strings, buffers, and
4
+ large file processing.
5
+
6
+ ## Features
7
+
8
+ - **Standard CRC32**: IEEE 802.3 compatible (ZIP, PNG, Ethernet)
9
+ - **CRC32C variant**: Castagnoli polynomial for improved performance
10
+ - **Buffer support**: ArrayBuffer, DataView, Uint8Array
11
+ - **Block processing**: Custom format for large files
12
+ - **Zero dependencies**: Pure JavaScript implementation
13
+ - **TypeScript ready**: Full JSDoc type annotations
14
+
15
+ ## Quick Start
16
+
17
+ ```javascript
18
+ import { stringToCrc32 } from './stringCrc32.js';
19
+ import { bufferToCrc32 } from './bufferCrc32.js';
20
+ import { bufferToBlockCrc32 } from './blockCrc32.js';
21
+ import { CRC32, CRC32C } from './crcTables.js';
22
+
23
+ // String checksums (IEEE 802.3 standard)
24
+ const crc = stringToCrc32('hello world');
25
+ console.log(crc); // 222957957 (0xd4a1185)
26
+
27
+ // Standard test vector verification
28
+ console.log(stringToCrc32('123456789')); // 3421780262 (0xcbf43926)
29
+ console.log(stringToCrc32('123456789', CRC32C)); // 3808858755 (0xe3069283)
30
+
31
+ // Buffer checksums (standard)
32
+ const buffer = new TextEncoder().encode('hello world');
33
+ const bufferCrc = bufferToCrc32(buffer);
34
+ console.log(bufferCrc); // 222957957 (same as string)
35
+
36
+ // Large file processing (custom format)
37
+ const result = bufferToBlockCrc32(buffer, 1024);
38
+ console.log(result.checksumList); // [222957957]
39
+ console.log(result.toBase58()); // Base58-encoded result
40
+ ```
41
+
42
+ ## Module Overview
43
+
44
+ ### `crcTables.js`
45
+ Shared CRC table generation and constants.
46
+
47
+ ```javascript
48
+ import { getCrcTable, CRC32, CRC32C } from './crcTables.js';
49
+
50
+ const table = getCrcTable(CRC32); // Get lookup table
51
+ ```
52
+
53
+ ### `stringCrc32.js`
54
+ String to CRC32 conversion.
55
+
56
+ ```javascript
57
+ import { stringToCrc32, CRC32, CRC32C } from './stringCrc32.js';
58
+
59
+ const crc = stringToCrc32('text', CRC32); // Standard CRC32
60
+ const crcC = stringToCrc32('text', CRC32C); // CRC32C variant
61
+ ```
62
+
63
+ ### `bufferCrc32.js`
64
+ Standard buffer CRC32 - compatible with external tools.
65
+
66
+ ```javascript
67
+ import { bufferToCrc32 } from './bufferCrc32.js';
68
+
69
+ // Works with all buffer types
70
+ const arrayBuffer = new ArrayBuffer(100);
71
+ const uint8Array = new Uint8Array(100);
72
+ const dataView = new DataView(arrayBuffer);
73
+
74
+ const crc1 = bufferToCrc32(arrayBuffer);
75
+ const crc2 = bufferToCrc32(uint8Array, 10, 50); // Offset & length
76
+ const crc3 = bufferToCrc32(dataView);
77
+ ```
78
+
79
+ ### `blockCrc32.js`
80
+ Custom block-based processing for large files.
81
+
82
+ ```javascript
83
+ import {
84
+ bufferToBlockCrc32,
85
+ blockCrc32Iterator,
86
+ bufferChecksumEquals,
87
+ optimalBlockSize
88
+ } from './blockCrc32.js';
89
+
90
+ // Process large buffer in blocks
91
+ const result = bufferToBlockCrc32(largeBuffer);
92
+ console.log(result.checksumList); // Array of CRC32 values
93
+ console.log(result.toBase58()); // Concatenated Base58 string
94
+
95
+ // Stream processing
96
+ for (const block of blockCrc32Iterator(buffer, 1024)) {
97
+ console.log(`Block at ${block.offset}: ${block.toBase58()}`);
98
+ }
99
+
100
+ // Verification
101
+ const isValid = bufferChecksumEquals(buffer, expectedChecksum);
102
+ ```
103
+
104
+ ## CRC32 Variants
105
+
106
+ ### CRC32 (IEEE 802.3)
107
+ - **Use case**: General purpose, file integrity
108
+ - **Compatible with**: ZIP files, PNG images, Ethernet frames
109
+ - **Polynomial**: `0xEDB88320` (reversed)
110
+ - **Standard test**: `"123456789"` → `0xcbf43926` ✅
111
+
112
+ ### CRC32C (Castagnoli)
113
+ - **Use case**: High-performance applications
114
+ - **Compatible with**: iSCSI, SCTP, certain databases
115
+ - **Polynomial**: `0x82f63b78` (reversed)
116
+ - **Standard test**: `"123456789"` → `0xe3069283` ✅
117
+
118
+ ```javascript
119
+ import { CRC32, CRC32C } from './crcTables.js';
120
+
121
+ // All functions accept variant parameter
122
+ stringToCrc32('data', CRC32); // Default
123
+ stringToCrc32('data', CRC32C); // Castagnoli
124
+
125
+ // Verify against standard test vectors
126
+ console.assert(stringToCrc32('123456789', CRC32) === 0xcbf43926);
127
+ console.assert(stringToCrc32('123456789', CRC32C) === 0xe3069283);
128
+ ```
129
+
130
+ ## Block Processing Details
131
+
132
+ ### Standard vs Block Format
133
+
134
+ **Standard CRC32** (compatible):
135
+ ```
136
+ Input: [large file data]
137
+ Output: 222957957 (single 32-bit value)
138
+ ```
139
+
140
+ **Block CRC32** (proprietary):
141
+ ```
142
+ Input: [large file data split into blocks]
143
+ Block 1: 222957957 → Base58 encoded
144
+ Block 2: 891347246 → Base58 encoded
145
+ Block 3: 234567890 → Base58 encoded
146
+ Output: [concatenated Base58 string]
147
+ ```
148
+
149
+ ### Block Size Selection
150
+
151
+ ```javascript
152
+ // Automatic sizing
153
+ const blockSize = optimalBlockSize(buffer);
154
+
155
+ // Manual sizing
156
+ const result = bufferToBlockCrc32(buffer, 65536); // 64KB blocks
157
+ ```
158
+
159
+ **Size Guidelines:**
160
+ - **Small files** (< 100KB): Single block
161
+ - **Medium files** (100KB - 2MB): 100KB blocks
162
+ - **Large files** (> 2MB): Adaptive sizing (max 20 blocks)
163
+
164
+ ### Use Cases
165
+
166
+ **Standard CRC32:**
167
+ - File integrity verification
168
+ - Compatibility with external tools
169
+ - Single checksum for entire data
170
+
171
+ **Block CRC32:**
172
+ - Large file streaming
173
+ - Partial corruption detection
174
+ - Progress tracking during transfer
175
+ - Resume capability for interrupted uploads
176
+
177
+ ## Error Handling
178
+
179
+ ```javascript
180
+ // Invalid CRC variant
181
+ getCrcTable('invalid'); // throws "Invalid variant [invalid]"
182
+
183
+ // Unsupported buffer type
184
+ bufferToCrc32('string'); // throws "Unsupported buffer type"
185
+
186
+ // All functions validate inputs and provide clear error messages
187
+ ```
188
+
189
+ ## Standards Compliance
190
+
191
+ ✅ **Verified Implementation**: Both CRC32 and CRC32C pass standard test vectors
192
+ - CRC32 IEEE 802.3: `"123456789"` → `0xcbf43926`
193
+ - CRC32C Castagnoli: `"123456789"` → `0xe3069283`
194
+
195
+ ✅ **Full Compatibility**:
196
+ - ZIP/PNG/Ethernet frames (CRC32)
197
+ - iSCSI/SCTP protocols (CRC32C)
198
+
199
+ ## Performance Notes
200
+
201
+ - **Table caching**: CRC tables generated once per variant
202
+ - **Memory efficient**: Block processing doesn't load entire files
203
+ - **Browser compatible**: Works in all modern browsers
204
+ - **Standards compliant**: Verified against authoritative test vectors
205
+ - **No dependencies**: Pure JavaScript implementation
206
+
207
+ ## Testing
208
+
209
+ Run tests for all modules:
210
+
211
+ ```bash
212
+ pnpm test:file src/lib/util/checksum/
213
+ ```
214
+
215
+ Run specific test files:
216
+
217
+ ```bash
218
+ pnpm test:file src/lib/util/checksum/stringCrc32.test.js
219
+ pnpm test:file src/lib/util/checksum/bufferCrc32.test.js
220
+ pnpm test:file src/lib/util/checksum/blockCrc32.test.js
221
+ ```
222
+
223
+ ## TypeScript Support
224
+
225
+ All modules include comprehensive JSDoc type annotations:
226
+
227
+ ```javascript
228
+ /**
229
+ * @param {string} str - String to calculate checksum for
230
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
231
+ * @returns {number} Unsigned 32-bit CRC32 value
232
+ */
233
+ ```
234
+
235
+ ## Migration Guide
236
+
237
+ ### From Original Implementation
238
+
239
+ **Old:**
240
+ ```javascript
241
+ import { stringToCrc32 } from './crc32.js';
242
+ ```
243
+
244
+ **New:**
245
+ ```javascript
246
+ import { stringToCrc32 } from './stringCrc32.js';
247
+ // Same API, no changes needed
248
+ ```
249
+
250
+ ### Adding Block Processing
251
+
252
+ **Before:**
253
+ ```javascript
254
+ // Single CRC32 for entire file
255
+ const crc = bufferToCrc32(largeFile);
256
+ ```
257
+
258
+ **After:**
259
+ ```javascript
260
+ // Block-based processing
261
+ const result = bufferToBlockCrc32(largeFile);
262
+ const checksum = result.toBase58(); // Custom format
263
+ ```
264
+
265
+ ## License
266
+
267
+ Part of HKdigital library core utilities.
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Calculate block-based CRC32 for buffer
3
+ *
4
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to process
5
+ * @param {number} [blockSize] - Block size (auto-calculated if not provided)
6
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
7
+ *
8
+ * @returns {object} Block checksum result
9
+ */
10
+ export function bufferToBlockCrc32(buffer: ArrayBuffer | DataView | Uint8Array, blockSize?: number, variant?: import("./crcTables.js").CrcVariant): object;
11
+ /**
12
+ * Iterate over buffer blocks and yield CRC32 for each
13
+ *
14
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to process
15
+ * @param {number} [blockSize] - Block size
16
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
17
+ *
18
+ * @yields {object} Block checksum with value and encoding methods
19
+ */
20
+ export function blockCrc32Iterator(buffer: ArrayBuffer | DataView | Uint8Array, blockSize?: number, variant?: import("./crcTables.js").CrcVariant): Generator<{
21
+ value: number;
22
+ offset: number;
23
+ size: number;
24
+ toBase58: () => string;
25
+ }, void, unknown>;
26
+ /**
27
+ * Check if buffer checksum matches expected value
28
+ *
29
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to verify
30
+ * @param {string} expectedChecksum - Expected Base58 checksum string
31
+ * @param {number} [blockSize] - Block size
32
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
33
+ *
34
+ * @returns {boolean} True if checksums match
35
+ */
36
+ export function bufferChecksumEquals(buffer: ArrayBuffer | DataView | Uint8Array, expectedChecksum: string, blockSize?: number, variant?: import("./crcTables.js").CrcVariant): boolean;
37
+ /**
38
+ * Calculate optimal block size for buffer
39
+ *
40
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to analyze
41
+ *
42
+ * @returns {number} Optimal block size
43
+ */
44
+ export function optimalBlockSize(buffer: ArrayBuffer | DataView | Uint8Array): number;
@@ -0,0 +1,174 @@
1
+ /**
2
+ * Custom block-based CRC32 calculation
3
+ *
4
+ * Splits large buffers into blocks and concatenates individual CRC32 values.
5
+ * Creates proprietary checksum format for efficient large file processing.
6
+ */
7
+
8
+ import { base58fromNumber } from '../bases.js';
9
+
10
+ import { bufferToCrc32 } from './bufferCrc32.js';
11
+ import { CRC32 } from './crcTables.js';
12
+
13
+ /* ---------------------------------------------------------------- Constants */
14
+
15
+ /** @type {number} */
16
+ const MIN_BUFFER_BLOCK_SIZE = 100000;
17
+
18
+ /** @type {number} */
19
+ const MAX_BUFFER_BLOCKS = 20;
20
+
21
+ /** @type {number} */
22
+ const OPTIMAL_BLOCK_SIZE_FACTOR = 0.95;
23
+
24
+ /* ---------------------------------------------------------------- Functions */
25
+
26
+ /**
27
+ * Calculate block-based CRC32 for buffer
28
+ *
29
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to process
30
+ * @param {number} [blockSize] - Block size (auto-calculated if not provided)
31
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
32
+ *
33
+ * @returns {object} Block checksum result
34
+ */
35
+ export function bufferToBlockCrc32(buffer, blockSize, variant = CRC32) {
36
+ if (!blockSize) {
37
+ blockSize = optimalBlockSize(buffer);
38
+ }
39
+
40
+ /** @type {number[]} */
41
+ const checksumList = [];
42
+
43
+ for (const block of blockCrc32Iterator(buffer, blockSize, variant)) {
44
+ checksumList.push(block.value);
45
+ }
46
+
47
+ return {
48
+ checksumList,
49
+ blockSize,
50
+ toBase58: () => checksumsToBase58(checksumList)
51
+ };
52
+ }
53
+
54
+ /**
55
+ * Iterate over buffer blocks and yield CRC32 for each
56
+ *
57
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to process
58
+ * @param {number} [blockSize] - Block size
59
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
60
+ *
61
+ * @yields {object} Block checksum with value and encoding methods
62
+ */
63
+ export function* blockCrc32Iterator(buffer, blockSize, variant = CRC32) {
64
+ if (!blockSize) {
65
+ blockSize = optimalBlockSize(buffer);
66
+ }
67
+
68
+ const bufferLength = getBufferLength(buffer);
69
+
70
+ for (let offset = 0; offset < bufferLength; offset += blockSize) {
71
+ const currentBlockSize = Math.min(blockSize, bufferLength - offset);
72
+
73
+ /** @type {number} */
74
+ const value = bufferToCrc32(buffer, offset, currentBlockSize, variant);
75
+
76
+ yield {
77
+ value,
78
+ offset,
79
+ size: currentBlockSize,
80
+ toBase58: () => base58fromNumber(value)
81
+ };
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Check if buffer checksum matches expected value
87
+ *
88
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to verify
89
+ * @param {string} expectedChecksum - Expected Base58 checksum string
90
+ * @param {number} [blockSize] - Block size
91
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
92
+ *
93
+ * @returns {boolean} True if checksums match
94
+ */
95
+ export function bufferChecksumEquals(
96
+ buffer,
97
+ expectedChecksum,
98
+ blockSize,
99
+ variant = CRC32
100
+ ) {
101
+ if (!blockSize) {
102
+ blockSize = optimalBlockSize(buffer);
103
+ }
104
+
105
+ /** @type {string} */
106
+ let remaining = expectedChecksum;
107
+
108
+ for (const block of blockCrc32Iterator(buffer, blockSize, variant)) {
109
+ const blockChecksum = block.toBase58();
110
+
111
+ if (!remaining.startsWith(blockChecksum)) {
112
+ return false;
113
+ }
114
+
115
+ remaining = remaining.slice(blockChecksum.length);
116
+ }
117
+
118
+ return remaining.length === 0;
119
+ }
120
+
121
+ /**
122
+ * Calculate optimal block size for buffer
123
+ *
124
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to analyze
125
+ *
126
+ * @returns {number} Optimal block size
127
+ */
128
+ export function optimalBlockSize(buffer) {
129
+ /** @type {number} */
130
+ const bufferByteLength = getBufferLength(buffer);
131
+
132
+ if (bufferByteLength < MIN_BUFFER_BLOCK_SIZE) {
133
+ return bufferByteLength;
134
+ }
135
+
136
+ /** @type {number} */
137
+ let blockSize = bufferByteLength / MAX_BUFFER_BLOCKS;
138
+
139
+ if (blockSize < MIN_BUFFER_BLOCK_SIZE) {
140
+ return MIN_BUFFER_BLOCK_SIZE;
141
+ }
142
+
143
+ return Math.ceil(
144
+ blockSize * OPTIMAL_BLOCK_SIZE_FACTOR +
145
+ MIN_BUFFER_BLOCK_SIZE * (1 - OPTIMAL_BLOCK_SIZE_FACTOR)
146
+ );
147
+ }
148
+
149
+ /* ------------------------------------------------------- Internal functions */
150
+
151
+ /**
152
+ * Get buffer length safely for different buffer types
153
+ *
154
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to measure
155
+ *
156
+ * @returns {number} Buffer length in bytes
157
+ */
158
+ function getBufferLength(buffer) {
159
+ if (buffer instanceof ArrayBuffer || buffer instanceof DataView) {
160
+ return buffer.byteLength;
161
+ }
162
+ return buffer.length;
163
+ }
164
+
165
+ /**
166
+ * Convert checksum array to concatenated Base58 string
167
+ *
168
+ * @param {number[]} checksumList - Array of CRC32 values
169
+ *
170
+ * @returns {string} Concatenated Base58 string
171
+ */
172
+ function checksumsToBase58(checksumList) {
173
+ return checksumList.map(crc => base58fromNumber(crc)).join('');
174
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Calculate standard CRC32 for buffer
3
+ *
4
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to checksum
5
+ * @param {number} [byteOffset=0] - Start offset in buffer
6
+ * @param {number} [byteLength] - Number of bytes to process
7
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
8
+ *
9
+ * @returns {number} Unsigned 32-bit CRC32 value
10
+ */
11
+ export function bufferToCrc32(buffer: ArrayBuffer | DataView | Uint8Array, byteOffset?: number, byteLength?: number, variant?: import("./crcTables.js").CrcVariant): number;
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Standard buffer CRC32 calculation
3
+ *
4
+ * Implements IEEE 802.3 CRC32 over entire buffer.
5
+ * Compatible with ZIP, PNG, and other standard formats.
6
+ */
7
+
8
+ import { getCrcTable, CRC32 } from './crcTables.js';
9
+
10
+ /**
11
+ * Calculate standard CRC32 for buffer
12
+ *
13
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Buffer to checksum
14
+ * @param {number} [byteOffset=0] - Start offset in buffer
15
+ * @param {number} [byteLength] - Number of bytes to process
16
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
17
+ *
18
+ * @returns {number} Unsigned 32-bit CRC32 value
19
+ */
20
+ export function bufferToCrc32(buffer, byteOffset = 0, byteLength, variant = CRC32) {
21
+ const table = getCrcTable(variant);
22
+
23
+ /** @type {DataView} */
24
+ const dataView = createDataView(buffer, byteOffset, byteLength);
25
+
26
+ /** @type {number} */
27
+ let crc = 0 ^ (-1);
28
+
29
+ for (let j = 0; j < dataView.byteLength; j = j + 1) {
30
+ crc = (crc >>> 8) ^ table[(crc ^ dataView.getUint8(j)) & 0xFF];
31
+ }
32
+
33
+ return (crc ^ (-1)) >>> 0;
34
+ }
35
+
36
+ /* ------------------------------------------------------- Internal functions */
37
+
38
+ /**
39
+ * Create DataView from various buffer types
40
+ *
41
+ * @param {ArrayBuffer|DataView|Uint8Array} buffer - Input buffer
42
+ * @param {number} [byteOffset=0] - Start offset
43
+ * @param {number} [byteLength] - Length to use
44
+ *
45
+ * @returns {DataView} DataView for the buffer
46
+ */
47
+ function createDataView(buffer, byteOffset = 0, byteLength) {
48
+ if (buffer instanceof DataView) {
49
+ return new DataView(
50
+ buffer.buffer,
51
+ buffer.byteOffset + byteOffset,
52
+ byteLength ?? (buffer.byteLength - byteOffset)
53
+ );
54
+ }
55
+
56
+ if (buffer instanceof ArrayBuffer) {
57
+ return new DataView(buffer, byteOffset, byteLength);
58
+ }
59
+
60
+ if (buffer instanceof Uint8Array) {
61
+ return new DataView(
62
+ buffer.buffer,
63
+ buffer.byteOffset + byteOffset,
64
+ byteLength ?? (buffer.byteLength - byteOffset)
65
+ );
66
+ }
67
+
68
+ throw new Error('Unsupported buffer type');
69
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Get CRC lookup table for specified variant
3
+ *
4
+ * @param {CrcVariant} [variant=CRC32] - CRC variant
5
+ *
6
+ * @returns {CrcTable} The CRC lookup table
7
+ */
8
+ export function getCrcTable(variant?: CrcVariant): CrcTable;
9
+ /**
10
+ * Shared CRC table generation and constants
11
+ */
12
+ /**
13
+ * @typedef {import('./typedef').CrcVariant} CrcVariant
14
+ * Valid CRC32 variant types
15
+ */
16
+ /**
17
+ * @typedef {import('./typedef').CrcTable} CrcTable
18
+ * Lookup table for CRC calculations - array of 256 numbers
19
+ */
20
+ /** @type {CrcVariant} */
21
+ export const CRC32: CrcVariant;
22
+ /** @type {CrcVariant} */
23
+ export const CRC32C: CrcVariant;
24
+ /**
25
+ * Valid CRC32 variant types
26
+ */
27
+ export type CrcVariant = import("./typedef").CrcVariant;
28
+ /**
29
+ * Lookup table for CRC calculations - array of 256 numbers
30
+ */
31
+ export type CrcTable = import("./typedef").CrcTable;
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Shared CRC table generation and constants
3
+ */
4
+
5
+ /**
6
+ * @typedef {import('./typedef').CrcVariant} CrcVariant
7
+ * Valid CRC32 variant types
8
+ */
9
+
10
+ /**
11
+ * @typedef {import('./typedef').CrcTable} CrcTable
12
+ * Lookup table for CRC calculations - array of 256 numbers
13
+ */
14
+
15
+ /* ---------------------------------------------------------------- Constants */
16
+
17
+ /** @type {CrcVariant} */
18
+ export const CRC32 = 'crc32';
19
+
20
+ /** @type {CrcVariant} */
21
+ export const CRC32C = 'crc32c';
22
+
23
+ /** @type {Record<CrcVariant, number>} */
24
+ const START_POLYNOMIALS = {
25
+ [CRC32]: 0xEDB88320,
26
+ [CRC32C]: 0x82f63b78
27
+ };
28
+
29
+ /** @type {Record<CrcVariant, CrcTable>} */
30
+ // @ts-ignore
31
+ const crcTables = {};
32
+
33
+ /* ---------------------------------------------------------------- Functions */
34
+
35
+ /**
36
+ * Get CRC lookup table for specified variant
37
+ *
38
+ * @param {CrcVariant} [variant=CRC32] - CRC variant
39
+ *
40
+ * @returns {CrcTable} The CRC lookup table
41
+ */
42
+ export function getCrcTable(variant = CRC32) {
43
+ return crcTables[variant] || (crcTables[variant] = makeCRCTable(variant));
44
+ }
45
+
46
+ /* ---------------------------------------------------------------- Internals */
47
+
48
+ /**
49
+ * Create CRC lookup table for specified variant
50
+ *
51
+ * @param {CrcVariant} variant - CRC variant to create table for
52
+ *
53
+ * @returns {CrcTable} The generated CRC lookup table
54
+ */
55
+ function makeCRCTable(variant) {
56
+ /** @type {number} */
57
+ let c;
58
+
59
+ /** @type {CrcTable} */
60
+ const crcTable = [];
61
+
62
+ /** @type {number} */
63
+ const startPolynomial = START_POLYNOMIALS[variant];
64
+
65
+ if (!startPolynomial) {
66
+ throw new Error(`Invalid variant [${variant}]`);
67
+ }
68
+
69
+ for (let n = 0; n < 256; n = n + 1) {
70
+ c = n;
71
+
72
+ for (let k = 0; k < 8; k = k + 1) {
73
+ c = ((c & 1) ? (startPolynomial ^ (c >>> 1)) : (c >>> 1));
74
+ }
75
+ crcTable[n] = c;
76
+ }
77
+
78
+ return crcTable;
79
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Calculate CRC32 hash for string input
3
+ *
4
+ * @param {string} str - String to calculate checksum for
5
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
6
+ *
7
+ * @returns {number} Unsigned 32-bit CRC32 value
8
+ */
9
+ export function stringToCrc32(str: string, variant?: import("./crcTables.js").CrcVariant): number;
10
+ import { CRC32 } from './crcTables.js';
11
+ import { CRC32C } from './crcTables.js';
12
+ export { CRC32, CRC32C };
@@ -0,0 +1,33 @@
1
+ /**
2
+ * String CRC32 calculation utility
3
+ *
4
+ * Calculates CRC32 checksums for strings using standard IEEE 802.3 algorithm.
5
+ * CRC32 is fast but not cryptographically secure.
6
+ */
7
+
8
+ import { getCrcTable, CRC32, CRC32C } from './crcTables.js';
9
+
10
+ /* ------------------------------------------------------------------ Exports */
11
+
12
+ export { CRC32, CRC32C };
13
+
14
+ /**
15
+ * Calculate CRC32 hash for string input
16
+ *
17
+ * @param {string} str - String to calculate checksum for
18
+ * @param {import('./crcTables.js').CrcVariant} [variant=CRC32] - CRC variant
19
+ *
20
+ * @returns {number} Unsigned 32-bit CRC32 value
21
+ */
22
+ export function stringToCrc32(str, variant = CRC32) {
23
+ const table = getCrcTable(variant);
24
+
25
+ /** @type {number} */
26
+ let crc = 0 ^ (-1);
27
+
28
+ for (let j = 0; j < str.length; j = j + 1) {
29
+ crc = (crc >>> 8) ^ table[(crc ^ str.charCodeAt(j)) & 0xFF];
30
+ }
31
+
32
+ return (crc ^ (-1)) >>> 0;
33
+ }
@@ -0,0 +1,10 @@
1
+ declare const _default: {};
2
+ export default _default;
3
+ /**
4
+ * Valid CRC32 variant types
5
+ */
6
+ export type CrcVariant = "crc32" | "crc32c";
7
+ /**
8
+ * Lookup table for CRC calculations - array of 256 numbers
9
+ */
10
+ export type CrcTable = number[];
@@ -0,0 +1,11 @@
1
+ /**
2
+ * @typedef {'crc32'|'crc32c'} CrcVariant
3
+ * Valid CRC32 variant types
4
+ */
5
+
6
+ /**
7
+ * @typedef {number[]} CrcTable
8
+ * Lookup table for CRC calculations - array of 256 numbers
9
+ */
10
+
11
+ export default {};
@@ -0,0 +1,4 @@
1
+ export { bufferToCrc32 } from "./checksum/bufferCrc32.js";
2
+ export { getCrcTable } from "./checksum/crcTables.js";
3
+ export { stringToCrc32, CRC32, CRC32C } from "./checksum/stringCrc32.js";
4
+ export { bufferToBlockCrc32, blockCrc32Iterator, bufferChecksumEquals, optimalBlockSize } from "./checksum/blockCrc32.js";
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Checksum utilities - CRC32 calculations
3
+ *
4
+ * Exports the main public-facing functions from the checksum module.
5
+ * Provides both standard IEEE 802.3 CRC32 and custom block-based processing.
6
+ */
7
+
8
+ // String CRC32 calculations
9
+ export { stringToCrc32, CRC32, CRC32C } from './checksum/stringCrc32.js';
10
+
11
+ // Standard buffer CRC32 (IEEE 802.3 compatible)
12
+ export { bufferToCrc32 } from './checksum/bufferCrc32.js';
13
+
14
+ // Custom block-based CRC32 for large files
15
+ export {
16
+ bufferToBlockCrc32,
17
+ blockCrc32Iterator,
18
+ bufferChecksumEquals,
19
+ optimalBlockSize
20
+ } from './checksum/blockCrc32.js';
21
+
22
+ // CRC table utilities (for advanced use)
23
+ export { getCrcTable } from './checksum/crcTables.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hkdigital/lib-core",
3
- "version": "0.4.56",
3
+ "version": "0.4.57",
4
4
  "author": {
5
5
  "name": "HKdigital",
6
6
  "url": "https://hkdigital.nl"