Add proof-backed parser byte reads and preserve retryable source failures

This commit is contained in:
2026-11-09 22:47:49 +08:00
parent f0ee0736b7
commit f11ea36b48
9 changed files with 220 additions and 14 deletions
@@ -0,0 +1,17 @@
import {fault} from '../canvas-core/values.ts';
const failures=new Set(['import_source_changed','invalid_import_byte_range','import_read_capacity','import_source_closed','import_source_read_failed','invalid_import_read_proof','import_read_proof_interpreter_unavailable']);
export const isImportByteFailure=(error:unknown)=>failures.has((error as {code?:string}|undefined)?.code??'');
/** Optional immutable-source port. Implementations return exactly the requested bytes. */
export type ImportByteReader={readonly byteLength:number;read(start:number,end:number,signal:AbortSignal):Promise<Uint8Array>};
export async function readImportRange(bytes:Blob,reader:ImportByteReader|undefined,start:number,end:number,signal:AbortSignal):Promise<Uint8Array<ArrayBuffer>>{
if(signal.aborted)throw fault('import_aborted');
if(!Number.isSafeInteger(start)||!Number.isSafeInteger(end)||start<0||end<start||start>bytes.size||reader&&reader.byteLength!==bytes.size)throw fault('invalid_import_byte_range');
const limit=Math.min(end,bytes.size);let value:Uint8Array;
try{value=reader?await reader.read(start,limit,signal):new Uint8Array(await bytes.slice(start,end).arrayBuffer());}
catch(error){if(signal.aborted)throw fault('import_aborted');if(isImportByteFailure(error))throw error;throw fault('import_source_read_failed');}
if(signal.aborted)throw fault('import_aborted');
if(!(value instanceof Uint8Array)||value.byteLength!==limit-start)throw fault('import_source_changed');
return reader?new Uint8Array(value):value as Uint8Array<ArrayBuffer>;
}