Files
Endoleap/src/lib/canvas-runtime/import-integrity.ts
T

18 lines
1.5 KiB
TypeScript

/**
* 完整导入源的增量 SHA256:有界 Blob 分块读取,不把全文件放进 UI ArrayBuffer。
* 摘要是源完整性/稳定身份依据,不证明该文件有权限、schema 正确或所有记录已加入画布。
*/
import { fault } from '../canvas-core/values.ts';
import {createSha256} from './sha256.ts';
/** Complete-source SHA-256, with bounded chunk memory and cooperative fallback scheduling. */
/** 默认64KiB分块(配置上限4MiB),每块读前/读后检查取消,并在块间合作让出。 */
export async function importSourceDigest(bytes:Blob,signal?:AbortSignal,options:{chunkBytes?:number;yieldTask?:()=>Promise<void>}={}):Promise<string>{
const chunk=options.chunkBytes??64*1024,yieldTask=options.yieldTask??(()=>new Promise<void>(resolve=>setTimeout(resolve,0)));
if(!(bytes instanceof Blob)||!Number.isSafeInteger(chunk)||chunk<1||chunk>4*1024*1024)throw fault('invalid_digest_input');
/** 读/计算/让出边界统一检查 signal;异步读取即使无法中止,迟到字节也不再参与有效结果。 */
const check=()=>{if(signal?.aborted)throw fault('import_aborted');};check();const hash=createSha256();
// 更新增量状态后释放对本块的局部引用;空文件直接 hex 得到标准空输入摘要。
for(let cursor=0;cursor<bytes.size;cursor+=chunk){check();const part=await bytes.slice(cursor,cursor+chunk).arrayBuffer();check();hash.update(new Uint8Array(part));if(cursor+chunk<bytes.size){await yieldTask();check();}}
check();return hash.hex();
}