use crate::candidate_selection::HashingStrategy;
use crate::ui::FromByteUnit;
use anyhow::{anyhow, Context, Result};
use clap::ArgMatches;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum AnalysisMode {
HashOnly,
Exact,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum LinkSelectionPreference {
Oldest,
Newest,
#[allow(dead_code)]
LinkEffort,
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Format {
JSON,
CSV,
}
#[derive(Copy, Clone, Debug)]
pub struct Options {
pub analysis_mode: AnalysisMode,
pub hashing_strategy: HashingStrategy,
pub block_size: u64,
pub initial_block_size: u64,
pub thread_count: usize,
pub min_size: u64,
pub max_size: Option<u64>,
pub debug: bool,
pub no_progress: bool,
pub error_on_duplicate: bool,
pub format: Format,
pub force: bool,
pub dry_run: bool,
pub link_priority: LinkSelectionPreference,
}
impl Options {
pub fn from_matches(matches: ArgMatches) -> Result<Self> {
let res = Options {
debug: matches.is_present("debug"),
no_progress: matches.is_present("hide-progress"),
analysis_mode: if matches.is_present("estimate") {
AnalysisMode::HashOnly
} else {
AnalysisMode::Exact
},
hashing_strategy: if matches.is_present("no-sampling") {
HashingStrategy::Complete
} else {
HashingStrategy::Sampling
},
block_size: matches
.value_of("buffer-size")
.map(u64::from_str_byte_unit)
.transpose()
.context("Failed to parse --buffer-size argument")?
.unwrap_or(16384),
initial_block_size: matches
.value_of("start-size")
.map(u64::from_str_byte_unit)
.transpose()
.context("Failed to parse --start-size argument")?
.unwrap_or(10),
thread_count: std::cmp::max(
matches
.value_of("threads")
.map(|n| usize::from_str_radix(n, 10))
.transpose()
.context("Failed to parse number of threads")?
.map(|n| {
if n > 0 {
Ok(n)
} else {
Err(anyhow!("Number of threads must be positive."))
}
})
.transpose()?
.unwrap_or_else(|| num_cpus::get() * 2),
1,
),
error_on_duplicate: matches.is_present("error-on-duplicate"),
min_size: matches
.value_of("min-size")
.map(u64::from_str_byte_unit)
.transpose()
.context("Failed to parse --min-size argument")?
.map(|n| {
if n > 0 {
Ok(n)
} else {
Err(anyhow!("Minimal file size must be positive."))
}
})
.transpose()?
.unwrap_or(1),
max_size: matches
.value_of("max-size")
.map(u64::from_str_byte_unit)
.transpose()
.context("Failed to parse --max-size argument")?,
format: matches
.value_of("output-format")
.map(|n| match n {
"json" => Ok(Format::JSON),
"csv" => Ok(Format::CSV),
_ => Err(anyhow!("Unsupported output format {}", n)),
})
.transpose()?
.unwrap_or(Format::CSV),
force: matches.is_present("force"),
dry_run: matches.is_present("dry-run"),
link_priority: matches
.value_of("prefer")
.map(|n| match n {
"oldest" => Ok(LinkSelectionPreference::Oldest),
"newest" => Ok(LinkSelectionPreference::Newest),
_ => Err(anyhow!("Unsupported link preference {}", n)),
})
.transpose()?
.unwrap_or(LinkSelectionPreference::Oldest),
};
Ok(res)
}
}