( filePath: string, fileSize: number, )
| 715 | } |
| 716 | |
| 717 | export async function readTranscriptForLoad( |
| 718 | filePath: string, |
| 719 | fileSize: number, |
| 720 | ): Promise<{ |
| 721 | boundaryStartOffset: number |
| 722 | postBoundaryBuf: Buffer |
| 723 | hasPreservedSegment: boolean |
| 724 | }> { |
| 725 | const boundaryMarker = compactBoundaryMarker() |
| 726 | const CHUNK_SIZE = TRANSCRIPT_READ_CHUNK_SIZE |
| 727 | |
| 728 | const s: LoadState = { |
| 729 | out: { |
| 730 | // Gated callers enter with fileSize > 5MB, so min(fileSize, 8MB) lands |
| 731 | // in [5, 8]MB; large boundaryless sessions (24-31MB output) take 2 |
| 732 | // grows. Ungated callers (attribution.ts) pass small files too — the |
| 733 | // min just right-sizes the initial buf, no grows. |
| 734 | buf: Buffer.allocUnsafe(Math.min(fileSize, 8 * 1024 * 1024)), |
| 735 | len: 0, |
| 736 | // +1: finalizeOutput may insert one LF between a non-LF-terminated |
| 737 | // carry and the reordered last attr-snap (crash-truncated file). |
| 738 | cap: fileSize + 1, |
| 739 | }, |
| 740 | boundaryStartOffset: 0, |
| 741 | hasPreservedSegment: false, |
| 742 | lastSnapSrc: null, |
| 743 | lastSnapLen: 0, |
| 744 | lastSnapBuf: undefined, |
| 745 | bufFileOff: 0, |
| 746 | carryLen: 0, |
| 747 | carryBuf: undefined, |
| 748 | straddleSnapCarryLen: 0, |
| 749 | straddleSnapTailEnd: 0, |
| 750 | } |
| 751 | |
| 752 | const chunk = Buffer.allocUnsafe(CHUNK_SIZE) |
| 753 | const fd = await fsOpen(filePath, 'r') |
| 754 | try { |
| 755 | let filePos = 0 |
| 756 | while (filePos < fileSize) { |
| 757 | const { bytesRead } = await fd.read( |
| 758 | chunk, |
| 759 | 0, |
| 760 | Math.min(CHUNK_SIZE, fileSize - filePos), |
| 761 | filePos, |
| 762 | ) |
| 763 | if (bytesRead === 0) break |
| 764 | filePos += bytesRead |
| 765 | |
| 766 | const chunkOff = processStraddle(s, chunk, bytesRead) |
| 767 | |
| 768 | let buf: Buffer |
| 769 | if (s.carryLen > 0) { |
| 770 | const bufLen = s.carryLen + (bytesRead - chunkOff) |
| 771 | buf = Buffer.allocUnsafe(bufLen) |
| 772 | s.carryBuf!.copy(buf, 0, 0, s.carryLen) |
| 773 | chunk.copy(buf, s.carryLen, chunkOff, bytesRead) |
| 774 | } else { |
no test coverage detected