dino-seq 0.1.0

Low-allocation FASTQ and FASTA parser core
Documentation
# Public API Surface

This document records the intended public surface for `dino_seq` `0.1.x`.
It is a release audit artifact, not a promise that the crate is frozen before
`1.0`. The purpose is to keep the first public release from accidentally
exporting implementation details that are hard to retract.

## Tier 1: Primary User Surface

These APIs are the default entry points for downstream scientific tools.

| API | Role | 0.1.x decision |
| --- | --- | --- |
| `FastqReader` | Borrowed batch reader over any `Read` source | Keep public |
| `FastqReader::count_records`, `count_fastq_read`, `count_fastq_bytes`, `FastqStats` | FASTQ count/total-bases/light-checksum paths without record view construction | Keep public |
| `FastqReader::visit_records`, `FastqVisitRecord` | Single-pass streaming visitor without batch side-table construction | Keep public |
| `FastqReader::next_chunk_with_sink`, `FastqRecordSink`, `FastqChunkSinkExt`, `FastqChunkConfig`, `FastqChunkStats` | Resumable chunk visitor for callers that fill their own output buffers and should not pay for Dino Seq batch side tables | Keep public |
| `visit_fastq_bytes` | Zero-copy visitor for complete resident FASTQ byte buffers | Keep public |
| `FastqBatch`, `FastqRecord`, `RecordRef` | Zero-copy record access within a reusable slab | Keep public |
| `FastqConfig` | Slab size, validation, and pairing configuration | Keep public |
| `open_fastq`, `open_fastq_with_config` | Convenience boxed file opener; raw by default, gzip/BGZF detection behind features | Keep public but do not steer raw hot paths here |
| `FastaReader`, `FastaBatch`, `FastaRecord`, `FastaRecordRef` | Streaming multiline FASTA batches over any `Read` source | Keep public |
| `FastaConfig` | FASTA batch, input-buffer, and sequence-length hint configuration | Keep public |
| `FastaConfig::reference` | Named parser tuning for chromosome-scale reference FASTA records | Keep public |
| `visit_fasta_bytes` | Zero-copy resident FASTA visitor with multiline folding fallback | Keep public |
| `visit_fasta_bytes_auto`, `detect_fasta_shape`, `FastaShape` | Resident FASTA shape detection and automatic strict two-line dispatch | Keep public |
| `visit_two_line_fasta_bytes`, `visit_two_line_fasta_read` | Strict `>header`/`sequence` fast paths for canonical two-line FASTA | Keep public |
| `FastaReader::stats`, `count_fasta_read`, `count_fasta_bytes`, `FastaStats` | Robust multiline FASTA count/total-bases/light-checksum paths | Keep public |
| `count_two_line_fasta_bytes`, `count_two_line_fasta_read` | Strict two-line FASTA count/total-bases/light-checksum fast paths | Keep public |
| `FastaRecordSink`, `FastaVisitRecord` | Borrowed FASTA visitor sink and record view | Keep public |
| `OwnedFastaBatch`, `OwnedFastaRecord` | Transferable owned FASTA batches derived from borrowed parser slabs | Keep public |
| `open_fasta`, `open_fasta_with_config` | Convenience boxed file opener; raw by default, gzip/BGZF detection behind features | Keep public but do not steer raw hot paths here |
| `open_fasta_for_reference` | File-path opener using `FastaConfig::reference` for long reference records | Keep public |
| `open_fastq_gzip_libdeflate*`, `open_fasta_gzip_libdeflate*`, `LibdeflateGzipLimits` | Explicit bounded buffered single-member gzip openers through the third-party `libdeflater` wrapper | Keep public behind `gzip-libdeflate` (`gzip` + `libdeflate`) |
| `PairedFastqReader`, `PairedFastqBatch`, `FastqPair` | Ordered paired-end streaming | Keep public |
| `open_paired_fastq*` | Paired file opener variants | Keep public |
| `PairingMode`, `PairValidation`, `strip_pair_suffix` | Explicit ordered-pair validation semantics | Keep public |
| `FastqError`, `FastqPosition`, `Result` | Typed error reporting | Keep public |

Rationale: these are the crate's core value proposition. They expose borrowed
FASTQ and FASTA batches without imposing a workflow, allocator, or owned record
model.

Performance-sensitive downstream integrations should use the narrowest surface
that matches the work they actually need. Batch APIs are for callers that need
record side tables. `count_records` and `count_fastq_*` are for count/stat
consumers that do not need record views. `visit_records` is for whole-stream
one-pass consumers. `next_chunk_with_sink` is for pipeline stages such as
aligners that need bounded chunks in caller-owned output structures and should
not pay for intermediate owned records or a Dino Seq batch table. If a sink
returns an error, the reader returns that error immediately and should be
dropped rather than reused, because the sink may already contain records from
the partial chunk.

