metrale_circuit/venn/
cli_args.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! 2026-09-29: The report's runs and regenerating command, from the `met circuit venn`
4//! arguments. Here, not in the CLI, so the CLI and the tests that check a report is current build
5//! the same header from the same arguments.
6//!
7//! Owner: metrale-circuit (venn).
8//! Invariants: decode and draft plan one row; multi_seq plans every requested count above one;
9//! verify plans the requested K. A mode left with no row count is an error, never skipped.
10
11use super::{Run, VennError};
12use crate::rules::Mode;
13
14/// 2026-09-29: What the CLI was asked for.
15#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct VennArgs {
17    /// 2026-09-29: `--target`, as given.
18    pub target: String,
19    /// 2026-09-29: `--against`, in order.
20    pub against: Vec<String>,
21    /// 2026-09-29: `--mode`, in order.
22    pub modes: Vec<Mode>,
23    /// 2026-09-29: `--rows`: the concurrency rungs.
24    pub rows: Vec<u64>,
25    /// 2026-09-29: `--verify-rows`: K for the MTP verify.
26    pub verify_rows: Vec<u64>,
27    /// 2026-09-29: `--out`, repo-relative.
28    pub out: String,
29}
30
31impl VennArgs {
32    /// 2026-09-29: The runs, in mode then row order.
33    pub fn runs(&self) -> Result<Vec<Run>, VennError> {
34        let mut out = Vec::new();
35        for &mode in &self.modes {
36            let rows: Vec<u64> = match mode {
37                Mode::Decode | Mode::Draft => vec![1],
38                Mode::MultiSeq => self.rows.iter().copied().filter(|&r| r > 1).collect(),
39                Mode::Verify => self.verify_rows.clone(),
40                // 2026-09-30: A batched verify is planned for a row table, which the Venn does
41                // not take.
42                Mode::VerifyBatch => {
43                    return Err(VennError::Run(
44                        "--mode verify_batch is not classified (its plans take a row table)".into(),
45                    ));
46                }
47            };
48            if rows.is_empty() || rows.contains(&0) {
49                return Err(VennError::Run(format!(
50                    "--mode {} has no row count to plan (multi_seq takes --rows above 1, verify --verify-rows)",
51                    mode.name()
52                )));
53            }
54            out.extend(rows.into_iter().map(|rows| Run { mode, rows }));
55        }
56        Ok(out)
57    }
58
59    /// 2026-09-29: The command line that regenerates the report.
60    pub fn command(&self) -> String {
61        let join = |v: &[u64]| v.iter().map(u64::to_string).collect::<Vec<_>>().join(",");
62        let modes: Vec<&str> = self.modes.iter().map(|m| m.name()).collect();
63        format!(
64            "met circuit venn --target {} --against {} --mode {} --rows {} --verify-rows {} --out {}",
65            self.target,
66            self.against.join(","),
67            modes.join(","),
68            join(&self.rows),
69            join(&self.verify_rows),
70            self.out
71        )
72    }
73}