The compiled Rust binary is both the product and the test subject — every differential harness in this project drives it through these same six subcommands.
printf 'file10\nfile2\nfile1\n' | natsort_port sort
file1, file2, file10 — one per linenatsort_port compare num2 num10
-1 (num2 sorts before num10)natsort_port key "a-5.034e2"
T:a- I:5 T:. I:34 T:e I:2Each token is T:ext,
I:nteger, or R:eal (float) — tab-separated so a caller can rebuild
the tuple exactly (this is how the differential harnesses compare keys byte-for-byte against
Python's natsort_keygen()).
printf 'Banana\napple\nCherry\n' | natsort_port os-sort
apple, Banana, CherryUsed internally by the Python test harnesses — batch mode avoids spawning one process per comparison.
printf 'real\t1.10\t1.2\n' | natsort_port batch-sort
flagspec item1 item2 ...This is what fuzz_harness.py,
fuzz_60s.py, and the adapter's natsorted() shim call — thousands of
comparisons without the ~1ms process-spawn cost each.
natsort_port bench 50000
Called by bench.py,
which wraps it with /usr/bin/time -v for peak RSS and computes p50/p95/p99 across
multiple runs.
Appended to sort,
compare, or key. Omit for the default (INT).
--realSigned floats: "1.10" parses as 1.1, not text-then-10--signedA leading +/- attaches to the following number--floatUnsigned floats--ignorecaseFold case before comparing (uses casefold, not lowercase)--lowercasefirstSwap the case of every letter before comparing--grouplettersExpand each letter to casefold(c) + c--noexpUnder REAL/FLOAT, don't treat e/E + digits as an exponent -- "1e5" stays 1.0, "e", 5.0--presortPre-sort lexicographically first, so ties in the natural key break by string order, not input orderbatch-sort takes the same
flags as comma-separated words in the line's first field instead: real,ignorecase.