UNPKG

@privateid/ultra-web-sdk-alpha

Version:
925 lines (816 loc) 31.4 kB
/* eslint-disable no-eval */ /* eslint-disable default-param-last */ /* eslint-disable no-undef */ /* eslint-disable no-underscore-dangle */ // importScripts('https://unpkg.com/comlink/dist/umd/comlink.js'); importScripts('./comlink.min.js'); var wasmPrivModules; let apiUrl; let sesstionToken; let publicKey; let debugType; let inputPtr; let imageInputSize; let barCodePtr; let privid_wasm_result = null; let privid_wasm_error = null; let wasmSession = null; let setCache = true; let checkWasmLoaded = false; let antispoofVersion; const ModuleName = 'ultra'; const cdnUrl = 'https://ultra-wasm.devel.privateid.com'; // Devel // const cdnUrl = 'https://ultra-wasm.privateid.com/wasm'; // Prod let useCdnLink = true; const createImageArguments = (imageData, width, height) => {}; const createStringArguments = () => {}; const printLogs = (message, data, type = 'LOG') => { console.log('FROM SDK', message, data); const errorLogs = ['1', '2', '3', '901', '902', '903']; const warningLogs = ['2', '3', '902', '903']; const allLogs = ['3', '903']; if (type === 'ERROR' && errorLogs.includes(debugType)) { console.error('DEBUG_SDK_WASM_WORKER', message, data); } else if (type === 'WARN' && warningLogs.includes(debugType)) { console.warn('DEBUG_SDK_WASM_WORKER', message, data); } else if (type === 'LOG' && allLogs.includes(debugType)) { console.log('DEBUG_SDK_WASM_WORKER', message, data); } }; const isLoad = ( simd, url, session_token, public_key, debug_type, cacheConfig = true, timeout = 5000, useCdn = false, shouldRegenerateSession, failureCb, usageScenario, cache_content, ) => new Promise(async (resolve, reject) => { apiUrl = url; sesstionToken = session_token; publicKey = public_key; useCdnLink = useCdn; privid_wasm_error = failureCb; if (debug_type) { debugType = debug_type; } let timeoutSession = 5000; if (timeout) { timeoutSession = timeout; } setCache = cacheConfig; printLogs(`data: `, { simd, url, session_token, public_key, debug_type, cache_content }); const modulePath = simd ? 'simd' : 'nosimd'; const moduleName = 'privid_fhe_uber'; const cachedModule = await readKey(ModuleName); // const fetchdVersion = await fetchdWasmVersion.json(); const fetchdWasmVersion = await (await fetch(`../wasm/${ModuleName}/${modulePath}/version.json`)).json(); printLogs( `versions: cached: ${cachedModule ? cachedModule?.version.toString() : 'no cached wasm'}, fetched: ${fetchdWasmVersion ? fetchdWasmVersion.version.toString() : 'no fetched version'}) modulePath: ${modulePath}`, '', ); const loadFromPackage = async () => { printLogs(`fetched version: `, fetchdWasmVersion); wasmPrivModules = await loadWasmModule(modulePath, moduleName, true, `${fetchdWasmVersion.version}`); printLogs(`ULTRA MODULE: `, wasmPrivModules); if (!checkWasmLoaded) { await initializeWasmSession( url, sesstionToken, publicKey, debugType, timeoutSession, usageScenario, cache_content, ); checkWasmLoaded = true; } resolve('Loaded'); }; if ( cachedModule && cachedModule.version && fetchdWasmVersion && fetchdWasmVersion.version && cachedModule.version.toString() === fetchdWasmVersion?.version.toString() ) { printLogs(`same version confirmed`, ''); printLogs(`PRIVMODULES LOADED?: `, wasmPrivModules); if (!wasmPrivModules) { const { cachedWasm, cachedScript } = cachedModule; if (cachedWasm && cachedScript) { eval(cachedScript); wasmPrivModules = await createTFLiteModule({ wasmBinary: cachedWasm }); printLogs(`ULTRA MODULE `, wasmPrivModules); if (!checkWasmLoaded) { await initializeWasmSession( url, sesstionToken, publicKey, debugType, timeoutSession, usageScenario, cache_content, ); checkWasmLoaded = true; } printLogs(`WASM MODULES: `, wasmPrivModules); } else { await loadFromPackage(); } } else if (wasmPrivModules && shouldRegenerateSession) { wasmSession = null; await initializeWasmSession( url, sesstionToken, publicKey, debugType, timeoutSession, usageScenario, cache_content, ); } else { await loadFromPackage(); } resolve('Cache Loaded'); } else { await loadFromPackage(); } }); function flatten(arrays, TypedArray) { const arr = new TypedArray(arrays.reduce((n, a) => n + a.length, 0)); let i = 0; arrays.forEach((a) => { arr.set(a, i); i += a.length; }); return arr; } const ultraEnroll = async (imageData, simd, config, cb) => { privid_wasm_result = cb; if (!wasmPrivModules) { await isLoad(simd, apiUrl, sesstionToken, publicKey, debugType); } const imageInputSize = imageData.data.length * imageData.data.BYTES_PER_ELEMENT; const imageInputPtr = wasmPrivModules._malloc(imageInputSize); wasmPrivModules.HEAPU8.set(new Uint8Array(imageData.data), imageInputPtr); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); const encoder = new TextEncoder(); const config_bytes = encoder.encode(`${config}`); const configInputSize = config_bytes.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); const bestImageFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); const bestImageLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); printLogs(`config: `, config); try { wasmPrivModules._privid_user_enroll( wasmSession /* session pointer */, configInputPtr, configInputSize, imageInputPtr /* input images */, imageData.width /* width of one image */, imageData.height /* height of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); } catch (e) { printLogs(`Error: `, e, 'ERROR'); } // let bestImage = null; // const [outputBufferSize] = new Uint32Array(wasmPrivModules.HEAPU8.buffer, bestImageLenPtr, 1); // if (outputBufferSize > 0) { // let outputBufferSecPtr = null; // [outputBufferSecPtr] = new Uint32Array(wasmPrivModules.HEAPU8.buffer, bestImageFirstPtr, 1); // const outputBufferPtr = new Uint8Array(wasmPrivModules.HEAPU8.buffer, outputBufferSecPtr, outputBufferSize); // const outputBuffer = Uint8ClampedArray.from(outputBufferPtr); // const outputBufferData = outputBufferSize > 0 ? outputBuffer : null; // bestImage = { imageData: outputBufferData, width: imageData.width, height: imageData.height }; // wasmPrivModules._free(outputBufferPtr); // } wasmPrivModules._free(imageInputPtr); wasmPrivModules._free(resultFirstPtr); wasmPrivModules._free(resultLenPtr); wasmPrivModules._free(configInputPtr); wasmPrivModules._free(bestImageFirstPtr); wasmPrivModules._free(bestImageLenPtr); // return bestImage; }; const ultraAgeEstimate = async (originalImages, simd, config, cb) => { privid_wasm_result = cb; if (!wasmPrivModules) { await isLoad(simd, apiUrl, sesstionToken, publicKey, debugType); } const imageInput = flatten( originalImages.map((x) => x.data), Uint8Array, ); const encoder = new TextEncoder(); const config_bytes = encoder.encode(`${config}`); const configInputSize = config.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); const imageInputSize = imageInput.length * imageInput.BYTES_PER_ELEMENT; const imageInputPtr = wasmPrivModules._malloc(imageInputSize); wasmPrivModules.HEAP8.set(imageInput, imageInputPtr / imageInput.BYTES_PER_ELEMENT); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); // create a pointer to interger to hold the length of the output buffer const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); printLogs(`Config: `, config); try { await wasmPrivModules._privid_estimate_age( wasmSession /* session pointer */, configInputPtr, configInputSize, imageInputPtr /* input images */, originalImages[0].width /* width of one image */, originalImages[0].height /* height of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); } catch (e) { printLogs(`Error: `, e, 'ERROR'); } wasmPrivModules._free(imageInputPtr); wasmPrivModules._free(configInputPtr); wasmPrivModules._free(resultFirstPtr); wasmPrivModules._free(resultLenPtr); }; const ultraPredict = async (originalImages, simd, config, cb) => { privid_wasm_result = cb; if (!wasmPrivModules) { await isLoad(simd, apiUrl, sesstionToken, publicKey, debugType); } const numImages = originalImages.length; const imageInput = flatten( originalImages.map((x) => x.data), Uint8Array, ); // const version = wasmPrivModules._get_version(); const encoder = new TextEncoder(); const config_bytes = encoder.encode(`${config}`); const configInputSize = config.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); const imageInputSize = imageInput.length * imageInput.BYTES_PER_ELEMENT; const imageInputPtr = wasmPrivModules._malloc(imageInputSize); wasmPrivModules.HEAP8.set(imageInput, imageInputPtr / imageInput.BYTES_PER_ELEMENT); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); // create a pointer to interger to hold the length of the output buffer const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); printLogs(`Config:`, config); try { await wasmPrivModules._privid_user_predict( wasmSession /* session pointer */, configInputPtr, configInputSize, imageInputPtr /* input images */, originalImages[0].width /* width of one image */, originalImages[0].height /* height of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); } catch (e) { printLogs(`Error: `, e, 'ERROR'); } wasmPrivModules._free(imageInputPtr); wasmPrivModules._free(configInputPtr); wasmPrivModules._free(resultFirstPtr); wasmPrivModules._free(resultLenPtr); }; function readKey(key) { if (!indexedDB) return Promise.reject(new Error('IndexedDB not available')); return new Promise((resolve, reject) => { const open = indexedDB.open('/privid-wasm', 21); open.onerror = function () { resolve(false); }; open.onupgradeneeded = function () { open.result.createObjectStore('/privid-wasm'); }; open.onsuccess = function () { const db = open.result; const tx = db.transaction('/privid-wasm', 'readwrite'); const store = tx.objectStore('/privid-wasm'); const getKey = store.get(key); getKey.onsuccess = function () { resolve(getKey.result); }; tx.onerror = function () { reject(tx.error); }; tx.oncomplete = function () { try { db.close(); } catch (e) { // printLogs(`Error readKey: `, e, 'ERROR'); } }; }; }); } function putKey(key, cachedWasm, cachedScript, version) { if (!indexedDB) return Promise.reject(new Error('IndexedDB not available')); return new Promise((resolve, reject) => { const open = indexedDB.open('/privid-wasm', 21); open.onerror = function () { resolve(false); }; open.onupgradeneeded = function () { open.result.createObjectStore('/privid-wasm'); }; open.onsuccess = function () { const db = open.result; const tx = db.transaction('/privid-wasm', 'readwrite'); const store = tx.objectStore('/privid-wasm'); const getKey = store.put({ cachedWasm, cachedScript, version }, key); getKey.onsuccess = function () { resolve('saved'); }; tx.onerror = function () { reject(tx.error); }; tx.oncomplete = function () { try { db.close(); } catch (e) { // printLogs(`Error putKey: `, e, 'ERROR'); } }; }; }); } // async function setCacheConfiguration() { // const db = indexedDB.open('test'); // db.onerror = function () { // printLogs(`Private browser no cache`, ''); // }; // db.onsuccess = async function () { // const cacheObj = JSON.stringify({ cache_type: setCache ? 'basic' : 'nocache' }); // const encoder = new TextEncoder(); // const cache_config_bytes = encoder.encode(`${cacheObj}`); // const cacheInputSize = cacheObj.length; // const cacheInputPtr = wasmPrivModules._malloc(cacheInputSize); // wasmPrivModules.HEAP8.set(cache_config_bytes, cacheInputPtr / cache_config_bytes.BYTES_PER_ELEMENT); // await wasmPrivModules._privid_set_configuration(wasmSession, cacheInputPtr, cacheInputSize); // wasmPrivModules._free(cacheInputPtr); // }; // } /** * @brief A closure to create a string buffer arguments that can be used with wasm calls * for a given javascript value. * This is suitable for native calls that have string input arguments represented with contigious * string_buffer,sizeofbuffer arguments. * If the 'text' argument is null or undefined or NaN then the arguments generated are [null,0] * @usage * var url_args= buffer_args(url); var key_args= buffer_args(key); var session_out_ptr = output_ptr(); const s_result = wasmPrivModules._privid_initialize_session( ...key_args.args(), ...url_args.args(), debug_type, session_out_ptr.outer_ptr(), ); url_args.free(); key_args.free(); //get var session = session_out_ptr.inner_ptr(); * * when .free() is called the closure can be reused to create a buffer for the same string with which, it was created with * over and over again. */ const buffer_args = function (text) { let strInputtPtr = null; let strInputSize = 0; let argsv = []; return { args: () => { do { if (argsv.length > 0) break; argsv = [null, 0]; if (text === null) break; if (text === undefined) break; // eslint-disable-next-line use-isnan if (text === NaN) break; const str = `${text}`; const encoder = new TextEncoder(); const bytes = encoder.encode(str); strInputSize = bytes.length * bytes.BYTES_PER_ELEMENT; strInputtPtr = wasmPrivModules._malloc(strInputSize); wasmPrivModules.HEAP8.set(bytes, strInputtPtr / bytes.BYTES_PER_ELEMENT); argsv = [strInputtPtr, strInputSize]; } while (false); return argsv; }, free: () => { if (strInputtPtr) { wasmPrivModules._free(strInputtPtr); strInputtPtr = null; strInputSize = 0; argsv = []; } }, }; }; /** * @brief A closure to create an output 32bits pointer closure. * This is usefull for allocating a native address and pass it to the * 'wasmPrivModules' so it can return in the address of a buffer (or an object like session) * that was allocated inside the wasm. This typically, correspond to * an argument of type void** (marked output argument) to pass to a native wasm * call. * @usage var myoutput_ptr = output_ptr(); * when passing the output pointer to the 'wasmPrivModules' module use * wasmPrivModules.nativecall(myoutput_ptr.outer_ptr()); * Then pull out the the allocated buffer by the wasm call this way: * @code * my_buffer_or_structure = myoutput_ptr.inner_ptr(); * @note It is the responsability of the caller to free the pointer returned by this inner_ptr() */ const output_ptr = function () { let out_ptr = null; let in_ptr = null; const free_ptr = (ptr) => { if (ptr) { wasmPrivModules._free(ptr); // eslint-disable-next-line no-param-reassign ptr = null; } }; return { /** * @brief Allocates a pointer to contain the result and return it, * if the container is already created it will be returned */ outer_ptr: () => { // TODO: may be used SharedArrayBuffer() instead // allocate memory the expected pointer (outer pointer or container) if (!out_ptr) out_ptr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); return out_ptr; }, /** * @brief Creates a javascript Uint32Array pointer to contain the result pointed by outer_ptr and return it, * It is the responsability of the caller to free the pointer returned by this function */ inner_ptr: () => { // If we did not allocate yet the output buffer return null if (!out_ptr) return null; // if we already have our inner pointer for this closure return it if (in_ptr) return in_ptr; // Access the outer pointer as an arry of uint32 which conatin a single cell // whose value is the pointer allocated in the wasm module (inner pointer of the output param) // and return it [in_ptr] = new Uint32Array(wasmPrivModules.HEAPU8.buffer, out_ptr, 1); return in_ptr; }, }; }; async function ultraCompareEmbeddings(encryptedEmbeddingsA, encryptedEmbeddingsB, config, cb) { try { privid_wasm_result = cb; if (!wasmPrivModules) { await isLoad(simd, apiUrl, sesstionToken, publicKey, debugType); } const encoder = new TextEncoder(); const config_bytes = encoder.encode(`${config}`); const configInputSize = config.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); const embeddingA_bytes = encoder.encode(`${encryptedEmbeddingsA}`); const embeddingOneSize = encryptedEmbeddingsA.length; const embeddingOnePtr = wasmPrivModules._malloc(embeddingOneSize); wasmPrivModules.HEAP8.set(embeddingA_bytes, embeddingOnePtr / embeddingA_bytes.BYTES_PER_ELEMENT); const embeddingB_bytes = encoder.encode(`${encryptedEmbeddingsB}`); const embeddingTwoSize = encryptedEmbeddingsB.length; const embeddingTwoPtr = wasmPrivModules._malloc(embeddingTwoSize); wasmPrivModules.HEAP8.set(embeddingB_bytes, embeddingTwoPtr / embeddingB_bytes.BYTES_PER_ELEMENT); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); // create a pointer to interger to hold the length of the output buffer const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); const result = await wasmPrivModules._privid_compare_embeddings( wasmSession /* session pointer */, configInputPtr, configInputSize, embeddingOnePtr /* 1st embedding (encrypted string) */, embeddingOneSize /* 1st embedding size */, embeddingTwoPtr /* 2nd embedding (encrypted string) */, embeddingTwoSize /* 2nd embedding size */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); wasmPrivModules._free(embeddingOnePtr); wasmPrivModules._free(embeddingTwoPtr); wasmPrivModules._free(configInputPtr); wasmPrivModules._free(resultFirstPtr); wasmPrivModules._free(resultLenPtr); return result; } catch (e) { printLogs(`Compare embeddings: `, e, 'ERROR'); } } async function ultraDocumentOcr(imageInput, config, cb) { try { privid_wasm_result = cb; if (!wasmPrivModules) { await isLoad(simd, apiUrl, sesstionToken, publicKey, debugType); } const encoder = new TextEncoder(); const config_bytes = encoder.encode(`${config}`); const input_Image_bytes = encoder.encode(`${imageInput}`); const configInputSize = config.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); const imageInputSize = imageInput.length; const imageInputPtr = wasmPrivModules._malloc(imageInputSize); wasmPrivModules.HEAP8.set(input_Image_bytes, imageInputPtr / input_Image_bytes.BYTES_PER_ELEMENT); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); // create a pointer to interger to hold the length of the output buffer const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); printLogs(`Document OCR Config: `, config); try { await wasmPrivModules._privid_doc_ocr_front_enc( wasmSession /* session pointer */, configInputPtr, configInputSize, imageInputPtr /* input images */, imageInputSize /* size of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); } catch (e) { printLogs(`Error: `, e, 'ERROR'); } wasmPrivModules._free(imageInputPtr); wasmPrivModules._free(configInputPtr); wasmPrivModules._free(resultFirstPtr); wasmPrivModules._free(resultLenPtr); } catch (e) { printLogs(`Compare embeddings: `, e, 'ERROR'); } } async function initializeWasmSession( url, session_token, public_key, debug_type, timeout = 5000, usageScenario, cache_content = '', ) { if (!wasmSession) { printLogs(`initSession: ${url}, ${session_token}, ${public_key} `); const session_out_ptr = output_ptr(); const settings = { ...url, session_token, public_key, debug_level: debug_type ? parseInt(debugType) : 0, custom_settings: { usage_scenario: usageScenario, cache_content }, }; printLogs(`Settings:`, settings); const settings_args = buffer_args(JSON.stringify(settings)); const s_result = wasmPrivModules._privid_initialize_session(...settings_args.args(), session_out_ptr.outer_ptr()); settings_args.free(); const isLoadedModels = wasmPrivModules._privid_check_models(); printLogs(`Loaded Models: `, isLoadedModels); if (s_result) { printLogs(`Session initialized successfully`, ''); } else { printLogs(`Session initialization Failed`, '', 'ERROR'); return; } wasmSession = session_out_ptr.inner_ptr(); printLogs(`wasm session: `, wasmSession); // if (setCache) { // await setCacheConfiguration(); // } } } const loadWasmModule = async (modulePath, moduleName, saveCache, version) => { const wasm = await fetchResource( `${cdnUrl}/${ModuleName}/${modulePath}/${version}/${moduleName}.wasm`, `../wasm/${ModuleName}/${modulePath}/${version}/${moduleName}.wasm`, ); const script = await fetchResource( `${cdnUrl}/${ModuleName}/${modulePath}/${version}/${moduleName}.js`, `../wasm/${ModuleName}/${modulePath}/${version}/${moduleName}.js`, ); const scriptBuffer = await script.text(); const buffer = await wasm.arrayBuffer(); printLogs(`SCRIPT. BUFFER': `, { scriptBuffer, buffer }); eval(scriptBuffer); const module = await createTFLiteModule({ wasmBinary: buffer }); printLogs(`Module: `, module); if (saveCache) { const version = module.UTF8ToString(module._privid_get_version()); await putKey('ultra', buffer, scriptBuffer, version); } return module; }; async function fetchResource(cdnUrl, localUrl) { try { printLogs(`LOADING RESOURCE`, ''); if (useCdnLink) { const response = await fetch(cdnUrl); printLogs(`Response: `, response); return response; } else { const response = await fetch(localUrl); return response; } } catch (error) { console.error(`Error fetching resource from CDN. Falling back to local path. Error: ${error}`); return fetch(localUrl); } } const pkiEncrypt = async (payload, config = JSON.stringify({})) => { const encoder = new TextEncoder(); const payloadBytes = encoder.encode(`${payload}`); const payloadInputSize = payloadBytes.length; const payloadInputPtr = wasmPrivModules._malloc(payloadInputSize); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); // create a pointer to interger to hold the length of the output buffer const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); wasmPrivModules.HEAP8.set(payloadBytes, payloadInputPtr / payloadBytes.BYTES_PER_ELEMENT); printLogs(`Payload: `, payload, debugType); let res = null; const config_bytes = encoder.encode(`${config}`); const configInputSize = config.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); try { res = wasmPrivModules._privid_encrypt_payload( wasmSession /* session pointer */, configInputPtr, configInputSize, payloadInputPtr, payloadInputSize, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); } catch (e) { printLogs(`Error: `, e, 'ERROR'); } printLogs(`Result: `, res); const [outputBufferSizes] = new Uint32Array(wasmPrivModules.HEAPU8.buffer, resultLenPtr, 1); if (outputBufferSizes > 0) { // de-reference & copy the data from pointer to integer in integer array of one element const outputBufferSize = new Uint32Array(wasmPrivModules.HEAPU8.buffer, resultLenPtr, 1)[0]; const outputBufferSecPtr = new Uint32Array(wasmPrivModules.HEAPU8.buffer, resultFirstPtr, 1)[0]; const outputBufferPtr = new Uint8Array(wasmPrivModules.HEAPU8.buffer, outputBufferSecPtr, outputBufferSize); var decoder = new TextDecoder('utf8'); var dec = decoder.decode(outputBufferPtr); dec.replace(/\0/g, ''); dec.replace(' ', ''); function removeNullBytes(str) { return str .split('') .filter((char) => char.codePointAt(0)) .join(''); } let parsedDec = JSON.stringify(removeNullBytes(dec)); printLogs(`Parsed: `, parsedDec); let isObject = JSON.parse(parsedDec); printLogs(`Is object? `, isObject); return JSON.parse(isObject); } return { error: true }; }; const ultraScanFrontDocument = async (imageInput, simd, config, cb) => { privid_wasm_result = cb; if (!wasmPrivModules) { await isLoad(simd, apiUrl, sesstionToken, publicKey); } const encoder = new TextEncoder(); const config_bytes = encoder.encode(`${config}`); const configInputSize = config.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); const imageInputSize = imageInput.data.length * imageInput.data.BYTES_PER_ELEMENT; const imageInputPtr = wasmPrivModules._malloc(imageInputSize); wasmPrivModules.HEAPU8.set(new Uint8Array(imageInput.data), imageInputPtr); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); printLogs(`Config: `, { wasmSession /* session pointer */, configInputPtr, configInputSize, imageInputPtr /* input images */, width: imageInput.width /* width of one image */, height: imageInput.height /* height of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr, }); try { await wasmPrivModules._privid_doc_scan_front( wasmSession /* session pointer */, configInputPtr, configInputSize, imageInputPtr /* input images */, imageInput.width /* width of one image */, imageInput.height /* height of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); } catch (e) { printLogs(`Error: `, e, 'ERROR'); } wasmPrivModules._free(imageInputPtr); wasmPrivModules._free(configInputPtr); wasmPrivModules._free(resultFirstPtr); wasmPrivModules._free(resultLenPtr); }; const ultraScanBackDocument = async (imageInput, simd, config, cb) => { privid_wasm_result = cb; if (!wasmPrivModules) { await isLoad(simd, apiUrl, sesstionToken, publicKey, debugType); } printLogs(`Extra config: `, config); const encoder = new TextEncoder(); const config_bytes = encoder.encode(`${config}`); const configInputSize = config.length; const configInputPtr = wasmPrivModules._malloc(configInputSize); wasmPrivModules.HEAP8.set(config_bytes, configInputPtr / config_bytes.BYTES_PER_ELEMENT); printLogs(`Image Input `, imageInput); const imageInputSize = imageInput?.data?.length * imageInput?.data?.BYTES_PER_ELEMENT; const imageInputPtr = wasmPrivModules._malloc(imageInputSize); printLogs(`Input image Size:`, imageInputSize); wasmPrivModules.HEAPU8.set(new Uint8Array(imageInput.data), imageInputPtr); // wasmPrivModules.HEAP8.set(imageInput, imageInputPtr / imageInput?.data?.BYTES_PER_ELEMENT); const resultFirstPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); // create a pointer to interger to hold the length of the output buffer const resultLenPtr = wasmPrivModules._malloc(Int32Array.BYTES_PER_ELEMENT); printLogs(`Config: `, { configInputPtr, configInputSize, imageInputPtr /* input images */, width: imageInput.width /* width of one image */, height: imageInput.height /* height of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, }); try { await wasmPrivModules._privid_doc_scan_back( wasmSession /* session pointer */, configInputPtr, configInputSize, imageInputPtr /* input images */, imageInput.width /* width of one image */, imageInput.height /* height of one image */, resultFirstPtr /* operation result output buffer */, resultLenPtr /* operation result buffer length */, ); } catch (e) { printLogs(`Error: `, e, 'ERROR'); } wasmPrivModules._free(imageInputPtr); wasmPrivModules._free(configInputPtr); wasmPrivModules._free(resultFirstPtr); wasmPrivModules._free(resultLenPtr); }; const checkIfModelsLoaded = () => { try { const isLoaded = wasmPrivModules._privid_check_models(); return isLoaded; } catch (e) { printLogs(`Error: `, e, 'ERROR'); return 0; } }; const freeMemory = () => { try { const isLoaded = wasmPrivModules._privid_free_memory(); return isLoaded; } catch (e) { printLogs(`Error: `, e, 'ERROR'); return 0; } }; Comlink.expose({ ultraEnroll, ultraPredict, ultraAgeEstimate, ultraCompareEmbeddings, isLoad, pkiEncrypt, checkIfModelsLoaded, ultraScanBackDocument, ultraScanFrontDocument, ultraDocumentOcr, freeMemory, });