@@ -174,55 +174,68 @@ export async function getMD5FromStream(
174174// Algorithm and lookup-table approach adapted from the Azure Storage JavaScript SDK (MIT License):
175175// https://github.com/Azure/azure-sdk-for-js/blob/main/sdk/storage/storage-blob/src/utils/crc64.ts
176176// Polynomial: 0x42F0E1EBA9EA3693 (ECMA-182 standard, unreflected, init=0, xorout=0)
177- const CRC64_POLY = 0x42f0e1eba9ea3693n ;
177+ // Represented as two 32-bit halves (hi, lo) to avoid BigInt.
178+ const CRC64_POLY_HI = 0x42f0e1eb ;
179+ const CRC64_POLY_LO = 0xa9ea3693 ;
178180
179- const CRC64_TABLE : readonly bigint [ ] = ( ( ) => {
180- const table : bigint [ ] = new Array ( 256 ) ;
181+ // Flat table: entry i occupies [i*2] (hi) and [i*2+1] (lo).
182+ const CRC64_TABLE : readonly number [ ] = ( ( ) => {
183+ const table : number [ ] = new Array ( 512 ) ;
181184 for ( let i = 0 ; i < 256 ; i ++ ) {
182- let crc = BigInt ( i ) << 56n ;
185+ let hi = ( i << 24 ) >>> 0 ;
186+ let lo = 0 ;
183187 for ( let j = 0 ; j < 8 ; j ++ ) {
184- if ( ( crc & 0x8000000000000000n ) !== 0n ) {
185- crc = ( ( crc << 1n ) ^ CRC64_POLY ) & 0xffffffffffffffffn ;
188+ if ( ( hi & 0x80000000 ) !== 0 ) {
189+ hi = ( ( ( hi << 1 ) | ( lo >>> 31 ) ) ^ CRC64_POLY_HI ) >>> 0 ;
190+ lo = ( ( lo << 1 ) ^ CRC64_POLY_LO ) >>> 0 ;
186191 } else {
187- crc = ( crc << 1n ) & 0xffffffffffffffffn ;
192+ hi = ( ( hi << 1 ) | ( lo >>> 31 ) ) >>> 0 ;
193+ lo = ( lo << 1 ) >>> 0 ;
188194 }
189195 }
190- table [ i ] = crc ;
196+ table [ i * 2 ] = hi ;
197+ table [ i * 2 + 1 ] = lo ;
191198 }
192199 return table ;
193200} ) ( ) ;
194201
195- function crc64Accumulate ( crc : bigint , chunk : Uint8Array ) : bigint {
202+ function crc64Accumulate (
203+ crcHi : number , crcLo : number , chunk : Uint8Array
204+ ) : [ number , number ] {
196205 for ( let i = 0 ; i < chunk . length ; i ++ ) {
197- const index = Number ( ( crc >> 56n ) ^ BigInt ( chunk [ i ] ) ) & 0xff ;
198- crc = ( ( crc << 8n ) ^ CRC64_TABLE [ index ] ) & 0xffffffffffffffffn ;
206+ const index = ( ( crcHi >>> 24 ) ^ chunk [ i ] ) & 0xff ;
207+ const tHi = CRC64_TABLE [ index * 2 ] ;
208+ const tLo = CRC64_TABLE [ index * 2 + 1 ] ;
209+ crcHi = ( ( ( crcHi << 8 ) | ( crcLo >>> 24 ) ) ^ tHi ) >>> 0 ;
210+ crcLo = ( ( crcLo << 8 ) ^ tLo ) >>> 0 ;
199211 }
200- return crc ;
212+ return [ crcHi , crcLo ] ;
201213}
202214
203- function bigintToUint8Array ( n : bigint ) : Uint8Array {
215+ function crc64ToUint8Array ( hi : number , lo : number ) : Uint8Array {
204216 const buf = Buffer . allocUnsafe ( 8 ) ;
205- buf . writeUInt32BE ( Number ( n >> 32n ) >>> 0 , 0 ) ;
206- buf . writeUInt32BE ( Number ( n & 0xffffffffn ) >>> 0 , 4 ) ;
217+ buf . writeUInt32BE ( hi >>> 0 , 0 ) ;
218+ buf . writeUInt32BE ( lo >>> 0 , 4 ) ;
207219 return buf ;
208220}
209221
210222export function getCRC64FromString ( text : string ) : Uint8Array {
211- return bigintToUint8Array ( crc64Accumulate ( 0n , Buffer . from ( text ) ) ) ;
223+ const [ hi , lo ] = crc64Accumulate ( 0 , 0 , Buffer . from ( text ) ) ;
224+ return crc64ToUint8Array ( hi , lo ) ;
212225}
213226
214227export async function getCRC64FromStream (
215228 stream : NodeJS . ReadableStream
216229) : Promise < Uint8Array > {
217230 return new Promise < Uint8Array > ( ( resolve , reject ) => {
218- let crc = 0n ;
231+ let hi = 0 , lo = 0 ;
219232 stream
220233 . on ( "data" , ( chunk : Buffer | string ) => {
221234 const data = Buffer . isBuffer ( chunk ) ? chunk : Buffer . from ( chunk as string ) ;
222- crc = crc64Accumulate ( crc , data ) ;
235+ [ hi , lo ] = crc64Accumulate ( hi , lo , data ) ;
223236 } )
224237 . on ( "end" , ( ) => {
225- resolve ( bigintToUint8Array ( crc ) ) ;
238+ resolve ( crc64ToUint8Array ( hi , lo ) ) ;
226239 } )
227240 . on ( "error" , reject ) ;
228241 } ) ;
@@ -237,15 +250,15 @@ export async function computeTransactionalChecksums(
237250) : Promise < { md5 : Uint8Array ; crc64 : Uint8Array } > {
238251 const hash = createHash ( "md5" ) ;
239252 return new Promise ( ( resolve , reject ) => {
240- let crc = 0n ;
253+ let hi = 0 , lo = 0 ;
241254 stream
242255 . on ( "data" , ( chunk : Buffer | string ) => {
243256 const data = Buffer . isBuffer ( chunk ) ? chunk : Buffer . from ( chunk as string ) ;
244257 hash . update ( data ) ;
245- crc = crc64Accumulate ( crc , data ) ;
258+ [ hi , lo ] = crc64Accumulate ( hi , lo , data ) ;
246259 } )
247260 . on ( "end" , ( ) => {
248- resolve ( { md5 : hash . digest ( ) , crc64 : bigintToUint8Array ( crc ) } ) ;
261+ resolve ( { md5 : hash . digest ( ) , crc64 : crc64ToUint8Array ( hi , lo ) } ) ;
249262 } )
250263 . on ( "error" , reject ) ;
251264 } ) ;
0 commit comments