Skip to content

Integer Type Audit

Status Applies to Owner
Enforced audit main branch as of 2026-07-10 Rust, PyO3, and JAX integer surfaces Native runtime maintainers

This page records the current native integer surfaces and the intended type for each category. Keep it in sync when changing native input/output contracts, reader APIs, manifests, or buffer ownership.

Current Type Map

Surface Current type Classification Decision
ChunkSpec.variant_start_index, ChunkSpec.variant_stop_index usize Memory index/range Keep usize.
BGEN sample_count, variant_count usize after header parse Memory count Keep usize; BGEN header u32 is checked during parse.
BGEN and aligned sample selection indices usize internally Memory index Keep native; sample-selection indices do not cross PyO3.
BGEN variant metadata positions Vec<i64> Genomic position/output metadata Keep fixed-width i64.
BGEN file offsets and block lengths parser-local checked integers File format offsets/lengths Keep checked before indexing mmap data.
ChunkStats count columns Vec<i32> Native/JAX/output count contract Keep i32; run preflight bounds the contributing sample count.
Output run manifest chunk identifiers and variant ranges i64 JSON/manifest schema Keep fixed-width i64; convert from usize with checked helpers.
Output writer row counts usize internally, manifest JSON fixed-width Memory count and schema field Keep usize internally; convert when serializing/resuming.
Runtime exit codes i32 Process contract Keep i32.
JAX loop limits and candidate capacities u32 in host configuration/RunPlan, checked i32 at PyO3 Host-to-device integer contract Preserve the unsigned host domain; validate and convert before Python exposure.
JAX indices and count reductions explicit jnp.int32 Device index/count contract Keep int32 even with JAX x64 enabled; reject shapes and products above the domain.
Materialization trait indices checked Vec<i32> at PyO3 Python/JAX boundary Convert from engine usize at the binding edge.
Telemetry counters usize internally, checked u64 when emitted JSON/tracing boundary Keep host counters internal and serialize nonnegative fixed-width snapshots.
BGEN decoded genotype allocation OwnedGenotypeBuffer containing Vec<f32> or pooled Vec<u8> ownership Rust ownership boundary Move typed ownership; do not introduce pointer-sized interchange.

Boundary Decisions

Internal genotype reader and input alignment APIs use usize for memory indices. The binding converts engine-owned active trait indices to checked i32 values when constructing the materialization request; no pointer-sized integer crosses PyO3.

Owned BGEN decode returns a DecodedGenotypeBatch. Its genotype allocation is a typed vector owned directly or through PooledPacked8Buffer; the decoder initializes reserved spare capacity and publishes the vector length only after complete success. The API exposes neither an allocation address nor a pointer-sized value count.

Enforcement Notes

Workspace Clippy denies truncating, wrapping, and sign-losing casts. The integer cast checker is active through check_rust_architecture. Current audited exceptions live in tooling/debug/integer_cast_allowlist.txt.

When a new cast is proposed, classify it as one of:

  • slice-derived SIMD or raw-pointer work, which must stay inside an audited unsafe implementation and must not be converted to an integer;
  • float-to-float or float-to-integer conversion required by numerical code;
  • SIMD lane extraction or mask count conversion;
  • benchmark/test fixture setup;
  • boundary conversion that should move to a helper.

Only the last category should be changed mechanically. Test-only casts may stay local to tests.rs; production and benchmark code should use checked conversion unless the cast is audited.

These cast checks do not detect structural boundary mistakes such as a new serialized usize. Review must still inspect Serde, tracing, PyO3, NumPy, and JAX integer surfaces against this table.

Compact Index Buffers

No compact u32 index buffer is introduced by this audit. The current large sample-selection surfaces use usize, which matches Rust slice indexing and avoids per-access conversion. A compact representation can be added only after a benchmark shows a material decode, preprocess, cache, memory-bandwidth, or end-to-end throughput benefit.

The remaining candidate surface for a future benchmark is large sample-selection arrays.