.nornir/assets/zoomies_parsing.svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1180 680" 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>
</defs>
<!-- PCB substrate -->
<rect x="0" y="0" width="1180" height="680" fill="url(#board)"/>
<g stroke="#143a52" stroke-width="1">
<line x1="0" y1="76" x2="1180" y2="76"/>
<line x1="0" y1="632" x2="1180" y2="632"/>
</g>
<g fill="#16415c">
<circle cx="40" cy="40" r="2"/><circle cx="1140" cy="40" r="2"/>
<circle cx="40" cy="652" r="2"/><circle cx="1140" cy="652" r="2"/>
</g>
<!-- title -->
<text x="40" y="44" fill="#eaf6ff" font-size="22" font-weight="700">parsing flows</text>
<text x="248" y="44" fill="#9fc9e0" font-size="15">XML rides gatling typed-mode (decode → cut at <tspan fill="#bfe6ff" font-weight="700"></way></tspan> → encode) — JSON splits on raw <tspan fill="#bfe6ff" font-weight="700">\n</tspan></text>
<!-- legend -->
<g font-size="12.5">
<line x1="804" y1="60" x2="844" y2="60" stroke="#6fd3f5" stroke-width="3"/>
<text x="852" y="64" fill="#cfe6f5">gatling slot pointer</text>
<line x1="1006" y1="60" x2="1046" y2="60" stroke="#c9a0ff" stroke-width="3"/>
<text x="1054" y="64" fill="#cfe6f5">rayon (not gatling)</text>
</g>
<!-- ===================== XML FLOW (top band) ===================== -->
<rect x="36" y="100" width="1108" height="300" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<text x="60" y="128" fill="#eaf6ff" font-size="15" font-weight="700">OSM XML → PBF — gatling::run_typed (typed mode)</text>
<text x="60" y="148" fill="#86b3cc" font-size="11">osm-katana/src/xml_to_pbf.rs · split cuts at element boundaries, the worker decodes+parses+encodes, the sink stitches cross-cut stubs</text>
<!-- reader -->
<rect x="60" y="176" width="140" height="170" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="130" y="202" fill="#eaf6ff" font-size="12.5" font-weight="700" text-anchor="middle">Reader</text>
<text x="130" y="222" fill="#9fc9e0" font-size="9.5" text-anchor="middle">raw / .bz2 / .gz</text>
<text x="130" y="240" fill="#86b3cc" font-size="9" text-anchor="middle">fills slot, prepends</text>
<text x="130" y="254" fill="#86b3cc" font-size="9" text-anchor="middle">carry headroom</text>
<text x="130" y="276" fill="#a9d8ee" font-size="8.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">chunk 200 MiB</text>
<text x="130" y="290" fill="#a9d8ee" font-size="8.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">carry 32 MiB · 6 slots</text>
<rect x="200" y="252" width="6" height="8" fill="#6fd3f5"/>
<g stroke="#6fd3f5" stroke-width="3" fill="none"><path d="M200 256 H236"/></g>
<circle cx="236" cy="256" r="4" fill="#bfecff"/>
<!-- split -->
<rect x="236" y="186" width="170" height="150" rx="10" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2"/>
<text x="321" y="210" fill="#eaf6ff" font-size="12.5" font-weight="700" text-anchor="middle">split</text>
<text x="321" y="228" fill="#9fc9e0" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">xml_split_typed</text>
<text x="321" y="246" fill="#86b3cc" font-size="9" text-anchor="middle">find_safe_slot_end →</text>
<text x="321" y="260" fill="#86b3cc" font-size="9" text-anchor="middle">last complete element</text>
<text x="321" y="278" fill="#86b3cc" font-size="9" text-anchor="middle">cut N segs on top-level</text>
<text x="321" y="292" fill="#86b3cc" font-size="9" text-anchor="middle"><node> / <way> starts</text>
<text x="321" y="312" fill="#bfe6ff" font-size="9" text-anchor="middle">.bz2 → bit-range segs</text>
<text x="321" y="326" fill="#7fa8c4" font-size="8.5" text-anchor="middle">tail straddler → carry</text>
<g fill="#6fd3f5"><rect x="406" y="218" width="6" height="8"/><rect x="406" y="256" width="6" height="8"/><rect x="406" y="296" width="6" height="8"/></g>
<!-- workers -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M412 222 H452"/><path d="M412 260 H452"/><path d="M412 300 H452"/>
</g>
<g>
<rect x="452" y="200" width="220" height="44" rx="9" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2"/>
<text x="562" y="220" fill="#eaf6ff" font-size="11.5" font-weight="700" text-anchor="middle">worker (no barrier)</text>
<text x="562" y="236" fill="#9fc9e0" font-size="8.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">decode → VTD parse → PBF</text>
<rect x="452" y="250" width="220" height="44" rx="9" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2"/>
<text x="562" y="270" fill="#eaf6ff" font-size="11.5" font-weight="700" text-anchor="middle">worker</text>
<text x="562" y="286" fill="#9fc9e0" font-size="8.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">encode_decoded_to_pbf</text>
<rect x="452" y="300" width="220" height="44" rx="9" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2"/>
<text x="562" y="320" fill="#eaf6ff" font-size="11.5" font-weight="700" text-anchor="middle">worker N−1</text>
<text x="562" y="336" fill="#9fc9e0" font-size="8.5" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">→ PbfSegment + stubs</text>
</g>
<!-- no-barrier mark -->
<g>
<line x1="694" y1="196" x2="694" y2="348" stroke="#3c6a86" stroke-width="2" stroke-dasharray="3 7"/>
<g stroke="#ff7a7a" stroke-width="2.2" stroke-linecap="round">
<line x1="687" y1="264" x2="701" y2="278"/><line x1="701" y1="264" x2="687" y2="278"/>
</g>
</g>
<!-- arrows to sink -->
<g stroke="#6fd3f5" stroke-width="3" fill="none">
<path d="M672 222 H712 V262 H752"/><path d="M672 272 H752"/><path d="M672 322 H712 V282 H752"/>
</g>
<circle cx="752" cy="272" r="5" fill="#bfecff"/>
<!-- sink -->
<rect x="752" y="200" width="200" height="144" rx="11" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2.5"/>
<text x="852" y="224" fill="#eaf6ff" font-size="12.5" font-weight="700" text-anchor="middle">PbfTypedSink</text>
<text x="852" y="242" fill="#9fc9e0" font-size="9" text-anchor="middle">forwards blobs in</text>
<text x="852" y="256" fill="#bfe6ff" font-size="9" text-anchor="middle" font-weight="700">strict stream order</text>
<text x="852" y="276" fill="#86b3cc" font-size="9" text-anchor="middle">stitches cross-cut stub:</text>
<text x="852" y="290" fill="#86b3cc" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">[prev_stub, left_stub]</text>
<text x="852" y="308" fill="#86b3cc" font-size="9" text-anchor="middle">flush_stub() parses the</text>
<text x="852" y="322" fill="#86b3cc" font-size="9" text-anchor="middle">element straddling the cut</text>
<text x="852" y="338" fill="#7fa8c4" font-size="8.5" text-anchor="middle">finish() flushes the last stub</text>
<rect x="952" y="268" width="6" height="8" fill="#6fd3f5"/>
<g stroke="#6fd3f5" stroke-width="3" fill="none"><path d="M958 272 H1000"/></g>
<circle cx="1000" cy="272" r="4" fill="#bfecff"/>
<!-- writer -->
<rect x="1000" y="216" width="132" height="112" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="1066" y="240" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">writer</text>
<text x="1066" y="260" fill="#9fc9e0" font-size="9" text-anchor="middle">one thread</text>
<text x="1066" y="278" fill="#86b3cc" font-size="9" text-anchor="middle">PBF blobs out</text>
<text x="1066" y="298" fill="#7fa8c4" font-size="8.5" text-anchor="middle">.bz2 split is</text>
<text x="1066" y="310" fill="#7fa8c4" font-size="8.5" text-anchor="middle">BIT-granular</text>
<!-- ===================== JSON FLOW (lower band) ===================== -->
<rect x="36" y="420" width="1108" height="184" rx="12" fill="url(#rail)" stroke="#7fc8ea" stroke-width="2"/>
<text x="60" y="448" fill="#eaf6ff" font-size="15" font-weight="700">NDJSON record scan — <tspan fill="#c9a0ff">rayon</tspan>, NOT gatling</text>
<text x="60" y="468" fill="#86b3cc" font-size="11">src/json.rs · RFC 8259 §7: an unescaped <tspan font-family="'DejaVu Sans Mono', monospace" fill="#a9d8ee">\n</tspan> is illegal inside a JSON string, so every raw newline is a record boundary — no escape-state machine to split</text>
<rect x="60" y="492" width="140" height="90" rx="10" fill="url(#chip)" stroke="#5aa6cf" stroke-width="2"/>
<text x="130" y="518" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">&[u8] NDJSON</text>
<text x="130" y="538" fill="#9fc9e0" font-size="9" text-anchor="middle">borrowed input</text>
<text x="130" y="556" fill="#86b3cc" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">find_safe_split</text>
<text x="130" y="570" fill="#86b3cc" font-size="9" text-anchor="middle">cut on next \n</text>
<rect x="200" y="533" width="6" height="8" fill="#c9a0ff"/>
<g stroke="#c9a0ff" stroke-width="3" fill="none"><path d="M200 537 H240"/></g>
<circle cx="240" cy="537" r="4" fill="#e6d2ff"/>
<rect x="240" y="500" width="240" height="74" rx="10" fill="url(#chip)" stroke="#c9a0ff" stroke-width="2"/>
<text x="360" y="524" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">rayon into_par_iter</text>
<text x="360" y="542" fill="#9fc9e0" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">scan_records_parallel</text>
<text x="360" y="560" fill="#86b3cc" font-size="9" text-anchor="middle">each worker scans its \n-bounded slice</text>
<rect x="480" y="533" width="6" height="8" fill="#c9a0ff"/>
<g stroke="#c9a0ff" stroke-width="3" fill="none"><path d="M486 537 H526"/></g>
<circle cx="526" cy="537" r="4" fill="#e6d2ff"/>
<rect x="526" y="500" width="240" height="74" rx="10" fill="url(#chip)" stroke="#7fc8ea" stroke-width="2"/>
<text x="646" y="524" fill="#eaf6ff" font-size="12" font-weight="700" text-anchor="middle">per-record probe</text>
<text x="646" y="542" fill="#9fc9e0" font-size="9" text-anchor="middle" font-family="'DejaVu Sans Mono', monospace">find_key (zero-copy)</text>
<text x="646" y="560" fill="#86b3cc" font-size="9" text-anchor="middle">string-aware depth scan, no full parse</text>
<text x="800" y="528" fill="#7fa8c4" font-size="10.5">Why rayon here, gatling there: NDJSON records are independent & uniform —</text>
<text x="800" y="544" fill="#7fa8c4" font-size="10.5">no carry, no stream-order reassembly, no straddling-element stub to stitch.</text>
<text x="800" y="560" fill="#86b3cc" font-size="10.5">gatling earns its keep where a unit can straddle a chunk edge.</text>
<!-- ===================== GROUND RAIL ===================== -->
<rect x="36" y="618" width="1108" height="0" fill="none"/>
</svg>