fileoverview import base64js from "base64-js" ; import { generateRandomUInt32Array } from "../platform-dependent" ; const UINT_32HASH_PRIME = 16777619 ; /**
 * Fast high quality 32 bit RNG for consistent guid.
 *
 * Good "randomness" (distribution); Period is approximately equal to  3.11*10^37
 * Implementation was take from "Numerical recipes. The Art of Scientific Computing.", 3rd edition.
 * Page 357, algorithm name: Ranlim32
 *
 */ const guidRNG = { u : 0 , v : 0 , w1 : 0 , w2 : 0 , isInitialized : false , param in_seed param in_enforceReInitialization returns alias initialize ( in_seed ? , in_enforceReInitialization = false ) { if ( this . isInitialized && ! in_enforceReInitialization ) { return 0 ; } else { this . isInitialized = true ; if ( in_seed === undefined ) { const randomValues = generateRandomUInt32Array ( 4 ) ; this . u = randomValues [ 0 ] ; this . v = randomValues [ 1 ] ; this . w1 = randomValues [ 2 ] ; this . w2 = randomValues [ 3 ] ; } else { this . v = 224461437 ; this . w1 = 521288629 ; this . w2 = 362436069 ; this . u = in_seed ^ this . v ; this . genRandUInt32 ( ) ; this . v = this . u ; this . genRandUInt32 ( ) ; } return - 1 ; } } , returns genRandUInt32 ( ) { this . u = multiply_uint32 ( this . u , 2891336453 ) + 1640531513 ; this . v ^= this . v >>> 13 ; this . v ^= this . v << 17 ; this . v = ( ( this . v >>> 5 ) ^ this . v ) >>> 0 ; this . w1 = multiply_uint32 ( 33378 , ( this . w1 & 0xffff ) ) + ( this . w1 >>> 16 ) ; this . w2 = multiply_uint32 ( 57225 , ( this . w2 & 0xffff ) ) + ( this . w2 >>> 16 ) ; let x = this . u ^ ( this . u << 9 ) ; x ^= x >>> 17 ; x ^= x << 6 ; let y = this . w1 ^ ( this . w1 << 17 ) ; y ^= y >>> 15 ; y ^= y << 5 ; return ( ( ( x >>> 0 ) + this . v ) ^ ( ( y >>> 0 ) + this . w2 ) ) >>> 0 ; } } ; param guid returns const isBase64 = ( guid ) : boolean => guid . length === 22 ; param a param b returns function multiply_uint32 ( a , b ) { let n = a ; let m = b ; n >>>= 0 ; m >>>= 0 ; const nlo = n & 0xffff ; return ( ( ( n - nlo ) * m >>> 0 ) + ( nlo * m ) ) >>> 0 ; } param base64 returns const toUrlBase64 = ( base64 ) : string => base64 . replace ( /\+/g , "-" ) . replace ( /\//g , "_" ) . split ( "=" ) [ 0 ] ; param x returns const toPaddedBase64 = function ( x ) : string { let base64 = x ; const padLength = 4 - base64 . length % 4 ; base64 += "=" . repeat ( padLength ) ; return base64 ; } ; param in_guidArray param base64 returns const uint32x4ToGUID = function ( in_guidArray , base64 = false ) : string { if ( base64 ) { const intArray = new Uint32Array ( in_guidArray ) ; const byteArray = new Uint8Array ( intArray . buffer ) ; const base64guid = base64js . fromByteArray ( byteArray ) ; return toUrlBase64 ( base64guid ) ; } else { let str = "" ; for ( let i = 0 ; i < 4 ; i ++ ) { const hex = in_guidArray [ i ] . toString ( 16 ) ; str += ( "0" . repeat ( 8 - hex . length ) + hex ) ; } return `${ str . substr ( 0 , 8 ) }-${ str . substr ( 8 , 4 ) }-${ str . substr ( 12 , 4 ) }-${ str . substr ( 16 , 4 ) }-${ str . substr ( 20 , 12 ) }` ; } } ; param in_guid param io_result returns const guidToUint32x4 = function ( in_guid , result = new Uint32Array ( 4 ) ) : Uint32Array { if ( isBase64 ( in_guid ) ) { const guid = toPaddedBase64 ( in_guid ) ; const bytes = base64js . toByteArray ( guid ) ; const intArray = new Uint32Array ( bytes . buffer ) ; result . set ( intArray ) ; } else { result [ 0 ] = parseInt ( `0x${ in_guid . substr ( 0 , 8 ) }` , 16 ) ; result [ 1 ] = parseInt ( `0x${ in_guid . substr ( 9 , 4 ) }${ in_guid . substr ( 14 , 4 ) }` , 16 ) ; result [ 2 ] = parseInt ( `0x${ in_guid . substr ( 19 , 4 ) }${ in_guid . substr ( 24 , 4 ) }` , 16 ) ; result [ 3 ] = parseInt ( `0x${ in_guid . substr ( 28 , 8 ) }` , 16 ) ; } return result ; } ; param in_guid returns const base64Tobase16 = ( in_guid ) => uint32x4ToGUID ( guidToUint32x4 ( in_guid ) ) ; param in_guid returns const base16ToBase64 = ( in_guid ) => uint32x4ToGUID ( guidToUint32x4 ( in_guid ) , true ) ; param base64 returns const generateGUID = function ( base64 = false ) : string { const rnds = new Uint32Array ( 4 ) ; rnds [ 0 ] = guidRNG . genRandUInt32 ( ) ; rnds [ 1 ] = guidRNG . genRandUInt32 ( ) ; rnds [ 2 ] = guidRNG . genRandUInt32 ( ) ; rnds [ 3 ] = guidRNG . genRandUInt32 ( ) ; return uint32x4ToGUID ( rnds , base64 ) ; } ; const reBase64 = ( /^[\w-]{21}[AQgw]$/ ) ; const reBase16 = ( /^[\dA-Fa-f]{8}(?:-[\dA-Fa-f]{4}){3}-[\dA-Fa-f]{12}$/ ) ; param in_guid returns const isGUID = ( in_guid ) => reBase16 . test ( in_guid ) || reBase64 . test ( in_guid ) ; param in_array1 param in_array2 returns const hashCombine4xUint32 = function ( in_array1 , in_array2 , io_result ? ) : Uint32Array { let accumulated = io_result ; if ( accumulated === undefined ) { accumulated = new Uint32Array ( in_array2 ) ; } else { accumulated [ 0 ] = in_array2 [ 0 ] ; accumulated [ 1 ] = in_array2 [ 1 ] ; accumulated [ 2 ] = in_array2 [ 2 ] ; accumulated [ 3 ] = in_array2 [ 3 ] ; } accumulated [ 0 ] += 0x9e3779b9 ; accumulated [ 1 ] += 0x638f227 ; accumulated [ 2 ] += 0x1aff2bad ; accumulated [ 3 ] += 0x3a8f05c5 ; accumulated [ 0 ] += in_array1 [ 3 ] << 6 ; accumulated [ 1 ] += in_array1 [ 0 ] << 6 ; accumulated [ 2 ] += in_array1 [ 1 ] << 6 ; accumulated [ 3 ] += in_array1 [ 2 ] << 6 ; accumulated [ 0 ] += in_array1 [ 2 ] >> 2 ; accumulated [ 1 ] += in_array1 [ 3 ] >> 2 ; accumulated [ 2 ] += in_array1 [ 0 ] >> 2 ; accumulated [ 3 ] += in_array1 [ 1 ] >> 2 ; accumulated [ 0 ] = ( ( accumulated [ 0 ] ^ in_array1 [ 1 ] ) * UINT_32HASH_PRIME ) >>> 0 ; accumulated [ 1 ] = ( ( accumulated [ 1 ] ^ in_array1 [ 2 ] ) * UINT_32HASH_PRIME ) >>> 0 ; accumulated [ 2 ] = ( ( accumulated [ 2 ] ^ in_array1 [ 3 ] ) * UINT_32HASH_PRIME ) >>> 0 ; accumulated [ 3 ] = ( ( accumulated [ 3 ] ^ in_array1 [ 0 ] ) * UINT_32HASH_PRIME ) >>> 0 ; return accumulated ; } ; param in_guid1 param in_guid2 param base64 returns const combineGuids = function ( in_guid1 , in_guid2 , base64 = false ) : string { const firstArray = guidToUint32x4 ( in_guid1 ) ; const secondArray = guidToUint32x4 ( in_guid2 ) ; const combined = hashCombine4xUint32 ( firstArray , secondArray ) ; return uint32x4ToGUID ( combined , base64 ) ; } ; guidRNG . initialize ( ) ; const initializeGUIDGenerator = ( ... args ) => { guidRNG . initialize ( ... args ) ; } ; export const GuidUtils = { uint32x4ToGUID , guidToUint32x4 , base64Tobase16 , base16ToBase64 , initializeGUIDGenerator , generateGUID , isGUID , combineGuids , hashCombine4xUint32 } ;