feat: enforce runtime validation for kmer and minimizer parameters
Introduces `CommonArgs::validate()` to enforce strict constraints on `--kmer-size` (odd, 11–31), `--minimizer-size` (odd, 3–k−1), and `z` (strictly less than k). This validation is applied at the entry point of the `superkmer` and `index` commands to prevent invalid configurations, avoid palindromes, prevent u64 overflow, and ensure positive effective indexing sizes. Documentation is updated to reflect these runtime checks and immediate termination on invalid input.
This commit is contained in:
@@ -63,6 +63,29 @@ pub fn block_size_to_bits(n: usize) -> u8 {
|
||||
}
|
||||
|
||||
impl CommonArgs {
|
||||
/// Validate k and m constraints. Exits on error.
|
||||
pub fn validate(&self) {
|
||||
let k = self.kmer_size;
|
||||
let m = self.minimizer_size;
|
||||
|
||||
if k < 11 || k > 31 {
|
||||
eprintln!("error: --kmer-size must be in [11, 31] (got {k})");
|
||||
std::process::exit(1);
|
||||
}
|
||||
if k % 2 == 0 {
|
||||
eprintln!("error: --kmer-size must be odd (got {k}); even k allows palindromic k-mers");
|
||||
std::process::exit(1);
|
||||
}
|
||||
if m < 3 || m >= k {
|
||||
eprintln!("error: --minimizer-size must be in [3, k−1] = [3, {}] (got {m})", k - 1);
|
||||
std::process::exit(1);
|
||||
}
|
||||
if m % 2 == 0 {
|
||||
eprintln!("error: --minimizer-size must be odd (got {m})");
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn seqfile_paths(&self) -> obiread::PathIter {
|
||||
let paths: Vec<PathBuf> = if self.inputs.is_empty() {
|
||||
vec![PathBuf::from("-")]
|
||||
|
||||
@@ -152,12 +152,23 @@ pub(crate) fn resolve_approx_params(
|
||||
}
|
||||
|
||||
pub fn run(args: IndexArgs) {
|
||||
args.common.validate();
|
||||
|
||||
let output = args.output.clone();
|
||||
let mut rep = Reporter::new();
|
||||
|
||||
// ── Resolve evidence kind ────────────────────────────────────────────────
|
||||
let evidence = if args.approx {
|
||||
let (z, b, fp) = resolve_approx_params(args.findere_z, args.evidence_bits, args.fp);
|
||||
let k = args.common.kmer_size;
|
||||
if z as usize >= k {
|
||||
eprintln!(
|
||||
"error: Findere z={z} must be < kmer-size={k} \
|
||||
(effective kmer size k−z+1 = {} ≤ 0)",
|
||||
k as isize - z as isize + 1
|
||||
);
|
||||
std::process::exit(1);
|
||||
}
|
||||
info!("approximate evidence: b={b}, z={z}, fp={fp:.2e}");
|
||||
IndexMode::Approx { b, z }
|
||||
} else {
|
||||
|
||||
@@ -33,6 +33,8 @@ fn write_batch(
|
||||
// ── Entry point ───────────────────────────────────────────────────────────────
|
||||
|
||||
pub fn run(args: SuperkmerArgs) {
|
||||
args.common.validate();
|
||||
|
||||
let k = args.common.kmer_size;
|
||||
let m = args.common.minimizer_size;
|
||||
let theta = args.common.theta;
|
||||
|
||||
Reference in New Issue
Block a user