# Contributing to fastx
Thanks for looking. Bug reports with a reproducing file are as welcome as code.
## Getting set up
```bash
git clone https://github.com/ScioFuturum/fastx
cd fastx
cargo test --all-features
```
That runs unit tests, integration tests, CLI tests driven through the real
binary, property tests and doc tests — currently a bit over 150 of them.
On a memory-constrained machine the doc tests can exhaust the linker; run them
with less parallelism:
```bash
cargo test --all-features -j 1 --doc -- --test-threads=2
```
## Before opening a pull request
```bash
cargo fmt --all
cargo clippy --all-features --all-targets -- -D warnings
cargo test --all-features
```
CI additionally runs the MSRV check, `cargo deny`, coverage and a short fuzzing
smoke run, so those three commands are usually enough locally.
## What the tests are for
Each layer catches a different kind of mistake, so please add to the one that
fits rather than to whichever is most convenient:
- **Unit tests** (in each module) for behaviour you can state in one line, and
for every edge case you fixed. If you fix a bug, the test should fail before
your change.
- **Integration tests** (`tests/integration.rs`) for anything that touches real
files: round trips, gzip, indexing, path inference.
- **CLI tests** (`tests/cli.rs`) run the built binary. Exit codes and stderr are
part of the interface.
- **Property tests** (`tests/property.rs`) for invariants that must hold for all
inputs. These have already found a panic on non-ASCII headers and an
undocumented RNA asymmetry, so they earn their keep.
- **Fuzz targets** (`fuzz/`) need nightly:
```bash
cargo +nightly fuzz run reader
```
Commit any crash artifact that a fuzzer finds as a unit test.
## Benchmarks
```bash
cargo bench
```
Please include before/after numbers in the pull request for anything claiming to
be faster, and say what machine they came from. Beware that timings on a laptop
vary by tens of percent between runs — compare figures measured in the same
session, and prefer ratios to absolute numbers.
Note the profile that already exists: parsing runs at roughly 700 MiB/s and is
not the bottleneck for real workloads. gzip is. Optimisations to the parser need
to show that they matter end to end.
## House style
- `rustfmt` decides formatting; do not hand-align.
- Comments explain *why*, not *what*. If a line needs a comment to say what it
does, the line probably wants rewriting instead.
- Public items need doc comments — `#![deny(missing_docs)]` enforces it — and a
doc example if the signature alone is not obvious.
- No `unsafe`. `#![forbid(unsafe_code)]` is not up for negotiation; if something
genuinely needs it, that is a discussion for an issue first.
- Errors carry context: a line number, a record id, or the path involved.
- Never invent data to make an API convenient. A missing quality string is an
error, not a row of fabricated `I`s.
## MSRV
The library and the CLI build on Rust 1.74. Optional features inherit the MSRV of
their dependencies, and CI checks each at its own version:
| default features, and `--no-default-features` | 1.74 |
| `--features parallel` (rayon) | 1.80 |
| `--all-features` (the zstd and libdeflate C chains, `cc` → `jobserver`) | 1.85 |
Raising any of these is a minor-version change and needs a reason in the pull
request. Note that a feature's MSRV is not really ours to control: the C build
chains behind `zstd` and `libdeflate` move quickly, so that row will drift upward
on its own.
Note also that dead-code warnings are feature-specific, and CI builds with
`-D warnings`: a helper used only by a `cfg`-gated type is invisible with the
feature on and a build error with it off. The lint job therefore checks six
combinations, and it is worth running the same locally before pushing:
```bash
RUSTFLAGS="-D warnings" cargo clippy --all-targets
RUSTFLAGS="-D warnings" cargo clippy --all-features --all-targets
RUSTFLAGS="-D warnings" cargo clippy --no-default-features --all-targets
```
## Licence
Contributions are dual licensed under MIT and Apache-2.0, matching the crate.