`FastqChunkConfig` and `FastqChunkStats` are marked non-exhaustive and expose
accessors so downstream tools do not need to construct or destructure them by
field. The `examples/fastq_chunk_sink.rs` example shows the intended adoption
shape for filling owned downstream records while reusing caller allocations.

Compression backends are not owned by dino_seq. The default crate has no
compression dependency. `gzip`, `bgzf`, and `transport` are explicit opt-ins,
and `libdeflate` remains a third-party C-backed opt-in through the
`libdeflater` wrapper. The `gzip-libdeflate` convenience feature enables both
`gzip` and `libdeflate` for explicit buffered single-member gzip openers. Dino
Seq owns the parser APIs, BGZF orchestration, backend-selection surface, and
benchmark labels around those engines.

Unsafe code should stay limited to low-level systems integration points such as
memory mapping and SIMD pack kernels. The default raw parser path should remain
dependency-light and require no unsafe code from callers.

## Tier 2: Advanced But Intentional Surface

These APIs are lower level, but they are still part of the intended scientific
systems surface because they let downstream tools avoid reparsing or
reallocating.

| API | Role | 0.1.x decision |
| --- | --- | --- |
| `pack::pack_bases`, `pack_bases_into`, `pack_bases_into_slices` | Two-bit base packing | Keep public |
| `pack::packed_base_at`, `is_masked` | Decode/access packed bases and ambiguity mask | Keep public |
| `pack::summarize_qualities`, `bin_qualities_into*` | Phred+33 summaries and bins | Keep public |
| `pack::PackedSequence`, `BaseSummary`, `QualitySummary`, `PackedRecordSummary` | Data carriers for packed side channels | Keep public |
| `pack::TrustedPackSink`, `TrustedPackedRecord`, `TrustedPackedPair`, `TrustedPackSlab` | Callback surface for streaming pack paths | Keep public with "trusted FASTQ" naming |
| `pack::pack_trusted_fastq*` | High-throughput four-line pack paths | Keep public with explicit trusted-input contract |
| `pack::selected_pack_kernel`, `PackKernel` | Build/host pack-kernel introspection | Keep public |

Rationale: the pack module is not a private optimization. It is a separable
side-channel API for tools that need compact base representation, ambiguity
masks, and quality summaries. The unsafe-looking part is semantic, not memory
unsafe: "trusted" means ordinary four-line FASTQ shape has already been chosen
as a workload contract. Public docs and benchmark text must keep that boundary
visible.

## Tier 3: Transport And Format Surface

These APIs make BGZF a first-class transport instead of hiding it behind file
auto-detection.

| API | Role | 0.1.x decision |
| --- | --- | --- |
| `BgzfReader`, `BgzfAutoReader`, `BgzfParallelReader` | Serial, adaptive, and bounded parallel BGZF decode | Keep public |
| `BgzfDecodedBlockReader`, `BgzfDecodedBlock` | Block-aware decoded streaming with compressed and uncompressed offsets | Keep public for indexing/reference builders |
| `BgzfWriter`, `BGZF_EOF_BLOCK` | BGZF output support | Keep public |
| `BgzfInflateBackend`, `BgzfDeflateBackend` | Backend selection when `libdeflate` is enabled | Keep public |
| `BgzfParallelConfig`, `BgzfPipelineMetrics*` | Parallel threshold, queue, backend, and backpressure tuning | Keep public |
| `BgzfVirtualOffset`, `BgzfIndex`, `BgzfIndexEntry`, `build_bgzf_index`, `build_bgzf_index_strict` | Seek/index support, including optional canonical EOF-marker validation | Keep public |
| `DetectedInputKind`, `detect_file_input_kind` | Shared raw/gzip/BGZF file-magic detection for tools | Keep public |
| `FastaIndex`, `FastaIndexEntry`, `build_fasta_index`, `build_fasta_index_bgzf` | `.fai`-style FASTA reference indexing, with BGZF sequence-start virtual offsets when `bgzf` is enabled | Keep public |
| `IndexedFastaReader`, `BgzfIndexedFastaReader` | `.fai`/BGZF-backed zero-based half-open reference range fetching and chunk streaming | Keep public |
| `FastaPartition`, `FastaPartitionConfig`, `plan_fasta_partitions` | Deterministic reference-contig partition planning with optional overlap for parallel callers | Keep public |
| `FastaReferenceChunk`, `FastaReferenceChunks`, `BgzfFastaReferenceChunks` | Owned reference-range chunk streaming from indexed raw/BGZF FASTA readers | Keep public |
| `FastaReferenceChunkRef`, `FastaReferenceChunkSink` | Borrowed reference chunk sink API for callers that provide reusable output buffers | Keep public |
| `IndexedFastaReader::reference_chunks`, `BgzfIndexedFastaReader::reference_chunks` | Chunked owned sequence iteration over zero-based half-open reference ranges | Keep public |
| `IndexedFastaReader::reference_chunks_into`, `BgzfIndexedFastaReader::reference_chunks_into` | Borrowed chunk streaming into caller-owned buffers | Keep public |
| `IndexedFastaReader::fetch_partition`, `BgzfIndexedFastaReader::fetch_partition` | Fetch planned `FastaPartition` ranges as owned `FastaReferenceChunk` values | Keep public |
| `visit_fastq_mmap`, `count_fastq_mmap`, `visit_fasta_mmap`, `count_fasta_mmap` | Optional resident file visitors and counters behind `mmap` | Keep public behind feature |
| `open_fastq_bgzf_*` | Explicit BGZF openers for callers that need transport control | Keep public |
| `compress_bgzf_parallel*`, `decompress_bgzf_parallel*` | Whole-buffer helpers for controlled conversions | Keep public, but not the main streaming path |

