.nornir/assets/lbzip2_readers_flow.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 660" font-family="'DejaVu Sans', 'Segoe UI', sans-serif">
<defs>
<linearGradient id="board" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#0b1c2e"/><stop offset="1" stop-color="#06111d"/></linearGradient>
<linearGradient id="chip" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#14384f"/><stop offset="1" stop-color="#0e2a3e"/></linearGradient>
<linearGradient id="rail" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#173d57"/><stop offset="1" stop-color="#0c2438"/></linearGradient>
<linearGradient id="slot" x1="0" y1="0" x2="0" y2="1"><stop offset="0" stop-color="#123448"/><stop offset="1" stop-color="#0a2032"/></linearGradient>
<marker id="ah" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="7" markerHeight="7" orient="auto-start-reverse"><path d="M0 0 L10 5 L0 10 z" fill="#6fd3f5"/></marker>
</defs>
<rect x="0" y="0" width="1180" height="660" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1"><line x1="0" y1="74" x2="1180" y2="74"/><line x1="0" y1="616" x2="1180" y2="616"/></g>
<g fill="#16415c"><circle cx="40" cy="38" r="2"/><circle cx="1140" cy="38" r="2"/></g>
<text x="40" y="42" fill="#eaf6ff" font-size="22" font-weight="700">lbzip2 readers</text>
<text x="248" y="42" fill="#9fc9e0" font-size="15">bzip2 library twins — parallel block-magic scan → self-dispatch BWT workers → in-order concat / <tspan fill="#bfe6ff" font-weight="700">Read</tspan> stream</text>
<g font-size="12"><line x1="800" y1="60" x2="840" y2="60" stroke="#6fd3f5" stroke-width="3" marker-end="url(#ah)"/><text x="846" y="64" fill="#cfe6f5">parallel dataflow</text></g>
<!-- INPUT -->
<rect x="34" y="250" width="140" height="150" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="104" y="276" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">bzip2 bytes</text>
<rect x="50" y="300" width="108" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="104" y="317" fill="#bfe6ff" font-size="8.6" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">&[u8] mmap/slice</text>
<rect x="50" y="332" width="108" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="104" y="349" fill="#bfe6ff" font-size="8.6" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">or Read source</text>
<text x="104" y="378" fill="#7fa8c4" font-size="9" text-anchor="middle">parallel.rs · reader.rs</text>
<!-- SCAN -->
<rect x="212" y="176" width="208" height="290" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="316" y="200" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">parallel block scan</text>
<text x="316" y="217" fill="#9fc9e0" font-size="10" text-anchor="middle">find_all_blocks_parallel</text>
<rect x="230" y="230" width="172" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="316" y="244" fill="#bfe6ff" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">split buf / n chunks</text>
<text x="316" y="255" fill="#9fc9e0" font-size="8.4" text-anchor="middle">+8-byte overlap per chunk</text>
<rect x="230" y="268" width="172" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="316" y="282" fill="#bfe6ff" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">gatling_for_each(n)</text>
<text x="316" y="293" fill="#9fc9e0" font-size="8.4" text-anchor="middle">64-bit window, 16-way bit check</text>
<rect x="230" y="306" width="172" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="316" y="320" fill="#bfe6ff" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">merge · sort · dedup</text>
<text x="316" y="331" fill="#9fc9e0" font-size="8.4" text-anchor="middle">by bit_offset</text>
<text x="316" y="356" fill="#7CFFB2" font-size="9.2" text-anchor="middle">== identical set to serial find_all_blocks</text>
<text x="316" y="372" fill="#86b3cc" font-size="9.2" text-anchor="middle">no 1-core serial magic-walk prefix</text>
<text x="316" y="396" fill="#ffcf6f" font-size="9" text-anchor="middle">streaming: hold back last block</text>
<text x="316" y="409" fill="#ffcf6f" font-size="9" text-anchor="middle">if !eof (may span next chunk)</text>
<text x="316" y="432" fill="#7fa8c4" font-size="9" text-anchor="middle">block_scan.rs:143 (magic 0x314159265359)</text>
<text x="316" y="450" fill="#7fa8c4" font-size="9" text-anchor="middle">FINAL_MAGIC + stream CRC: block_scan.rs:82</text>
<!-- WORKERS -->
<rect x="458" y="216" width="214" height="212" rx="12" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="565" y="240" fill="#eaf6ff" font-size="14.5" font-weight="700" text-anchor="middle">N workers</text>
<text x="565" y="257" fill="#9fc9e0" font-size="10" text-anchor="middle">gatling_for_each · no barrier</text>
<g font-family="'DejaVu Sans Mono',monospace">
<rect x="478" y="270" width="174" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="565" y="287" fill="#bfe6ff" font-size="9" text-anchor="middle">decode_segment_checked</text>
<rect x="478" y="302" width="174" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="565" y="319" fill="#bfe6ff" font-size="9" text-anchor="middle">Huffman→MTF→BWT⁻¹</text>
<rect x="478" y="334" width="174" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="565" y="351" fill="#bfe6ff" font-size="9" text-anchor="middle">per-block CRC-32</text>
</g>
<text x="565" y="382" fill="#86b3cc" font-size="9" text-anchor="middle">decompress_parallel: ~4 segs/thread,</text>
<text x="565" y="395" fill="#86b3cc" font-size="9" text-anchor="middle">1 growing buf/worker (no per-block Vec)</text>
<text x="565" y="416" fill="#7fa8c4" font-size="9" text-anchor="middle">chunk.rs:117 · block.rs</text>
<!-- ASSEMBLE -->
<rect x="710" y="216" width="196" height="212" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="808" y="240" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">in-order assemble</text>
<rect x="728" y="256" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="808" y="270" fill="#bfe6ff" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">concat by segment order</text>
<text x="808" y="281" fill="#9fc9e0" font-size="8.4" text-anchor="middle">only n_segments copies</text>
<rect x="728" y="294" width="160" height="30" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="808" y="308" fill="#bfe6ff" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">combined stream CRC</text>
<text x="808" y="319" fill="#9fc9e0" font-size="8.4" text-anchor="middle">rotl1 ^ per-block CRC</text>
<text x="808" y="346" fill="#ff9c9c" font-size="9" text-anchor="middle">mismatch ⇒ hard error</text>
<text x="808" y="366" fill="#86b3cc" font-size="9" text-anchor="middle">streaming: serve out_buf via read(),</text>
<text x="808" y="379" fill="#86b3cc" font-size="9" text-anchor="middle">keep undecoded tail in comp_buf</text>
<text x="808" y="402" fill="#7fa8c4" font-size="9" text-anchor="middle">parallel.rs:97 · reader.rs:150</text>
<!-- OUTPUT -->
<rect x="944" y="250" width="180" height="150" rx="11" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="1034" y="276" fill="#eaf6ff" font-size="14" font-weight="700" text-anchor="middle">output</text>
<rect x="962" y="296" width="144" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="1034" y="313" fill="#bfe6ff" font-size="8.6" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">Vec<u8> (parallel)</text>
<rect x="962" y="328" width="144" height="26" rx="5" fill="url(#slot)" stroke="#6fd3f5" stroke-width="1.4"/>
<text x="1034" y="345" fill="#bfe6ff" font-size="8.6" text-anchor="middle" font-family="'DejaVu Sans Mono',monospace">impl Read (stream)</text>
<text x="1034" y="374" fill="#7fa8c4" font-size="9" text-anchor="middle">bounded: 1 batch/chunk live</text>
<!-- FLOW -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M174 325 H210" marker-end="url(#ah)"/>
<path d="M420 320 H456" marker-end="url(#ah)"/>
<path d="M672 322 H708" marker-end="url(#ah)"/>
<path d="M906 322 H942" marker-end="url(#ah)"/>
</g>
<!-- ground rail -->
<rect x="212" y="560" width="912" height="44" rx="9" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<text x="230" y="580" fill="#dff1ff" font-size="12" font-weight="700">three twins</text>
<text x="230" y="596" fill="#bcd9ec" font-size="10">decompress_parallel (whole slice → Vec) · StreamingBz2Read (Read, 100 MB chunks) · ParallelBz2Read (mmap, 64-block batches) — all share find_all_blocks_parallel + gatling_for_each</text>
</svg>