Skip to content

Commit e9cebad

Browse files
committed
refactored the CLI
1 parent 1321752 commit e9cebad

30 files changed

+535
-268
lines changed

src/cli/optimize_codes.rs renamed to src/cli/analyze/codes.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,13 @@ use dsi_progress_logger::prelude::*;
1313
use lender::*;
1414
use std::path::PathBuf;
1515

16-
pub const COMMAND_NAME: &str = "optimize-codes";
16+
pub const COMMAND_NAME: &str = "codes";
1717

1818
#[derive(Args, Debug)]
1919
#[command(about = "Reads a graph and suggests the best codes to use.", long_about = None)]
2020
pub struct CliArgs {
2121
/// The basename of the graph.
22-
basename: PathBuf,
22+
pub src: PathBuf,
2323
}
2424

2525
pub fn cli(command: Command) -> Command {
@@ -29,7 +29,7 @@ pub fn cli(command: Command) -> Command {
2929
pub fn main(submatches: &ArgMatches) -> Result<()> {
3030
let args = CliArgs::from_arg_matches(submatches)?;
3131

32-
match get_endianness(&args.basename)?.as_str() {
32+
match get_endianness(&args.src)?.as_str() {
3333
#[cfg(any(
3434
feature = "be_bins",
3535
not(any(feature = "be_bins", feature = "le_bins"))
@@ -49,7 +49,7 @@ where
4949
for<'a> BufBitReader<E, MemWordReader<u32, &'a [u32]>>: CodeRead<E> + BitSeek,
5050
{
5151
// TODO!: speed it up by using random access graph if possible
52-
let graph = BVGraphSeq::with_basename(args.basename)
52+
let graph = BVGraphSeq::with_basename(args.src)
5353
.endianness::<E>()
5454
.load()?
5555
.map_factory(StatsDecoderFactory::new);

src/cli/analyze/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Tommaso Fontana
3+
*
4+
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5+
*/
6+
7+
use anyhow::Result;
8+
use clap::{ArgMatches, Command};
9+
10+
pub mod codes;
11+
12+
pub const COMMAND_NAME: &str = "analyze";
13+
14+
pub fn cli(command: Command) -> Command {
15+
let sub_command = Command::new(COMMAND_NAME)
16+
.about("Compute statistics on a BVGraph.")
17+
.subcommand_required(true)
18+
.arg_required_else_help(true)
19+
.allow_external_subcommands(true);
20+
let sub_command = codes::cli(sub_command);
21+
command.subcommand(sub_command)
22+
}
23+
24+
pub fn main(submatches: &ArgMatches) -> Result<()> {
25+
match submatches.subcommand() {
26+
Some((codes::COMMAND_NAME, sub_m)) => codes::main(sub_m),
27+
Some((command_name, _)) => {
28+
eprintln!("Unknown command: {:?}", command_name);
29+
std::process::exit(1);
30+
}
31+
None => {
32+
eprintln!("No command given for analyze");
33+
std::process::exit(1);
34+
}
35+
}
36+
}

src/cli/bench/bf_visit.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ pub const COMMAND_NAME: &str = "bf-visit";
2121
#[command(about = "Breadth-first visits a graph.", long_about = None)]
2222
struct CliArgs {
2323
/// The basename of the graph.
24-
basename: PathBuf,
24+
pub src: PathBuf,
2525
/// Static dispatch (default BVGraph parameters).
2626
#[arg(short = 's', long = "static")]
27-
_static: bool,
27+
pub _static: bool,
2828
/// Static dispatch (default BVGraph parameters).
2929
#[arg(short = 'r', long, default_value_t = 1)]
30-
repeats: usize,
30+
pub repeats: usize,
3131
}
3232

3333
pub fn cli(command: Command) -> Command {
@@ -37,12 +37,12 @@ pub fn cli(command: Command) -> Command {
3737
pub fn main(submatches: &ArgMatches) -> Result<()> {
3838
let args = CliArgs::from_arg_matches(submatches)?;
3939

40-
let config = BVGraph::with_basename(&args.basename)
40+
let config = BVGraph::with_basename(&args.src)
4141
.mode::<Mmap>()
4242
.flags(MemoryFlags::TRANSPARENT_HUGE_PAGES | MemoryFlags::RANDOM_ACCESS);
4343

4444
for _ in 0..args.repeats {
45-
match get_endianness(&args.basename)?.as_str() {
45+
match get_endianness(&args.src)?.as_str() {
4646
#[cfg(any(
4747
feature = "be_bins",
4848
not(any(feature = "be_bins", feature = "le_bins"))

src/cli/bench/bvgraph.rs

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,31 +23,31 @@ pub const COMMAND_NAME: &str = "bvgraph";
2323
#[command(about = "Benchmarks the Rust BVGraph implementation.", long_about = None)]
2424
struct CliArgs {
2525
/// The basename of the graph.
26-
basename: PathBuf,
26+
pub src: PathBuf,
2727

2828
/// Perform a random-access test on this number of randomly chosen nodes.
2929
#[arg(short, long)]
30-
random: Option<usize>,
30+
pub random: Option<usize>,
3131

3232
/// The number of repeats.
3333
#[arg(short = 'R', long, default_value = "10")]
34-
repeats: usize,
34+
pub repeats: usize,
3535

3636
/// In random-access test, test just access to the first successor.
3737
#[arg(short = 'f', long)]
38-
first: bool,
38+
pub first: bool,
3939

4040
/// Static dispatch for speed tests (default BVGraph parameters).
4141
#[arg(short = 's', long = "static")]
42-
_static: bool,
42+
pub _static: bool,
4343

4444
/// Test sequential high-speed offset/degree scanning.
4545
#[arg(short = 'd', long)]
46-
degrees: bool,
46+
pub degrees: bool,
4747

4848
/// Do not test speed, but check that the sequential and random-access successor lists are the same.
4949
#[arg(short = 'c', long)]
50-
check: bool,
50+
pub check: bool,
5151
}
5252

5353
pub fn cli(command: Command) -> Command {
@@ -57,7 +57,7 @@ pub fn cli(command: Command) -> Command {
5757
pub fn main(submatches: &ArgMatches) -> Result<()> {
5858
let args = CliArgs::from_arg_matches(submatches)?;
5959

60-
match get_endianness(&args.basename)?.as_str() {
60+
match get_endianness(&args.src)?.as_str() {
6161
#[cfg(any(
6262
feature = "be_bins",
6363
not(any(feature = "be_bins", feature = "le_bins"))
@@ -137,11 +137,9 @@ where
137137
for<'a> BufBitReader<E, MemWordReader<u32, &'a [u32]>>: CodeRead<E> + BitSeek,
138138
{
139139
if args.check {
140-
let graph = BVGraph::with_basename(&args.basename)
141-
.endianness::<E>()
142-
.load()?;
140+
let graph = BVGraph::with_basename(&args.src).endianness::<E>().load()?;
143141

144-
let seq_graph = BVGraphSeq::with_basename(&args.basename)
142+
let seq_graph = BVGraphSeq::with_basename(&args.src)
145143
.endianness::<E>()
146144
.load()?;
147145

@@ -155,7 +153,7 @@ where
155153
assert_eq!(succ.collect_vec(), seq_succ.collect_vec());
156154
}];
157155
} else if args.degrees {
158-
let seq_graph = BVGraphSeq::with_basename(&args.basename)
156+
let seq_graph = BVGraphSeq::with_basename(&args.src)
159157
.endianness::<E>()
160158
.load()?;
161159

@@ -181,7 +179,7 @@ where
181179
) {
182180
(Some(samples), true) => {
183181
bench_random(
184-
BVGraph::with_basename(&args.basename)
182+
BVGraph::with_basename(&args.src)
185183
.endianness::<E>()
186184
.dispatch::<Dynamic>()
187185
.mode::<Mmap>()
@@ -194,7 +192,7 @@ where
194192
}
195193
(Some(samples), false) => {
196194
bench_random(
197-
BVGraph::with_basename(&args.basename)
195+
BVGraph::with_basename(&args.src)
198196
.endianness::<E>()
199197
.dispatch::<Static>()
200198
.mode::<Mmap>()
@@ -207,7 +205,7 @@ where
207205
}
208206
(None, true) => {
209207
bench_seq(
210-
BVGraphSeq::with_basename(&args.basename)
208+
BVGraphSeq::with_basename(&args.src)
211209
.endianness::<E>()
212210
.dispatch::<Dynamic>()
213211
.mode::<Mmap>()
@@ -218,7 +216,7 @@ where
218216
}
219217
(None, false) => {
220218
bench_seq(
221-
BVGraphSeq::with_basename(&args.basename)
219+
BVGraphSeq::with_basename(&args.src)
222220
.endianness::<E>()
223221
.dispatch::<Static>()
224222
.mode::<Mmap>()

src/cli/build/dcf.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub const COMMAND_NAME: &str = "dcf";
2323
#[command(about = "Builds an Elias–Fano representation of the degree cumulative function of a graph.", long_about = None)]
2424
pub struct CliArgs {
2525
/// The basename of the graph.
26-
pub basename: PathBuf,
26+
pub src: PathBuf,
2727
}
2828

2929
pub fn cli(command: Command) -> Command {
@@ -33,7 +33,7 @@ pub fn cli(command: Command) -> Command {
3333
pub fn main(submatches: &ArgMatches) -> Result<()> {
3434
let args = CliArgs::from_arg_matches(submatches)?;
3535

36-
match get_endianness(&args.basename)?.as_str() {
36+
match get_endianness(&args.src)?.as_str() {
3737
#[cfg(any(
3838
feature = "be_bins",
3939
not(any(feature = "be_bins", feature = "le_bins"))
@@ -52,7 +52,7 @@ pub fn build_dcf<E: Endianness + 'static>(args: CliArgs) -> Result<()>
5252
where
5353
for<'a> BufBitReader<E, MemWordReader<u32, &'a [u32]>>: CodeRead<E> + BitSeek,
5454
{
55-
let basename = args.basename;
55+
let basename = args.src;
5656
let properties_path = basename.with_extension(PROPERTIES_EXTENSION);
5757
let f = File::open(&properties_path).with_context(|| {
5858
format!(

src/cli/build/ef.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub const COMMAND_NAME: &str = "ef";
2323
#[command(about = "Builds the .ef file for a graph.", long_about = None)]
2424
pub struct CliArgs {
2525
/// The basename of the graph.
26-
pub basename: PathBuf,
26+
pub src: PathBuf,
2727
/// The number of elements to be inserted in the Elias-Fano
2828
/// starting from a label offset file. It is usually one more than
2929
/// the number of nodes in the graph.
@@ -37,7 +37,7 @@ pub fn cli(command: Command) -> Command {
3737
pub fn main(submatches: &ArgMatches) -> Result<()> {
3838
let args = CliArgs::from_arg_matches(submatches)?;
3939

40-
match get_endianness(&args.basename)?.as_str() {
40+
match get_endianness(&args.src)?.as_str() {
4141
#[cfg(any(
4242
feature = "be_bins",
4343
not(any(feature = "be_bins", feature = "le_bins"))
@@ -56,7 +56,7 @@ pub fn build_eliasfano<E: Endianness + 'static>(args: CliArgs) -> Result<()>
5656
where
5757
for<'a> BufBitReader<E, MemWordReader<u32, &'a [u32]>>: CodeRead<E> + BitSeek,
5858
{
59-
let basename = args.basename;
59+
let basename = args.src;
6060
if let Some(num_nodes) = args.n {
6161
// Horribly temporary duplicated code for the case of label offsets.
6262
let of_file_path = basename.with_extension(LABELOFFSETS_EXTENSION);

src/cli/build/offsets.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ pub const COMMAND_NAME: &str = "offsets";
2323

2424
pub struct CliArgs {
2525
/// The basename of the graph.
26-
pub basename: PathBuf,
26+
pub src: PathBuf,
2727
}
2828

2929
pub fn cli(command: Command) -> Command {
@@ -33,7 +33,7 @@ pub fn cli(command: Command) -> Command {
3333
pub fn main(submatches: &ArgMatches) -> Result<()> {
3434
let args = CliArgs::from_arg_matches(submatches)?;
3535

36-
match get_endianness(&args.basename)?.as_str() {
36+
match get_endianness(&args.src)?.as_str() {
3737
#[cfg(any(
3838
feature = "be_bins",
3939
not(any(feature = "be_bins", feature = "le_bins"))
@@ -54,10 +54,10 @@ where
5454
for<'a> BufBitReader<E, WordAdapter<u32, BufReader<File>>>: CodeRead<E> + BitSeek,
5555
{
5656
// Create the sequential iterator over the graph
57-
let seq_graph = BVGraphSeq::with_basename(&args.basename)
57+
let seq_graph = BVGraphSeq::with_basename(&args.src)
5858
.endianness::<E>()
5959
.load()?;
60-
let offsets = args.basename.with_extension(OFFSETS_EXTENSION);
60+
let offsets = args.src.with_extension(OFFSETS_EXTENSION);
6161
let file = std::fs::File::create(&offsets)
6262
.with_context(|| format!("Could not create {}", offsets.display()))?;
6363
// create a bit writer on the file

src/cli/check_ef.rs renamed to src/cli/check/ef.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub const COMMAND_NAME: &str = "check-ef";
2626
#[command(about = "Check that the '.ef' file (and `.offsets` if present) is coherent with the graph.", long_about = None)]
2727
pub struct CliArgs {
2828
/// The basename of the graph.
29-
basename: PathBuf,
29+
pub src: PathBuf,
3030
}
3131

3232
pub fn cli(command: Command) -> Command {
@@ -38,7 +38,7 @@ pub fn main(submatches: &ArgMatches) -> Result<()> {
3838
}
3939

4040
pub fn check_ef(args: CliArgs) -> Result<()> {
41-
let properties_path = args.basename.with_extension(PROPERTIES_EXTENSION);
41+
let properties_path = args.src.with_extension(PROPERTIES_EXTENSION);
4242
let f = File::open(&properties_path).with_context(|| {
4343
format!(
4444
"Could not load properties file: {}",
@@ -49,9 +49,9 @@ pub fn check_ef(args: CliArgs) -> Result<()> {
4949
let num_nodes = map.get("nodes").unwrap().parse::<usize>()?;
5050

5151
// Create the offsets file
52-
let of_file_path = args.basename.with_extension(OFFSETS_EXTENSION);
52+
let of_file_path = args.src.with_extension(OFFSETS_EXTENSION);
5353

54-
let ef = EF::mmap(args.basename.with_extension(EF_EXTENSION), Flags::default())?;
54+
let ef = EF::mmap(args.src.with_extension(EF_EXTENSION), Flags::default())?;
5555

5656
let mut pl = ProgressLogger::default();
5757
pl.display_memory(true)
@@ -85,7 +85,7 @@ pub fn check_ef(args: CliArgs) -> Result<()> {
8585
.expected_updates(Some(num_nodes));
8686

8787
info!("The offsets file does not exists, reading the graph to build Elias-Fano");
88-
let seq_graph = crate::graphs::bvgraph::sequential::BVGraphSeq::with_basename(&args.basename)
88+
let seq_graph = crate::graphs::bvgraph::sequential::BVGraphSeq::with_basename(&args.src)
8989
.endianness::<BE>()
9090
.load()?;
9191
// otherwise directly read the graph

src/cli/check/mod.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2024 Tommaso Fontana
3+
*
4+
* SPDX-License-Identifier: Apache-2.0 OR LGPL-2.1-or-later
5+
*/
6+
7+
use anyhow::Result;
8+
use clap::{ArgMatches, Command};
9+
10+
pub mod ef;
11+
12+
pub const COMMAND_NAME: &str = "check";
13+
14+
pub fn cli(command: Command) -> Command {
15+
let sub_command = Command::new(COMMAND_NAME)
16+
.about("Check coherence of files.")
17+
.subcommand_required(true)
18+
.arg_required_else_help(true)
19+
.allow_external_subcommands(true);
20+
let sub_command = ef::cli(sub_command);
21+
command.subcommand(sub_command)
22+
}
23+
24+
pub fn main(submatches: &ArgMatches) -> Result<()> {
25+
match submatches.subcommand() {
26+
Some((ef::COMMAND_NAME, sub_m)) => ef::main(sub_m),
27+
Some((command_name, _)) => {
28+
eprintln!("Unknown command: {:?}", command_name);
29+
std::process::exit(1);
30+
}
31+
None => {
32+
eprintln!("No command given for check");
33+
std::process::exit(1);
34+
}
35+
}
36+
}

0 commit comments

Comments
 (0)