use clap::{Args, Parser, Subcommand, ValueEnum};
#[derive(Parser, Debug)]
#[command(
name = "pathrex",
about = "RPQ evaluator and benchmarking tool for edge-labeled graphs"
)]
pub struct Cli {
#[command(subcommand)]
pub command: Commands,
}
#[derive(Subcommand, Debug)]
pub enum Commands {
Query(QueryArgs),
Bench(BenchArgs),
}
#[derive(Args, Debug)]
pub struct CommonArgs {
#[arg(short = 'g', long)]
pub graph: String,
#[arg(short = 'f', long, value_enum, default_value_t = GraphFormat::Mm)]
pub format: GraphFormat,
#[arg(short = 'q', long)]
pub queries: String,
#[arg(
short = 'b',
long,
num_args = 0..=1,
default_missing_value = "http://example.org/",
require_equals = false
)]
pub base_iri: Option<String>,
#[arg(short = 'a', long, value_enum, num_args = 1.., required = true)]
pub algo: Vec<Algo>,
}
#[derive(Args, Debug)]
pub struct QueryArgs {
#[command(flatten)]
pub common: CommonArgs,
#[arg(short = 'o', long)]
pub output: Option<String>,
}
#[derive(Args, Debug)]
pub struct BenchArgs {
#[command(flatten)]
pub common: CommonArgs,
#[arg(short = 'o', long, default_value = "bench_results.json")]
pub output: String,
#[arg(short = 'c', long, default_value = "bench_checkpoint.json")]
pub checkpoint: String,
#[arg(long)]
pub resume: bool,
#[arg(long)]
pub criterion_dir: Option<String>,
#[arg(long)]
pub plots: bool,
#[arg(long, default_value_t = 10)]
pub sample_size: usize,
#[arg(long, default_value_t = 1)]
pub warm_up: u64,
#[arg(long, default_value_t = 5)]
pub measurement: u64,
}
#[derive(Debug, Clone, PartialEq, Eq, Hash, ValueEnum, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "lowercase")]
#[value(rename_all = "lowercase")]
pub enum Algo {
NfaRpq,
Rpqmatrix,
}
impl std::fmt::Display for Algo {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Algo::NfaRpq => write!(f, "nfarpq"),
Algo::Rpqmatrix => write!(f, "rpqmatrix"),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, ValueEnum)]
#[value(rename_all = "lowercase")]
pub enum GraphFormat {
Mm,
Csv,
Rdf,
}
impl std::fmt::Display for GraphFormat {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GraphFormat::Mm => write!(f, "mm"),
GraphFormat::Csv => write!(f, "csv"),
GraphFormat::Rdf => write!(f, "rdf"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
#[test]
fn query_requires_at_least_one_algo() {
let result = Cli::try_parse_from([
"pathrex",
"query",
"--graph",
"graph",
"--queries",
"queries",
]);
assert!(result.is_err());
}
}