Rationale: BGZF is common enough in bioinformatics that downstream users need
explicit knobs for backend choice, seek/index behavior, and bounded parallelism.
The public docs should steer raw performance consumers toward
`FastqReader<File>` / `FastaReader<File>`, ordinary convenience consumers toward
`open_fastq` / `open_fasta`, and advanced users toward explicit BGZF APIs only
when they need transport control.

## Hidden Or Internal Surface

Internal parser scanners, slab framing helpers, benchmark helpers, and BGZF
worker plumbing remain private. New public exports should be added only when a
downstream caller can state a concrete use case that cannot be served by the
existing batch, pack, or transport tiers.

The previous generic `FastaBatchSource`, `FastqBatchSource`, and
`FastqPairBatchSource` traits were removed before `0.1.0`. Each had one local
implementation and added a public abstraction layer without improving the hot
path.

## Risks To Revisit Before 1.0

- Keep the core crate centered on FASTQ/FASTA parser adoption. The pack module,
  BGZF indexing, FASTA reference partitioning, mmap visitors, and explicit
  transport knobs should remain only while they have real downstream callers.
  If they start expanding independently, move them behind narrower features or
  into sibling crates before `1.0`.
- `RecordRef` exposes raw byte ranges. This is valuable for zero-copy callers,
  but a future 1.0 API may prefer an opaque view if range layout changes.
- Trusted pack functions assume ordinary four-line FASTQ. They are useful and
  benchmarked, but public examples must not imply multiline FASTQ support.
- FASTA support is intentionally parser-only in `0.1.x`: no quality summaries,
  paired validation, or trusted FASTQ pack APIs apply to FASTA records.
- `FastaConfig::reference` is a named preset, not a new parser mode. Before
  `1.0`, revisit whether reference tuning should stay as fixed constants or
  grow into workload-specific presets.
- Owned FASTA batches and reference chunks copy sequence bytes by design so
  callers can transfer work across threads or partition boundaries. They should
  not replace borrowed `FastaBatch` in the primary streaming examples.
- The `visit_two_line_fasta_*` and `count_two_line_fasta_*` functions are
  deliberately strict fast paths for canonical two-line FASTA. Use
  `FastaReader`, `FastaReader::stats`, `count_fasta_read`,
  `count_fasta_bytes`, or `visit_fasta_bytes` for ordinary multiline FASTA.
- `build_fasta_index` follows `.fai` wrapping constraints and reports
  uncompressed offsets. `FastaIndex::from_fai_*` parses five-column `.fai`
  sidecars. `IndexedFastaReader` fetches uncompressed FASTA ranges, while
  `BgzfIndexedFastaReader` combines `.fai` math with `BgzfIndex` so arbitrary
  BGZF range starts use the correct virtual offset rather than only the
  sequence-start offset.
- `FastaPartition` planning uses byte-owned sequence names and zero-based
  half-open ranges. Before `1.0`, revisit whether partition naming and overlap
  policy need stronger type wrappers for large parallel reference workflows.
- Whole-buffer BGZF helpers are convenient for fixtures and conversions, but
  large production workflows should prefer streaming readers/writers.
- Explicit `libdeflate` gzip openers buffer compressed and decompressed data by
  design, enforce caller-visible limits, and reject concatenated gzip members
  rather than silently undercounting relative to the default streaming gzip
  opener.
- `PairValidation::FastSlash` is intentionally fast and narrow. Broader naming
  conventions should be modeled as new explicit validation modes, not hidden
  behavior changes.

## Release Decision

For `0.1.0`, keep the default crate centered on raw parsing. Compression,
mmap, SIMD, libdeflate, and gzip-libdeflate are explicit features. The public
surface is still broader than a parser-only crate because it includes pairing,
packed side channels, indexing, and BGZF transport, but README, rustdoc, and
benchmark prose should keep raw `FastqReader<File>` / `FastaReader<File>` paths
as the performance story.